OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5068|回复: 3

基于STM32F103用FreeRTOS实现消息队列的两个按键分别表示发送和接收消息时,必须等待所有消息发送完后才显示接收到的消息

[复制链接]

21

主题

131

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2019-5-12
在线时间
168 小时
发表于 2020-1-31 11:46:21 | 显示全部楼层 |阅读模式
1金钱
  1. //FreeRTOS头文件
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4. #include "queue.h"
  5. //STM32F103外围硬件的头文件均定义在global.h中
  6. #include "global.h"




  7. /****************************任务句柄**********************/
  8. /*
  9. *任务句柄是一个指针,用于指向一个任务,当任务创建好之后,
  10. *它就具有了一个任务句柄,如果是自身的任务操作自己,那么
  11. *这个句柄就可以为NULL
  12. *
  13. */
  14. //创建任务句柄
  15. static TaskHandle_t AppTaskCreateHandle = NULL;
  16. // LED
  17. static TaskHandle_t        RedLedTaskHandle = NULL;
  18. static TaskHandle_t        YellowLedTaskHandle = NULL;
  19. // KEY
  20. static TaskHandle_t KeyTaskHandle = NULL;

  21. //发送和接收任务句柄
  22. static TaskHandle_t ReceiveTaskHandle = NULL;
  23. static TaskHandle_t SendTaskHandle = NULL;

  24. /**********************内核对象句柄*******************/
  25. /*
  26. *信号量,消息队列,事件标志组,软件定时器这些都属
  27. *于内核的对象,要想使用这些内核对象,必须先创建,
  28. *创建成功之后会返回一个相应的句柄。实际上就是一个
  29. *指针
  30. *
  31. *
  32. *
  33. *内核对象是一种全局的数据结构,通过这些数据结构可以
  34. *实现任务间的通信,任务间的事件同步等各种功能。至于
  35. *这些功能的实现我们是通过调用这些内核对象的函数
  36. * 来完成的
  37. *
  38. *
  39. *
  40. */
  41. QueueHandle_t TestQueueHandle = NULL;


  42. /*********************全局变量声明*****************/


  43. /************************宏定义********************/

  44. #define QUEUE_LEN                4//队列的长度,最大可包含多少个消息
  45. #define QUEUE_SIZE        4//队列中每个消息大小
  46. /*
  47. *******************************************
  48. *                                                                        函数声明
  49. *******************************************
  50. */
  51. static void AppTaskCreate(void);//用于创建任务
  52. static void RedLedTask(void *pvParameters);
  53. static void YellowLedTask(void *pvParameters);
  54. static void KeyTask(void *pvParameters);

  55. static void ReceiveTask(void *pvParameters);//接收任务
  56. static void SendTask(void *pvParameters);//发送任务

  57. static void BspInit(void);//初始化板载STM32F103外设硬件

  58. int main(void)
  59. {
  60.         BaseType_t xReturn = pdPASS;//定义一个创建信息返回值,默认为 pdPAS
  61.         BspInit();
  62.         printf("FreeRTOSTask\r\n");
  63.         printf("Please send queue message by press KEY2 or KEY_UP\n");
  64.         printf("ReceiveTask receive message echo in USART\n\n");
  65.         xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate,//任务入口函数
  66.                                                                                                 (const char*   )"AppTaskCreate",//函数名字
  67.                                                                                                 (uint16_t      )512,//任务栈入口大小
  68.                                                                                                 (void*         )NULL,//任务入口函数参数
  69.                                                                                                 (UBaseType_t   )1,//任务的优先级
  70.                                                                                                 (TaskHandle_t* )&AppTaskCreateHandle);//任务控制块指针
  71.         //启动任务调度                                                                                                
  72.         if(pdPASS == xReturn)
  73.         {
  74.                 vTaskStartScheduler();//启动任务,开始调度
  75.         }               
  76.         else
  77.         {
  78.                 return -1;
  79.         }
  80.         while(1);//正常不会执行到这里
  81.         
  82. }
  83. /*
  84. *@brief:为了方便管理,所有的任务创建函数都放在这个函数里面
  85. *@function:AppTaskCreate
  86. *@param:none
  87. *@retval:none
  88. */
  89. static void AppTaskCreate(void)
  90. {
  91.         BaseType_t xReturn = pdPASS;//定义一个创建信息返回值默认为pdPAss
  92.         taskENTER_CRITICAL();//进入临界区
  93.         
  94.         TestQueueHandle = xQueueCreate((UBaseType_t)QUEUE_LEN,//消息队列的长度
  95.                                                                                                                                         (UBaseType_t)QUEUE_SIZE);//消息队列的大小
  96.         
  97.         if(NULL != TestQueueHandle)
  98.         {
  99.                 printf("Create TestQueueHandle Success!\n");
  100.         }
  101.         
  102.         
  103.         //创建ReceiveTask任务
  104.         xReturn = xTaskCreate((TaskFunction_t )ReceiveTask,//任务入口函数
  105.                                                                                                 (const char*    )"ReceiveTask",//
  106.                                                                                                 (uint16_t       )512,//
  107.                                                                                                 (void*          )NULL,//
  108.                                                                                                 (UBaseType_t    )2,//
  109.                                                                                                 (TaskHandle_t*  )&ReceiveTaskHandle);//
  110.         if(pdPASS == xReturn)
  111.         {
  112.                 printf("Create ReceiveTask Success!\n");//
  113.         }
  114.         //创建SendTask任务
  115.         xReturn = xTaskCreate((TaskFunction_t )SendTask,
  116.                                                                                                 (const char*    )"SendTask",
  117.                                                                                                 (uint16_t       )512,
  118.                                                                                                 (void*          )NULL,
  119.                                                                                                 (UBaseType_t    )3,
  120.                                                                                                 (TaskHandle_t*  )&SendTaskHandle);
  121.         if(pdPASS == xReturn)
  122.         {
  123.                 printf("Create SendTask Success!\n\n");
  124.         }               
  125.         
  126.         

  127.         vTaskDelete(AppTaskCreateHandle);//删除AppTaskCreate任务
  128.         taskEXIT_CRITICAL();//退出临界区
  129. }
  130. /*
  131. *@brief:RedLed任务管理
  132. *@function:RedLedTask
  133. *@param:*parameter
  134. *@retval:none
  135. */
  136. static void RedLedTask(void *parameter)
  137. {
  138.         while(1)
  139.         {
  140.                 RED_LED_ON();
  141.                 vTaskDelay(15000);//延时15000个tick
  142.                 printf("RedLedTask Running,RED_LED_OFF\n");
  143.                
  144.                 RED_LED_OFF();
  145.                 vTaskDelay(15000);//延时15000个tick
  146.                 printf("RedLedTask Running,RED_LED_ON\n");
  147.         }
  148. }

  149. /*
  150. *@brief:YellowLed任务管理
  151. *@function:YellowLedTask
  152. *@param:*parameter
  153. *@retval:none
  154. */
  155. static void YellowLedTask(void *parameter)
  156. {
  157.         while(1)
  158.         {
  159.                 YELLOW_LED_ON();
  160.                 vTaskDelay(15000);//延时15000个tick
  161.                 printf("YellowLedTask Running,YELLOW_LED_OFF\n");
  162.                
  163.                 YELLOW_LED_OFF();
  164.                 vTaskDelay(15000);//延时15000个tick
  165.                 printf("YellowLedTask Running,YELLOW_LED_ON\n");
  166.         }
  167. }
  168. /*
  169. *@brief:Key任务管理
  170. *@function:KeyTask
  171. *@param:*parameter
  172. *@retval:none
  173. */
  174. static void KeyTask(void *parameter)
  175. {
  176.         while(1)
  177.         {
  178.                 if(KeyScan(KEY0_GPIO_PORT,KEY0_GPIO_PIN) == KEY012_ON)
  179.                 {
  180.                         //KEY0被按下
  181.                         printf("Suspend Task of LED!\n\n");
  182.                         vTaskSuspend(RedLedTaskHandle);//挂起红灯任务
  183.                         vTaskSuspend(YellowLedTaskHandle);//挂起黄灯任务
  184.                 }
  185.                 if(KeyScan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY012_ON)
  186.                 {
  187.                         //KEY1被按下
  188.                         printf("Resume Task of LED!\n\n");
  189.                         vTaskResume(RedLedTaskHandle);//挂起红灯任务
  190.                         vTaskResume(YellowLedTaskHandle);//挂起黄灯任务
  191.                 }
  192.                 vTaskDelay(100);//延时100个tick,串口打印更稳定
  193.         }

  194. }

  195. /*
  196. *@brief:ReceiveTask任务管理
  197. *@function:
  198. *@param:none
  199. *@retval:none
  200. */
  201. static void ReceiveTask(void *parameter)
  202. {
  203.         BaseType_t xReturn = pdTRUE;//定义一个创建信息返回值,默认为 pdTRUE
  204.         uint32_t ReceiveQueue;//定义一个接收消息的变量
  205.         while(1)
  206.         {
  207.                 xReturn = xQueueReceive(TestQueueHandle,
  208.                                                                                                                 &ReceiveQueue,
  209.                                                                                                                 portMAX_DELAY);
  210.                 if(pdTRUE == xReturn)
  211.                 {
  212.                         printf("This time receive data is%d\n",ReceiveQueue);
  213.                 }
  214.                 else
  215.                 {
  216.                         printf("Data receive error,error code:0x%lx\n",xReturn);
  217.                 }
  218.         }
  219. }
  220. /*
  221. *@brief:SendTask任务管理
  222. *@function:
  223. *@param:none
  224. *@retval:none
  225. */
  226. static void SendTask(void *parameter)
  227. {
  228.         BaseType_t xReturn = pdPASS;//定义一个创建信息返回值,默认为 pdPASS
  229.         uint32_t sendData1 = 1;
  230.         uint32_t sendData2 = 2;
  231.         
  232.         while(1)
  233.         {
  234.                 if(KeyScan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY012_ON)
  235.                 {
  236.                         //KEY2被按下
  237.                         printf("Send message 'sendData1'!\r\n");
  238.                         xReturn = xQueueSend(TestQueueHandle,//消息队列的句柄
  239.                                                                                                                 &sendData1,//发送的消息内容
  240.                                                                                                                 0);//等待时间为0
  241.                         if(pdPASS == xReturn)
  242.                         {
  243.                                 printf("sendData1 send success!\n\n");
  244.                         }
  245.                         
  246.                 }
  247.                 if(KeyScan(KEY_UP_GPIO_PORT,KEY_UP_GPIO_PIN) == KEY_UP_ON)
  248.                 {
  249.                         //KEY_UP被按下
  250.                         printf("Send message 'sendData2'!\r\n");
  251.                         xReturn = xQueueSend(TestQueueHandle,//消息队列的句柄
  252.                                                                                                                 &sendData2,//发送的消息内容
  253.                                                                                                                 0);//0
  254.                         if(pdPASS == xReturn)
  255.                         {
  256.                                 printf("sendData2 send success!\n\n");
  257.                         }
  258.                         
  259.                 }
  260.                 vTaskDelay(100);//延时100个tick,串口打印更稳定
  261.         }
  262. }
  263. /*
  264. *@brief:板级支持包,初始化STM32F103外围硬件
  265. *@function:BspInit
  266. *@param:none
  267. *@retval:none
  268. */
  269. static void BspInit()
  270. {
  271.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置NVIC中断优先级分组,2位抢占优先级和2位响应优先级        
  272.         LedGpioConfig();
  273.         UsartConfig();
  274.         KeyConfig();
  275. }
复制代码
但是在串口中的打印应该是在按下KEY2后,打印
Send message 'sendData1'!
sendData1 send success!
且打印
This time receive data is1
现在的问题是只有等待KEY2和KEY_UP都执行后也就是在
Send message 'sendData1'!
sendData1 send success!
Send message 'sendData2'!
sendData2 send success!
都出现后才会打印
This time receive data is1
This time receive data is2
应该如何解决?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2020-2-1 01:13:06 | 显示全部楼层
回复

使用道具 举报

4

主题

65

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
461
金钱
461
注册时间
2016-8-4
在线时间
192 小时
发表于 2020-2-1 14:41:55 | 显示全部楼层
本帖最后由 小施 于 2020-2-1 15:05 编辑

ReceiveTask任务优先级比较低吧,可以试下提高下ReceiveTask任务优先级,同时加个vTaskDelay(10)。
回复

使用道具 举报

21

主题

131

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2019-5-12
在线时间
168 小时
 楼主| 发表于 2020-2-1 19:24:25 | 显示全部楼层
小施 发表于 2020-2-1 14:41
ReceiveTask任务优先级比较低吧,可以试下提高下ReceiveTask任务优先级,同时加个vTaskDelay(10)。
[/back ...

按键发送消息,都有加100ms延时,然后接收的任务优先级放在第二位也没错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 21:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表