首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于RTX51实时操作系统的用户专用键盘软件设计 02

基于RTX51实时操作系统的用户专用键盘软件设计 02

 采用时间轮询的方式决定了某个任务在执行完时间片后,在下一次执行前需要等待固定的时间,这个时间与系统的任务数及每个任务的执行时间密切相关,为避免数据丢失,串口接收任务应及时读取接收缓存器中的数据。由于中断处理过程与正在运行的任务是相互独立的,即中断处理过程在RTX51系统内核之外和任务切换规则没有关联,因此可以在串口中断服务程序中完成串口接收任务。另外,串口发送时要求将整个按键码值数据包一次性发送完毕,如果将串口发送过程在中断服务程序中完成,在SBUF缓存器发送完一个字节后触发串口发送中断标志,再次进入中断服务程序继续下一字节数据的发送,则可以方便地实现上述要求。根据以上分析,串口接收、串口发送两个子任务的功能在中断服务程序中完成,将系统子任务的个数由5个减少为3个,调整后的任务分配如下:
  任务1:按键状态扫描(TASK SCAN);
  任务2:按键码值查询(TASK KEY);
  任务3:串口数据处理((TASK LIGHT));
  中断服务程序:串口接收、发送。
  任务间信号关系如图2所示。


  如图,任务1在检测到按键状态变化后向任务2发送信号,任务2随后由等待状态进入“准备好”状态,在本任务的下一个时间片,任务2开始进行指定位置按键的码值查询,然后通过串口完成码值发送。
  同时,串口数据通过中断服务程序接收,串口数据接收后即发送信号给任务3,使后者进入“准备好”状态,并在下一个时间片到来后进行数据处理。
  以上三个任务中,任务l始终处于“运行”或“准备好”状态,任务2、任务3大多数时间处于“等待”状态,任务2、任务3分别在接收到按键状态扫描任务、中断服务程序的信号后被“唤起”。另有任务0,负责创建任务1、2、3,然后删除自己。任务0简化程序如下所示:
  #define INIT 0/*任务0:初始化及创建*/
  #define SCAN 1/*任务1:按键状态扫描*/
  #define KEY 2/*任务2:按键码值查询*/
  #define LIGHT 3/*任务3:串口数据处理*/
  Init()_task_INIT{
  Serial_init();
  Os_create task(SCAN);
  Os_create_task(KEY);
  Os_create_task(LIGHT);
  Os_delete-task(INIT);
  }
  以下对中断服务程序及各个任务分别予以介绍。
  3.2 中断服务程序
  用户专用键盘串口接收、发送中断服务程序流程如图3所示。

  由于中断可能由发送控制器或接收控制器引起,因此在程序中首先要判断是接收中断还是发送中断,然后分别进行处理。对于接收的数据,程序将其存入接收缓冲区,然后通知串口数据处理任务进行处理。
  用户专用键盘数据的发送在中断服务程序中完成,上一字节的数据发送完毕产生中断,进入中断服务程序继续完成下一字节的发送,而发送缓冲区中的数据由系统在按键码值查询任务中存入。简化的中断服务程序如下:

  3.3 串口数据处理任务(TASK_LIGHT)
  中断服务程序只处理串口缓存器SBUF的读取或写入,数据一旦接收完毕即存入缓冲区,并在专门的任务中进行处理。在多任务系统的用户专用键盘程序中,串口数据处理任务在创建后即被“挂起”,此时该任务处于“等待”状态,不占用任何时间片,只有当任务接收到“唤起”信号后才继续执行。本程序中“唤起”信号来自中断服务程序。由于中断处理过程可以同RTX51任务互发信号或交换数据,因此,中断服务程序在接收到数据后立即发送信号量给串口数据处理任务,使后者处于“准备好”状态,当下一时间片来到时,串口数据处理任务继续执行,完成数据解析及控制指示灯等操作。由于该任务为循环操作,当所有接收的数据处理完毕后,任务再次进入“等待”状态,等待下一次串口数据接收后的处理。图3中,斜体部分即为中断服务程序发送信号至串口数据处理任务的过程。串口数据处理任务的简化程序如下:

  3.4 按键状态扫描任务(TASK SCAN)
  按键状态扫描为一个循环执行的任务,程序通过不断地读取单片机IO口的值获取每个按键的当前状态,然后将当前状态值与存储在内存中的上一次状态值进行比较,通过比较结果判断该按键状态是否发生变化。为消除按键按下时抖动造成的多次状态变化,在扫描到某个按键状态发生改变后,延时一段时间后进行第二次扫描,如果两次扫描结果相同则认为该按键状态确实发生改变,并转入下一步处理。按键状态扫描任务流程如图4所示。  



   
  下面给出按键状态扫描任务简化的源程序:
  Scan()_task_SCAN{/*按键状态扫描任务*/
  …
  While(1){
  Key_first_scan();/*第1次扫描*/
  If(Keychanged=1){
  Os_wait(K_TMO,2,0)/*延时*/
  Key_second_scan();/*第2次扫描*/
  If(first scan=second scan){/*如果两次扫描的按键状态一致*/
  os_send_signal(2);/*发送信号至按键码值查询任务+/
  }
  }
  }
  }
返回列表