你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

《低功耗MCU运行FreeRTOS》培训课程(五)信号量实现人机交互

[复制链接]
wolfgang2015 发布时间:2018-5-12 18:25
试验三:信号量应用
创建FreeRTOS任务中断和同步(信号量方式)
21.jpg

其实可以这里可以延伸利用信号量来实现串口数据的不定长收发,定长收发使用
“HAL_UART_Receive_IT(&huart2,Rx_Buffer,RxBufferSize);”即可,而不定长的方法在论坛中有网友也举了详细的创建方法(可在论坛中搜索“不定长”),也有修改HAL_UART_Receive_IT 函数的方法实现。
  试验设想:这里是利用FreeRTOS信号量机制实现,主要结合不定长数据的接收,加上FreeRTOS信号量的控制,再通过串口数据接收任务中的消息解析操作,可实现简单的人机交互功能。

交互机制的选择:
  面对消息队列、事件标志组、 信号量等多种交互机制下,可以参考下表进行任务间的交互。
22.jpg

本实验选择互斥信号量来实现,相关的FreeRTOS 信号量 API 函数如下图:
19_1.jpg

使用CubeMX配置串口 DMA的内容略过(参考论坛的不定长DMA配置,FreeRTOS的配置见前篇),待工程建立好后,在代码中增加以下的内容:

在main.h中增加定义:
  1. #define RXBUFFERSIZE 255
复制代码

在main.c中增加定义:
  1. extern SemaphoreHandle_t xScanSemaphore;   //串口中断处理的任务

  2. uint8_t ReceiveBuff[RXBUFFERSIZE] = { 0 }; //接收缓冲区
  3. uint8_t ReceiveInfo[RXBUFFERSIZE]={ 0 };   //接收待识别字符数组

  4. uint8_t Rx_BuffLen, Rx_InfoLen;

  5. void vStartLPUart1ScanTask(void const * argument);
  6. #define Uart_TASK_PRIORITY   ( tskIDLE_PRIORITY + 3UL )
复制代码

在main函数中,调整增加部分代码内容:
  1. int main(void){
  2.   HAL_Init();
  3.   SystemClock_Config();

  4.   MX_GPIO_Init();
  5.   MX_DMA_Init();
  6.   MX_LPUART1_UART_Init();
  7.   MX_USB_OTG_FS_PCD_Init();

  8.   MX_NVIC_Init();  //中断初始化中,增加空闲中断的捕获 __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);

  9.   /*        开启下一次接收        */
  10.   HAL_UART_Receive_DMA(&hlpuart1,(uint8_t*)ReceiveBuff,RXBUFFERSIZE);
  11.   //创建信号量
  12.   xScanSemaphore = xSemaphoreCreateBinary();
  13.   //增加交互任务
  14.   xTaskCreate((TaskFunction_t) vStartLPUart1ScanTask, //任务函数
  15.                     "LPUart1S",              //任务名称
  16.                     200,                     //任务栈大小
  17.                     NULL,                    //任务函数参数
  18.                     Uart_TASK_PRIORITY,      //任务执行等级
  19.                     (TaskHandle_t *) NULL);  //任务句柄
  20.    //启动任务
  21.    vTaskStartScheduler();
  22. }


复制代码

创建串口中断任务内容
  1. void vStartLPUart1ScanTask(void const * argument){
  2.     uint8_t *strp,*strp1;
  3.     configASSERT(xScanSemaphore);
  4.     //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回
  5.     xSemaphoreTake(xScanSemaphore, Scan_BLOCK);
  6.     for (;;) {
  7.        //获取信号量,超时时间为portMAX_DELAY值
  8.        xSemaphoreTake(xScanSemaphore, portMAX_DELAY);
  9.        /*        打印接收到的数据长度 */
  10.        printf("rx_len=%d:\n%s \n", Rx_InfoLen,ReceiveInfo);

  11.         //回答Hello
  12.         strp=strstr((char *)ReceiveInfo,(char *)"Hello");
  13.         if (NULL != strp){
  14.             printf("\n Nice to meet you! \n");
  15.         };

  16.          //回答guten tag/ guten morgen/ guten abend / guten nacht
  17.          strp=strstr((char *)ReceiveInfo,(char *)"Guten");
  18.          if (NULL != strp){
  19.             strp1=strstr((char *)ReceiveInfo,(char *)"morgen");
  20.             if (NULL != strp1){
  21.                 printf("\n Guten Morgen ! \n");
  22.             }
  23.             strp1=strstr((char *)ReceiveInfo,(char *)"tag");
  24.             if (NULL != strp1){
  25.                  printf("\n Guten Tag ! \n");
  26.             }
  27.             strp1=strstr((char *)ReceiveInfo,(char *)"abend");
  28.             if (NULL != strp1){
  29.                  printf("\n Guten Abend ! \n");
  30.             }
  31.             strp1=strstr((char *)ReceiveInfo,(char *)"nacht");
  32.             if (NULL != strp1){
  33.                 printf("\n Guten Nacht ! \n");
  34.             }
  35.        }
  36.        /*        清空接收到的数据        */
  37.        memset(ReceiveInfo, 0x00, Rx_InfoLen);
  38.        Rx_InfoLen=0;
  39.        </font>
复制代码
严格意义上需要词法、语法分析器,这里就不多说,往深的说就就可以实现类似“micropython”的系统了。这里就不离FreeRTOS 信量太远

在stm32l4xx_it.c 文件中设置以下内容
  1. <font face="新宋体" size="3">extern SemaphoreHandle_t xScanSemaphore;
  2. extern uint8_t ReceiveInfo[RXBUFFERSIZE];
  3. extern uint8_t  Rx_BuffLen, Rx_InfoLen;

复制代码
将CubeMX生成的LPUART1_IRQHandler(void)函数中增加以下内容:
  1. void LPUART1_IRQHandler(void) {
  2.     ………
  3.     uint32_t temp;
  4.     static BaseType_t xHigherPriorityTaskWoken;
  5.     HAL_UART_IRQHandler(&hlpuart1);

  6.     /* 如果是串口1IDLE中断        */
  7.     if (RESET != __HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE)) {
  8.        /*        停止DMA接收        */
  9.        HAL_UART_DMAStop(&hlpuart1);

  10.        /*        获取DMA当前还有多少未填充        */
  11.        temp = __HAL_DMA_GET_COUNTER(&hdma_lpuart_rx);

  12.        /*        清除中断标志        */
  13.        __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);

  14.        /*        计算串口接收到的数据个数        */
  15.        Rx_BuffLen = RXBUFFERSIZE - temp;
  16.        Rx_InfoLen = Rx_BuffLen;
  17.        memcpy(ReceiveInfo,ReceiveBuff,Rx_InfoLen);
  18.        memset(ReceiveBuff, 0x00, Rx_BuffLen);
  19.        /*        接收数据长度清零        */
  20.        Rx_BuffLen = 0;
  21.     }

  22.     if (utime_tick >= 200) {
  23.         xSemaphoreGiveFromISR(xScanSemaphore, &xHigherPriorityTaskWoken);
  24.         utime_tick = 0;
  25.      }
  26.      portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
  27.      …………
  28. }

复制代码

编译项目,下载执行,打开串口工具,分别输入 Hello、Guten morgen、Gutentag、Guten abend、Guten nacht能从串口中得到开发板返回的以下内容:

19_2.jpg

没有严格的词法、语法分析, 就不能正确识别处理 “ Hello Guten tag" 之类的指令了,当然回复也是错误的。人机交互的内容就可参考状态机、模糊逻辑、人工智能等内容。

在增加这个信号量任务的时候,还可以将LED的任务、按键中断同时执行,通过控制LED的不同闪烁,同步返回不同的状态。
也可以配合音频文件、音频流等方式,发出标准的语音模式。可以将实验更加丰富、更加有趣。

这样基本的基于FreeRTOS的信号量的人机交互就初步完成。
注意,创建多个任务时“FreeRTOSConfig.h”中#define configTOTAL_HEAP_SIZE 的值大小,太小了,某些任务不会被成功创建;


《低功耗MCU运行FreeRTOS》培课程的准备内容(一)
《低功耗MCU运行FreeRTOS》培课程回顾(二)
《低功耗MCU运行FreeRTOS》培训课程(三) Atollic环境实验
《低功耗MCU运行FreeRTOS》培训课程(四) 创建任务
《低功耗MCU运行FreeRTOS》培训课程(六)消息队列的使用

收藏 3 评论0 发布时间:2018-5-12 18:25

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版