嵌入式系统课程设计基于μCOSII的电子词典设计与实现_第1页
嵌入式系统课程设计基于μCOSII的电子词典设计与实现_第2页
嵌入式系统课程设计基于μCOSII的电子词典设计与实现_第3页
嵌入式系统课程设计基于μCOSII的电子词典设计与实现_第4页
嵌入式系统课程设计基于μCOSII的电子词典设计与实现_第5页
已阅读5页,还剩32页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目录1系统定义与需求分析31.1系统定义31.1.1任务功能描述31.1.2 任务的优先级分配41.1.3 任务间同步与通信的规则41.2 系统配置42详细设计62.1 系统移植62.1.1移植os_cpu.h62.1.2 移植os_cpu_c.c72.2 最小系统的运行调试102.2.1 保证编译正确,系统启动正确112.2.2调试os_enter_critical()112.2.3 调试osstarthighrdy()122.2.4 调试osctxsw()122.2.5 调节时钟节拍132.2.6 调试osintctxsw()和ostickisr()143 驱动程序的设计与调试153.1

2、基于c/os-ii的中断设计153.2 基于c/os-ii的设备驱动程序设计153.3 基于c/os-ii的设备驱动程序测试164 系统集成与功能测试174.1 初始化任务174.2 键盘处理任务184.3 触摸屏处理任务234.4 系统集成测试355参考文献381系统定义与需求分析1.1系统定义电子词典是一个典型的由外部输入驱动的开环系统,由键盘或触摸屏输入信息,处理器根据输入的信息在lcd显示屏上显示相应的内容,显示完成之后系统进入空闲状态等待下一次输入。根据这一处理过程,讲电子词典应用分为3个主任务主执行任务,键盘任务,触摸屏任务。系统的总体设计如图1-1所示。main()函数初始化任务

3、键盘任务主执行任务触摸屏任务光标任务键盘isr触摸屏isr时钟节拍 图1-1 c/os-ii系统总是从main()函数开始,通常在main()函数中指创建一个用户任务,即初始化任务,这样设计有利于系统管理,而且结构也会更清晰。在初始化任务中启动时钟节拍,创建各个任务以及要用到的信号量或消息。1.1.1任务功能描述在电子词典设计中,键盘任务和触摸屏任务负责采集输入信号,并将其转换为键值告知主处理任务。主处理任务负责根据读到的键值启动相应功能。而光标任务则是用来展现时钟节拍,让目标板上的led灯以指定的时间间隔进行闪烁。1.1.2 任务的优先级分配系统中的优先级分配按照最经常发生的优先级最高这一原

4、则进行,具体分配如下:优先级03:分配优先级时将最高的4个优先级留给系统用户;优先级5:主处理任务优先级最高为5级;优先级6:键盘的使用概率大于触摸屏,其优先级定为6级;优先级7:触摸屏的优先级为7级;优先级8:光标每隔一个固定的时间闪烁一次,这个时间可以由用户自定义,优先级为8级;最低优先级-1:系统统计任务(可选);最低优先级:系统空闲任务。1.1.3 任务间同步与通信的规则需要传递消息的任务是键盘与主执行任务。触摸屏与主执行任务之间传递的都是按键值,且键值不用区分来源,所以使用一个消息邮箱即可。由于任务间不存在共享互斥资源的问题,所以不需要进行任务间的同步。键盘与触摸屏都是由外界时间触发

5、的,可以使用中断机制设计驱动程序。在驱动程序的设计中,遵循中断中处理的时间尽量短,讲更多的事情交给任务区完成这一原则。1.2 系统配置c/os-ii并不提供列斯linux那样的命令行形式的配置方法,而是通过对配置的内容进行条件编译来实现的。这是由于c/os-ii提供开放的源代码,用户可以直接使用#define constants语句来更改内核的很多参数。系统中提供了以下配置项:事件标志:包括使能或禁止事件标志及其相关功能,通常以os_flag_为前缀;消息邮箱:包括使能或禁止消息邮箱及其相关功能,通常以os_mbox_为前缀;内存管理:包括使能或禁止内存管理及其相关功能,目前版本中只有两个可配

6、置项os_mem_en和os_mem_query_en;互斥型信号量:包括使能或禁止互斥型信号量及其相关功能,通常以os_mutex_为前缀;消息队列:包括使能或禁止消息队列及其相关功能,通常以os_q_为前缀;信号量:包括使能或禁止信号量及其相关功能,通常以os_sem_为前缀;任务管理:系统提供两个任务创建函数,在配置文件中至少要对其中一个进行使能,另外还包括一些对任务其他相关属性的配置,通常以os_task_为前缀;时钟管理:c/os-ii中用户可以使用操作系统的时钟作为演示的基准,这里包括使能或禁止使用系统时钟及其相关功能,通常以os_time_为前缀;杂项:包括配置任务,事件,消息队

7、列的最大个数,任务堆栈的容量等。c/os-ii内核默认的是将系统配置为最大系统,即使能所有功能,并且将认为尿素时间按等设置为最大。在电子词典的应用中,只有13个任务(5个用户任务,8个系统预留任务)、两个事件标志、一个消息邮箱,所以需要对默认系统进行重新配置。需要更改的主要参数如下:os_max_events:最大可申请的事件控制块数。系统中每个消息和信号量都需要一个事件控制块。电子词典中只用到一个消息邮箱,该值大于1即可。为了便于本系统扩展,将其设为5。os_max_flags:最大可申请的事件标志数。当前使用了俩各个事件标志,该值大于2即可。为了便于本系统扩展将其设为5。os_max_ta

8、sks:最大可申请的用户任务书。电子词典中共定义了5个用户任务,该值大于5即可。为了便于本系统扩展将其设为10。os_lowest_prio:系统可分配的最低优先级。系统根据该参数初始化任务控制块,所以这个参数会影响系统对ram的占用 。电子词典将此参数定义为15,其中5个用户任务、8个系统任务、2个余量任务。各个功能的使能/禁止参数通常以_en为后缀,1为使能,0为禁止。在电子词典中要使能消息邮箱(os_mbox_en)和信号量(os_sem_en),将其对应的参数设为1,其余使能参数设为0,其他参数均使用默认值即可。2详细设计2.1 系统移植在移植c/os-ii之前,要确保目标系统(主要是

9、处理器及其编译环境)满足如下要求:(1) 目标系统所使用的编译环境要包括标准的c交叉编译器。(2) 目标系统所使用的c编译器支持在c程序中对中断进行操作。(3) 处理器必须可以产生定时器中断。(4) 处理器必须可容纳一定数据存储硬件堆栈。(5) 处理器中的寄存器与内存之间可以相互读/写。2.1.1移植os_cpu.h在os_cpu.h里主要包括与处理器有关的数据类型、常量以及宏的定义。定义常量so_stk_growth。这个常量表示了栈的增长方向。1为向上递减,栈底高地址入栈时指针减,出栈时指针加;0为向下递增,栈底低地入栈时指针加,出栈时减。定义宏os_enter_critical()和os

10、_exit_critical()。这两个宏是用来打开和关闭中断的。当c/os-ii需要处理不能被中断打断的段时,就要用到这两个宏对其进行保护。由于不同的处理器对中断的操作不尽相同,所以在这里对这两个操作进行定义。关中断宏代码如下:#define os_enter_critical() _ _asmbl armdisableint 开中断宏代码如下:#define os_exit_critical() _ _asmbl armenableint 具体功能在os_cpu_a.s实现,代码如下:armdisableintmrsr0,cpsrstmfd sp!,r0 ;保存当前处理器状态orrr0,r

11、0,#0x80msrcpsr_c,r0 ;禁止中断movpc,lrarmenableintldmfdsp!,r0 ;从栈中弹出处理器的状态值msrcpsr_c,r0 ;恢复原始的处理器状态movpc,lr2.1.2 移植os_cpu_c.cos_cpu_c.c包括10个简单的c函数。与移植相关的只有ostaskstkinit()函数,该函数负责对任务栈进行初始化。另外9个都是对各种任务进行扩展时用的,虽然必须定义,但可以不用包含任何代码。这10个函数分别是:ostaskstkinit()、ostaskcreatehook()、ostaskdelhook()、ostaskswhook()、ost

12、askidlehook()、ostaskstathook()、ostimetickhook()、osinithookbegin()、osinithookend()和ostcbinithook()。ostaskstkinit()函数在创建任务时被ostaskcreate()或ostaskcreateexit()调用,以初始化任务栈结构,将所有的寄存器像刚发生中断一样保存在栈里。虽然arm对栈的方向并没有特殊要求,但是由于ads编译器仅支持满减栈fd(full descending),即高地址为栈底,入栈时指针减1,栈指针指向最后一个入栈的数据元素,所以需要在os_cpu.h中将任务栈定义为减栈:

13、#define os_stk_growth 1/*内存中栈的增长方向为从高到低*/其实际结构如图2-1所示。pdata是在人物创建时传递给任务的一个参数。代码如下:os_stk*ostaskstkinit(viod(*task)(void*pd),void*pdata,os_stk*ptos,int16u opt)unsigned int * stk;opt=opt; stk=(unsigned int *)ptos; /*当前栈指针*/*对新任务建立上下文环境*/*_ _stk=(unsigned int) task; /* pc*/*_ _stk=(unsigned int) task;

14、/* lr*/*_ _stk=0; /* r12*/*_ _stk=0; /* r11*/*_ _stk=0; /* r10*/*_ _stk=0; /* r9*/*_ _stk=0; /* r8*/*_ _stk=0; /* r7*/*_ _stk=0; /* r6*/*_ _stk=0; /* r5*/*_ _stk=0; /* r4*/*_ _stk=0; /* r3*/*_ _stk=0; /* r2*/*_ _stk=0;/* r1*/*_ _stk=(unsigned int)pdata;/* r0*/*_ _stk=(svc32mode|0x0;/* 禁用cpsr中的irq,fi

15、q*/*_ _stk=(svc32mode|0x0);/* 禁用spsr中的irq,fiq*/return(void*)stk;c/os-iic/os-ii中有4个与处理器相关的函数要用汇编语言实现,这4个函数分别是:oostarthighrdy( )、osctxsw( )、osintctxsw( )和ostickisr( )。oostarthighrdy( )oostarthighrdy( )仅在osstart()函数中被调用。具体实现代码如下: osstarthighrdybl ostaskswhookldrr4,=osrunningmovr5,#1strbr5,r4ldrr4,=osrc

16、bhighrdyldrr4,r4ldrsp,r4ldmfdsp!,r4msrspsr_c,r4ldmfdsp!,r4msr cpsr_c,r4ldmedsp!,r0-r12,lr,pc这段代码中ostaskswhook()在文件os_cpu_c.c中定义,通过它用户可以扩展任务切换代码的功能。osctxsw( )osctxsw( )用来实现任务级的任务切换。具体实现代码如下: osctxswstmfdsp!,lrstmfdsp!,r0-r12,lrmrsr4,cpsrstmfdsp!,r4mrsr4,spsrstmfdsp!,r4_osctxswbl ostaskswhookldrr4,=os

17、priocurldrr5,=ospriohighrdyldrbr6,r5strbr6,r4ldrr4,=ostcbcurldrr5,r4strsp,r5ldrr6,= ospriohighrdyldrr6,r6ldrsp,r6strr6,r4ldmfdsp!,r4msrspsr_cxsf,r4ldmfdsp!,r4msrcpsr_cxsf,r4ldmfdsp!,r0-r12,lr,pcosintctxsw( )osintctxsw( )由osintexit( )调用,在isr中实现任务切换功能。通常使用如下形式的代码实现中断级的任务切换: osintctxswldrr0,=osintctxsw

18、flagmovr1,#1strr1,r0movpc,lr以上这段代码值设置了一个用以表示是否需要进行任务切换的标志osintctxswflag,在中断后的第一个时钟节拍内对此标志进行判断,根据判断结果决定是都需要进行中断级任务切换。ostixkisr( )ostixkisr( )时钟节拍中断的isr。在之前提到过的c/os-ii要求用户提供一个称为时钟节拍的定时中断,以实现延时与超时控制等功能。这个中断频率一般是10100hz。具体实现代码如下:nointequ0xc0i_ispcequ0x1e00024timer0equ0x1ostickisrstmfdsp!,r0-r3,r12,lrblo

19、sintenterldrr0,=i_ispcmovr2,#timer0ldrr1,r0orrr1,r1,r2,lsl #13strr1,r0blostimetickblosintexitldrr0,=osintctxswflagldrr1,r0cmpr1,#1beq_intctxswidmfdsp!,r0-r3,r12,lrsubspc,lr,#4/*-以下代码用于任务切换-*/_intctxswldrr0,=osintctxswflagmovr1,#0str r1,r0idmfdsp!,r0-r3,r12,lrstmfdsp!,r0-r3movr1,spaddspsubr2,lr,#4mrs

20、r3,spsrorrr0,r3,#nointmsrspsr_c,r0idrr0,=.+8movspc,r0stmfdsp!,r2stmfdsp!,r4-r12,lrmovr4,r1movr5,r3idmfdr4!,r0-r3stmfdsp!,r0-r3stmfdsp!,r5mrsr4,spsrstmfdsp!,r4b_osctxsw2.2 最小系统的运行调试最小系统主要是指如处理器、存储器这些最基本的元素所组成的可运行的最小系统,在增加了操作系统之后,可以认为最小系统等于硬件最小能运行系统加上可运行的操作系统内核。只有当最小系统运行起来以后,才能进一步开发应用程序。系统测试的过程要与系统运行过

21、程一致。系统上电后调用的启动程序对处理器以及存储器这些硬件进行初始化,初始化完成之后跳转至main()函数,在此之前的工作基本与c/os-ii内核无关,所以对内核的测试从main()函数开始。在main()函数中系统调用osinit()初始化c/os-ii中所有的变量和数据结构,为了使测试更加简单,可以在系统配置中禁止系统 统计任务(#define os_task_stat_en 0)。于是,系统在初始化时至创建一个空闲任务,并将其优先级设置为最低,让其永远处于就绪状态。测试之前建立的main()函数代码如下:void main(void)target_init();osinit();osta

22、skcreate(starttask,(void*)0,&starttaskstktasksize-1,pro);osstart();代码含义如下:初始化目标板上载调试时要用到的基本硬件,如led;调用osinit(),初始化c/os-ii系统内核;创建一个用户任务,用来测试多任务调度是否成功;调用osstart(),开始多任务调度。这里用到的与系统相关的函数有osinit()、ostaskcreate()、osstart(),只要这3个函数运行正常系统就算移植成功。下面开始测试代码。2.2.1 保证编译正确,系统启动正确从最简单的开始 ,这一步只要保证代码没有语法错误并且系统可正确启动即可。

23、将main()函数进行如下改动:#include”includes.h”void main(void)target_init( );led_on( );在ads下编译并运行这段代码。如果指示灯被成功点亮,就说明没有语法问题,而且硬件也已经启动完成了。这是一段用来验证是否存在语法错误并且编译、链接器以及汇编器是否配置正确的代码。2.2.2调试os_enter_critical()讲之前的测试程序进行如下更改,在之前的main()函数中加入osinit()函数,即#include”includes.h”void main(void)target_init( );osinit( );led_on(

24、);系统函数osinit()用于初始化c/os-ii系统,使用系统函数osinit()时不需要输入参数,直接调用即可。osinit()函数设计的移植代码包括os_enter_critical( )、os_exit_critical()、ostaskstkinit()。在ads下编译完成,启动axd进行调试。以上3个函数都是在osinit()内部创建系统空闲任务时被调用的。对这些函数分别使用单步雕饰的发那个发,观察寄存器中的值是否与设计一致。2.2.3 调试osstarthighrdy()在之前的main()函数中加入osstart()函数,即#include”includes.h”void m

25、ain(void)target_init( );osinit( );led_on( );osstart( );系统函数osstart()用于启动多任务,使用时不需要输入参数,直接调用即可。进入调试器开始调试,执行main()函数。如果移植正确,程序会从osstarthighrdy()运行至os_taskidle()。整个运行过程中需要关注的是移植中重写的函数osstarthighrdy()。这里可以通过调试器观察是否将优先级最高的任务控制块交付给当前处理器,也就是os_taskidle( )任务,并且将新任务的所有寄存器按与入栈相反的顺序出栈。如果这里出现问题那么栈指针就会出错,这是就要对os

26、starthighrdy()进行修改。从osstarthighrdy()中返回时应该直接跳转至os_taskidle(),如果没有这样,那么有可能是在初始化时系统调用的ostaskstkinit()没能正确创建任务堆栈,这是只要检查并改正就可以 。在ostaskidlehook()将指示灯的状态取反,并在其后加上适当延时。具体如下:void ostaskidlehook(void)led_turn( );delay(10);这样如果指示灯能够闪烁,那么就说明系统运行正常,osstarthighrdy()的移植是成功的。2.2.4 调试osctxsw()通过上面几步可知ostaskstkinit

27、()对任务栈的初始化操作是正确的,下来就可以创建一个用户任务,并且通过osctxsw()使其被切换至os_taskidle(),以此验证osctxsw()正确与否。首先更改主程序,即#include”include.h”os_stk taskstk100;void main(void)char idl=1;osinit( );led_on( );ostaskcreate(starttask,&idl,&taskstk99,4);osstart( ); void starttask(void* pdata)pdata=pdata;while(1)led_off( );ostimedly(1);系

28、统函数ostaskcreate()用于创建用户任务,有4个输入参数,它们分别是:第1个参数:task指向任务代码的指针,即在定义任务时使用的任务名;第2个参数:pdata任务开始时传递给任务的参数指针;第3个参数:ptos分配给任务栈的栈顶指针,任务栈需要提前声明为os_stk类型的数组,这里的任务栈是容量为100的减栈。第4个参数:prio任务优先级,任务就是在这里获得最初优先级。系统函数ostimedly()用于系统延时时,有一个输入参数,int16u类型的ticks,用以表示要延时多少个时钟节拍后再重新返回该任务。但是由于此时还没有启动时钟节拍,所以系统无法从os_taskidle(0中

29、返回到startask()任务。编译通过即可调试运行,同第3步一样单步运行osstart()会发现,程序会跳转至新建立的任务,这是因为新建立的任务优先级高于os_taskidle();继续单步运行starttask()至ostimedly(1),系统在ostimedly()的最后调用了任务调度器os_sched(),在调度器的最后用osctxsw()实现了任务级的任务切换;单步执行至osctxsw(),在osctxsw()中可以看到当前任务starttask()中所有寄存器已经保存到它自己的任务栈中,os_taskidle()任务栈中的寄存器则被调入当前处理器,从osctxsw()返回到so_

30、taskidle()。如果没能运行到os_taskidle(),则需在osctxsw(0中查找原因并改正错误。当全速欲行程序时,如果结果正确则可以看到指示灯先闪灭一次,然后开始以一个固定的频率闪动。2.2.5 调节时钟节拍由前面可知,任务栈的建立和初始化,以及任务级的任务调度都是正确的,还剩下系统时钟ostickisr()和中断级任务调度osintctxsw()这两个移植项需要测试。在测试这两个函数之前,首先要保证系统的时钟节拍(定时器中断)是否可以正常运行,对starttask()任务进行如下改正:void starttask(void*pdata)pdata=pdata;timer_ini

31、t( );while(1);将ostimetick()中调用的ostimetickhook()更改如下:void ostimetickhook(void)led_turn( );编译通过后开始调试,全速运行。如果看到指示灯闪烁说明时钟节拍没有问题,否则要对ostickisr()进行单步调试。2.2.6 调试osintctxsw()和ostickisr()首先删除ostimetickhook()和ostaskidlehook()中对指示灯的操作。其次对starttask()任务进行如下更改:void starttask(void*pdata)pdata = pdata;timer_init( )

32、;for(;)ostimedly(1);编译通过后可以开始调试。如果osintctxsw()移植正确,全速运行指示灯闪烁,并且闪烁频率与ostimedly(x)中的x成正比关系。否则就要针对osintctxsw()移植代码进行调试更改。调试时仍用外部中断代替定时器中断。至此所有与移植相关的文件都已经调试完成,移植的c/os-ii意见可以正常工作,下面将在这个移植好的操作系统上,重新实现之前的电子词典应用实例。3 驱动程序的设计与调试3.1 基于c/os-ii的中断设计中断使得处理器可以在事件发生时才予以处理,而不必连续不断地查询是否有事件发生,所以是设计驱动时一个很重要的方法。在实时环境中,关

33、中断的事件应尽量短。关中断影响中断响应时间,关中断时间太长可能会引起中断丢失。中断服务的处理时间应该尽可能短,中断服务所做的事情应该尽可能少,应该把大部分工作留给任务去做。c/os-ii系统内核通过特殊函数os_enter_critical( )和os_exit_critical( )来开/关中断,让用户决定什么情况下需要响应中断,什么情况下不需要。本设计中涉及到的中断分为两大类:定时器中断和用户中断。定时器中断:它作为系统的时钟节拍为系统提供特定的周期性中断,是系统任务调度的基础。使得系统内核可以将任务延时若干个时钟节拍,以及当任务要求等待时提供超时依据。用户中断:键盘中断以及触摸屏中断。所

34、有基于c/os-ii的isr需要调用osintenter()和osintexit()使内核进入/退出中断处理状态。3.2 基于c/os-ii的设备驱动程序设计将硬件分为主动式硬件和被动式硬件两类。主动式硬件指可以接受外部信息要求软件作出响应的软件,如本系统的键盘和触摸屏。主动式硬件驱动设计可分为初始化、中断服务以及请求处理3类。在中断服务中使用信号量通知任务有事情发生,根据信号量的不同启动相应的任务,在该任务中对发出信号的硬件进行处理。因此,在初始化具体硬件时需要创建用于通知系统的信号量。下面是相应代码:os_event *f_key;os_event *f_touch;os_event *k

35、ey_value;void device_drever_init(void)int8u err;f_key=ossemcreate(0);f_touch=ossemcreate(0);key_value=osmboxcreate(void*)0);gui_init( );keyboard_init( );touchscreen_init( );系统函数ossemcreate()用于创建信号量,只有一个int16u型的参数cnt用于表示该信号量的初始计数值,范围是065535。信号量f_key和f_touch,分别用于表示键盘和触摸屏。这两个信号量都是用于表示有一个硬件输入时间按发生所以在创建时

36、将cnt的初始值赋为0。系统函数osmboxcreate()用于创建消息邮箱,唯一的输入参数msg是一个可以指向任意类型值的指针,这个指针所指向的就是邮箱的内容。在调用此函数创建邮箱时必须定义指针的初始值。通常用null将这个邮箱初始化为空,也可以在初始化时就给邮箱中放入消息。该函数返回一个指向事件控制块ebc的指针,相当于这个邮箱的名字。触摸屏中断服务代码如下:void_ _irq touchscreen_int (void)osintenter( );rintmsk|=bit_eint0;ri_ispc=bit_einto;ossempost(f_touch);osintexit( );3

37、.3 基于c/os-ii的设备驱动程序测试在开始设计任务之前,可借鉴调试最小系统的方法对完成的设备驱动进行测试,测试仍遵循由简到繁的原则,先测试被动式硬件,再测试主动式硬件。将做好的驱动代码加入之前的测试工程,在创建的starttask中加入要测试硬件的初始化代码。代码在pc机上启动串口调试工具,设置参数。编译并运行测试代码,如果测试成功则会通过串口每隔一个固定时间间隔打印一条提示信息。在timer_init( )内将时钟节拍设置为100hz,ostimedly(100)就会使starttask任务每秒启动一次,则打印的时间间隔应该大约是1s。测试主动式硬件与此过程稍有不同,需要在任务中等待系

38、统发来的相应信号,以键盘为例,仍然使用starttask任务,代码如下:代码系统函数ossempend用于等待信号量。有3个输入参数分别是:第1个参数为指向要等待的信号量对应的事件控制块的指针;第2个参数为int16u类型的timeout,代表等待超时的时间,以时钟节拍为单位,如果设置为0,表示无限期等待;第3特参数认为返回的err错误状态。4 系统集成与功能测试4.1 初始化任务系统初始化任务通常在main()函数中创建,分配的优先级可以是允许的优先级中的任意一个,因为初始化任务通常只运行一次,运行完成后可以将其删除,不会对其他任务优先级分配造成影响。在main()函数中要对目标板上的基本硬

39、件做初始化工作,如串口的初始化、中断控制的初始化、s3c44b0x内部缓存的初始化等。main()函数的代码如下:void main(void)char idl=1;target_init( );uart_printf(0,”*=start test=*n);osinit( );ostaskcreate(inittask,&idl,&taskstk1taskstacksize-1,4);osstart( );硬件初始化:如lcd、键盘和触摸屏。软件初始化:创建所需的信号量、事件标志组、消息邮箱、消息队列中的一个或多个;创建用户任务,但可以不是所有的任务,根据系统的需要而定。由于初始化任务并不需

40、要重复进行,所以在最后调用ostaskdel(so_prio_self)将其自身删除即可。其代码如下:/定义每个任务所要用到的栈os_stktaskstk1taskstacksize;os_stktaskstk2mintaskstacksize;os_stktaskstk3maxtaskstacksize;os_stktaskstk4taskstacksize;os_stktaskstk5taskstacksize;void inittask(void* pdata)char id2=2;char id3=3;char id4=4;char id5=5;ostaskcreate(coursor

41、task,&id2,&taskstk2mintaskstacksize-1,7); ostaskcreate(executtask,&id5,&taskstk3maxtaskstacksize-1,8);ostaskcreate(kbrecievetask,&id4,&taskstk4 taskstacksize-1,9);ostaskcreate(adconvertask,&id3,&taskstk5 taskstacksize-1,6);target_start( );ostaskdel(os_prio_self); 4.2 键盘处理任务对键盘的处理首先需要能对键盘动作做出响应,因此键盘处

42、理函数必须能够响应键盘中断,并通过系统总线读取键盘相应信息,并将其打印出来。代码如下:/键盘测试函数:void keyboard_test(void)int i, j, k;uint8t ucchar, t;iic_init();/ set eint2 interrupt handler pisr_eint2 = (int)keyboard_int;for(;) f_nkeypress = 0;rintmsk = rintmsk & (bit_global|bit_eint2);/ enable eint2 intwhile(f_nkeypress = 0);iic_read(0x70, 0x

43、1, &ucchar);if(ucchar !=0)ucchar = key_set(ucchar);if(ucchar 10) ucchar += 0x30;else if(ucchar 16) ucchar += 0x37;if(ucchar 255)uart_printf(press key %cn, ucchar);if(ucchar = 0xff)uart_printf( press key fun (exit now)nr);return; while(1);其中f_nkeypress为全局变量,含义是是否有键盘中断发生(0代表有,1代表没有)。键盘中断函数如下:void keyb

44、oard_int(void)uint8t ucchar; delay(1000);rintmsk = rintmsk | bit_eint2;/ disable eint2 int ri_ispc = bit_eint2; f_nkeypress = 1;对键盘数值进行转换代码如下:uint8t key_set(uint8t ucchar)switch(ucchar)case 1:case 2:case 3:case 4:case 5:ucchar-=1; break;case 9:case 10:case 11:case 12:case 13:ucchar-=4; break;case 17

45、:case 18:case 19:case 20:case 21:ucchar-=7; break;case 25: ucchar = 0xf; break;case 26: ucchar = +; break;case 27: ucchar = -; break;case 28: ucchar = *; break;case 29: ucchar = 0xff; break;default: ucchar = 0xfe;return ucchar;iic头文件代码:/* file:iic.h* author:embest* desc:iic header file* history:*/#i

46、fndef _iic_h_#define _iic_h_#endif /*_iic_h_*/系统总线iic的初始化函数如下:void iic_init(void)f_ngetack = 0; / enable interruptrintmod = 0x0;rintcon = 0x1;rintmsk = rintmsk & (bit_global|bit_iic); pisr_iic= (unsigned)iic_int;/ initialize iicriicadd = 0x10;/ s3c44b0x slave address riiccon = 0xe5;/ enable ack, int

47、errupt, iicclk=mclk/512, enable ack/64mhz/512/(15+1) = 8khz riicstat= 0x10;/ enable tx/rx iic的写操作代码如下:/* name:iic_write* func:write data to iic* para:unslaveaddr - input, chip slave address*unaddr- input, data address*ucdata - input, data value* ret:none* modify:* comment:*/void iic_write(uint32t un

48、slaveaddr,uint32t unaddr,uint8t ucdata)f_ngetack = 0; / send control byte riicds = unslaveaddr;/ 0xa0 riicstat = 0xf0; / master tx,start while(f_ngetack = 0);/ wait ack f_ngetack = 0; / send address riicds = unaddr; riiccon = 0xe5; / resumes iic operation.while(f_ngetack = 0);/ wait ack f_ngetack = 0; / send data riicds = ucdata; riiccon = 0xe5; / resumes iic operation. while(f_ngetack = 0);/ wait ack f_ngetack = 0; / end send riicstat = 0xd0;/ stop master tx condition riiccon = 0xe5;/ resumes iic operation.while(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论