基于FreeRTOS的队列管理的应用

来源:互联网 发布:整形医院网站源码 编辑:程序博客网 时间:2024/06/05 20:19
[cpp] view plaincopy
  1.         我们前一篇技术文章大概说明了,如何基于FreeRTOS嵌入式实时操作系统,进行基本的应用软件开发。在这里,我们将说说在应用中,如果使用FreeRTOS的队列。这是因为在应用程序中,不同任务间的消息传送,会大量用到队列这种方式。  
  2.   
  3.         先解释一下队列:是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。  
  4.   
  5.         在FreeRTOS中,对队列有专门的管理机制及函数,在queue.h定义。使用队列进行消息传送,可以避免数据冲突与丢失等现象。如:有一个任务,需要根据另外三个任务的数据来执行它的操作或运行流程,且在这四个任务运行时,是不定时的,没有任何规律可言,那么按照传统的公共变量的方式,就有可能产生数据丢失或数据访问冲突。如果在这里使用FreeRTOS的队列来传递数据信息,则相当容易地把这种问题给解决了。在FreeRTOS中使用队列,最简单的应用,需要创建队列、发送队列消息、等待接收队列消息、删除队列等操作。使用队列,不仅可以传送单字节消息,也可以传送数据结构。在这里,队列管理相关的函数定义不就再进行说明了,需要时,可以参考queue.h。下面直接举例,说明如何使用FreeRTOS队列。  
  6.   
  7. 例如:有一组LED灯,在同一个物理操作端口上面,另外三个不同的任务,需要操作这组LED灯来指示系统状态。这时,引入一个单独的任务来操作这组LED灯,那三个不同的任务则向这一个LED灯操作任务发送消息来控制LED灯。则应用程序框架如下所示:  
  8.   
  9. 1、 定义消息数据结构及变量  
  10.   
  11. typedef struct //定义一个需要传递的消息的数据结构  
  12.   
  13. {  
  14.   
  15.        u8 msg_src; // 消息来源编号  
  16.   
  17.        u8 msg_val; // 消息值  
  18.   
  19. } Led_msg;  
  20.   
  21.    
  22.   
  23. #define  Task1_msg  0x1  // 定义任务1所传递的消息  
  24.   
  25. #define  Task2_msg  0x2  // 定义任务2所传递的消息  
  26.   
  27. #define  Task3_msg  0x3  // 定义任务3所传递的消息  
  28.   
  29. xQueueHandle  hLED_MSG; //用于传递消息的一个公共Handle变量  
  30.   
  31. 2、 在main程序中,创建一个消息用于消息的传递  
  32.   
  33.         hLED_MSG = xQueueCreate( 10 , sizeof(Led_msg) );//创建一个消息,最多可以有10个值进行排队,每个值的大小为数据结构Led_msg大小。  
  34.   
  35.    
  36.   
  37. 3、 在LED灯操作的任务中等待消息并处理  
  38.   
  39. void Task_LED( void *pvParameters )  
  40.   
  41. {  
  42.   
  43.         Led_msg Receive_msg;  
  44.   
  45.         While(1) //该任务是一个不退出的循环任务  
  46.   
  47.         {  
  48.   
  49.                While(xQueueReceive(hLED_MSG, & Receive_msg, portMAX_DELAY ) != pdPASS ); // 等待消息直到收到一个有效的消息数据,并放入Receive_msg变量中  
  50.   
  51.                Switch(Receive_msg.msg_src)  
  52.   
  53.                {  
  54.   
  55.                 case: Task1_msg  
  56.   
  57.   
  58.                        ;;;;;// 执行任务1传递过来的消息,对LED的操作  
  59.   
  60.   
  61.                        Break;  
  62.   
  63.   
  64.                 case: Task2_msg  
  65.   
  66.   
  67.                        ;;;;;// 执行任务2传递过来的消息,对LED的操作  
  68.   
  69.   
  70.                        Break;  
  71.   
  72.   
  73.                 case: Task3_msg  
  74.   
  75.   
  76.                        ;;;;;// 执行任务3传递过来的消息,对LED的操作  
  77.   
  78.   
  79.                        Break;  
  80.   
  81.   
  82.                 default:  
  83.   
  84.   
  85.                        Break;  
  86.   
  87.   
  88.                 }  
  89.   
  90.   
  91.         }  
  92.   
  93. }  
  94.   
  95.    
  96.   
  97. 4、消息的发送  
  98.   
  99. void Task1 ( void *pvParameters )  
  100.   
  101. {  
  102.   
  103.         Led_msg Send_msg;  
  104.   
  105.         While(1)  
  106.   
  107.         {  
  108.   
  109.                 ;;;;;//任务1的任务部份  
  110.   
  111.   
  112.                 Send_msg. msg_src = Task1_msg; //指定任务1消息编号  
  113.   
  114.   
  115.                 Send_msg. msg_val = 0x5;//假定该任务要传递的值为0x5  
  116.   
  117.   
  118.                 xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息  
  119.   
  120.   
  121.         }  
  122.   
  123. }  
  124.   
  125.    
  126.   
  127. void Task2 ( void *pvParameters )  
  128.   
  129. {  
  130.   
  131.         Led_msg Send_msg;  
  132.   
  133.         While(1)  
  134.   
  135.         {  
  136.   
  137.                 ;;;;;//任务2的任务部份  
  138.   
  139.   
  140.                 Send_msg. msg_src = Task2_msg; //指定任务2消息编号  
  141.   
  142.   
  143.                 Send_msg. msg_val = 0x77;//假定该任务要传递的值为0x77  
  144.   
  145.   
  146.                 xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息  
  147.   
  148.   
  149.         }  
  150.   
  151. }  
  152.   
  153.    
  154.   
  155. void Task3 ( void *pvParameters )  
  156.   
  157. {  
  158.   
  159.         Led_msg Send_msg;  
  160.   
  161.         While(1)  
  162.   
  163.         {  
  164.   
  165.                 ;;;;;//任务3的任务部份  
  166.   
  167.   
  168.                 Send_msg. msg_src = Task3_msg; //指定任务3消息编号  
  169.   
  170.   
  171.                 Send_msg. msg_val = 0x9;//假定该任务要传递的值为0x9  
  172.   
  173.   
  174.                 xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息  
  175.   
  176.   
  177.         }  
  178.   
  179. }  
  180.   
  181.    
  182.   
  183.         到此,队列的基本应用例子程序已完成。如果在应用程序中的某种条件下,不再需要这个队列,则可以调用xQueueDelete(hLED_MSG)将该队列删除。基本了解了FreeRTOS任务的创建及应用,以及队列的应用,则可以完成一些简单应用程序的编写。