FreeRTOS通过消息队列实现串口命令解析(串口中断)

作者:Jack_G
时间:2023.08.08
版本:V1.0
上次修改时间:
环境:
\quad \quad \quad \quad STM32Cube MX V6.8.1
\quad \quad \quad \quad STM32CubeH7 Firmware Package V1.11.0 / 04-Nov-2022
\quad \quad \quad \quad Keil: V5.29

一、串口配置:

正常配置,不过需要勾选全局中断,后续在接收中断中将接收到的数据送入消息队列。
在usart.c文件中添加以下代码以重定义fputc以支持printf

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)  
//解决HAL库使用时,某些情况可能报错的bug
int _ttywrch(int ch)    
{ch=ch;return ch;
}
//标准库需要的支持函数                 
struct __FILE 
{ int handle; /* Whatever you require here. If the only file you are using is */ /* standard output using printf() for debugging, no file handling */ /* is required. */ 
}; 
/* FILE is typedef’ d in stdio.h. */ 
FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      while((USART1->ISR&0X40)==0);//循环发送,直到发送完毕   USART1->TDR = (unsigned char) ch;      return ch;//	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch, 1); 
//  return (ch);}
#endif 

记得添加头文件

#include "stdio.h"	
#include "stdlib.h"
#include "string.h"

二、代码部分

创建指令解析的任务和消息队列和信号量:

其中信号量是用于串口接收完一次完整消息后通知任务开始获取消息队列的消息。
这部分代码主要:
创建命令解析任务、创建命令解析所用的消息队列、创建命令解析所用的信号量

void StartCMDAnalysisTask(void const * argument);//声明命令解析函数osThreadId cmdAnalysisTaskHandle;//定义命令解析任务的句柄
SemaphoreHandle_t  uartSemaphore;//定义串口接收一次完成的信号量
QueueHandle_t  uartQueue;//定义串口消息队列的句柄/* 创建指令解析任务 */
osThreadDef(cmdAnalysisTask, StartCMDAnalysisTask, osPriorityBelowNormal, 0, 512);
cmdAnalysisTaskHandle = osThreadCreate(osThread(cmdAnalysisTask), NULL);/* 创建串口的消息队列 */
uartQueue = xQueueCreate((UBaseType_t ) 128,/* 消息队列的长度 */(UBaseType_t ) sizeof( char));/* 消息的大小 */
if(NULL == uartQueue)printf("uartQueue created failed\r\n");/* 创建串口接收完成的信号量 */
uartSemaphore = xSemaphoreCreateBinary();
if(NULL == uartSemaphore)printf("uartSemaphore created failed\r\n");

具体实现:

实现逻辑:
①开启串口的接收中断(UART_IT_RXNE)和空闲中断(UART_IT_IDLE)
\quad \quad 接收中断是每接收一个字符时 产生一次中断
\quad \quad 空闲中断是每完成一次接收后产生的中断

②每当接收中断时(即接收一个字符),将获取的字符送入消息队列
③当完成一个串口传输时(即本次传输完成),释放信号(通知任务传输完成)
④任务获取到信号量后,将消息队列中的数据尽数取出,直到’\r’,(这个\r是我自己定义的)
⑤将取出的消息放提前准备好的缓冲区中,使用strcmp函数进行对比
⑥清空缓冲区,等待下一次的’\r’

开启串口中断

笔者实测STM32H7将开启串口中断代码放于串口初始化后,会莫名奇妙直接进入空闲中断,查阅资料发现有些F1不会出现这种情况,因此笔者建议这部分放于创建完任务后,实测可行。

__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//开启接收中断
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启空闲中断
__HAL_UART_CLEAR_IDLEFLAG(&huart1);	

串口中断函数

void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 1 */uint8_t res = 0;
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) != RESET){HAL_UART_Receive(&huart1,&res,1,1000);//将数据放入消息队列xQueueSendFromISR(uartQueue,&res,NULL);__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);}//空闲中断if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET){//一帧数据接收完成		//释放信号量xSemaphoreGiveFromISR(uartSemaphore,NULL);__HAL_UART_CLEAR_IDLEFLAG(&huart1);}/* USER CODE END USART1_IRQn 1 */
}

解析任务

void StartCMDAnalysisTask(void const * argument)
{char Rx_Buffer[128];int index=0;memset(Rx_Buffer,'\0',128);for(;;){if(uxSemaphoreGetCount(uartSemaphore) == 1) //串口完成了一次接收{xSemaphoreTake(uartSemaphore, ( TickType_t ) 10);//获取信号量/* 获取消息队列中的数据到Buffer中直至获取到\r */		do{if(xQueueReceive(uartQueue,&Rx_Buffer[index],( TickType_t ) 10) == pdTRUE){index++;}				elseosDelay(10);}while(Rx_Buffer[index-1] != '\r');Rx_Buffer[index-1] = '\0';index = 0;	
/* 命令解析 命令 存于Rx_Buffer中,解析完一次则清空一次*/if(strcmp(Rx_Buffer,"AT") == 0){printf("ok\r\n");}/* 放置你需要解析的命令if(strcmp(Rx_Buffer,"your CMd") == 0){//定义处理的方式}*/memset(Rx_Buffer,'\0',128);			}osDelay(2);}
}

这里只写了AT,返回OK,
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/81197.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创意项目管理软件推荐:满足客户需求的完美解决方案

发现功能强大的工作管理软件,让创意大放异彩。将您团队的愿景变成引人注目的项目。 一、交付总是令人印象深刻的工作 Zoho Projects的创意项目管理软件可帮助您和您的团队在一个地方监督多个项目。使用我们的内置管理工具和模板,花更少的时间在管理上&a…

【福建事业单位-推理判断】02图形推理(数量-空间重构)

【福建事业单位-推理判断】02图形推理(数量-空间重构) 一、数量规律1.1点(交点、切点)点的细化考法总结 1.2线条(线条的数量)线的细化考点一笔画(重点)一笔画的判定 总结 1.3 面面的…

Ajax同源策略及跨域问题

Ajax同源策略及跨域问题 同源策略ajax跨域问题什么是跨域?为什么不允许跨域?跨域解决方案1、CORS2、express自带的中间件cors3、JSONP原生JSONPjQuery发送JSONP 4、使用vscode的Live Server插件 同源策略 同源策略(Same-Origin Policy&#…

数学建模学习(9):模拟退火算法

模拟退火算法(Simulated Annealing, SA)的思想借 鉴于固体的退火原理,当固体的温度很高的时候,内能比 较大,固体的内部粒子处于快速无序运动,当温度慢慢降 低的过程中,固体的内能减小,粒子的慢慢趋于有序&a…

华三H3C S5120V3交换机的配置之组建IRF

IRF(Intelligent Resilient Framework,智能弹性架构),是华三交换机实现虚拟堆叠的一种技术,其核心思想是将多台交换机连接在一起,虚拟成一台交换机,进而实现统一管理。和传统的堆叠概念不同&…

HTML

HTML 1. 块级标签 标题&#xff1a; <h1>一级标题</h1> div: <div>这是一个div标签</div> p&#xff1a; <p>这是一个p标签&#xff0c;段落标签</p> <!DOCTYPE html> <html lang"en"> <head><meta charse…

如何使用 ChatGPT 规划家居装修

你正在计划家庭装修项目&#xff0c;但不确定从哪里开始&#xff1f;ChatGPT 随时为你提供帮助。从集思广益的设计理念到估算成本&#xff0c;ChatGPT 可以简化你的家居装修规划流程。在本文中&#xff0c;我们将讨论如何使用 ChatGPT 有效地规划家居装修&#xff0c;以便你的项…

Redis 和 Mysql 如何保证数据一致性

项目场景&#xff1a; 一般情况下&#xff0c;Redis 用来实现应用和数据库之间读操作的缓存层&#xff0c;主要目的是减少数据库 IO&#xff0c;还可以提升数据的 IO 性能。 如下图所示&#xff0c;这是它的整体架构。 当应用程序需要去读取某个数据的时候&#xff0c;首先会先…

目标检测与跟踪 (2)- YOLO V8配置与测试

系列文章目录 第一章 目标检测与跟踪 &#xff08;1&#xff09;- 机器人视觉与YOLO V8 目标检测与跟踪 &#xff08;1&#xff09;- 机器人视觉与YOLO V8_Techblog of HaoWANG的博客-CSDN博客3D物体实时检测、三维目标识别、6D位姿估计一直是机器人视觉领域的核心研究课题&a…

[golang gin框架] 45.Gin商城项目-微服务实战之后台Rbac微服务之角色权限关联

角色和权限的关联关系在前面文章中有讲解,见[golang gin框架] 14.Gin 商城项目-RBAC管理之角色和权限关联,角色授权,在这里通过微服务来实现角色对权限的授权操作,这里要实现的有两个功能,一个是进入授权,另一个是,授权提交操作,页面如下: 一.实现后台权限管理Rbac之角色权限关…

[CVPR-23-Highlight] Magic3D: High-Resolution Text-to-3D Content Creation

目录 Abstract Background: DreamFusion High-Resolution 3D Generation Coarse-to-fine Diffusion Priors Scene Models Coarse-to-fine Optimization NeRF optimization Mesh optimization Experiments Controllable 3D Generation Personalized text-to-3D Prom…

如何选择适合您需求的新闻稿件校对软件

选择适合您需求的新闻稿件校对软件时&#xff0c;可以考虑以下几个因素&#xff1a; 1.校对功能&#xff1a;了解软件的校对功能&#xff0c;包括拼写检查、语法检查、词汇和语义检查等方面。确保软件能够满足您的基本校对需求&#xff0c;并提供准确的建议和改进意见。 2.多语…

kubesphere 部署 ingress 并使用 80 端口

文章目录 创建集群网关创建应用路由访问域名使用 80 端口 创建集群网关 官方文档&#xff1a;集群网关 点击左上角的平台管理并选择集群管理 点击导航面板中集群设置下的网关设置&#xff0c;选择集群网关选项卡&#xff0c;并点击启用网关 选择 NodePort 模式&#xff0c;配…

【CSS】说说对BFC的理解

目录 一、概念 二、BFC的布局规则 三、设置BFC的常用方式 四、BFC的应用场景 1、解决浮动元素令父元素高度坍塌的问题 2、解决非浮动元素被浮动元素覆盖问题 3、解决外边距垂直方向重合的问题 五、总结 一、概念 我们在页面布局的时候&#xff0c;经常出现以下情况&am…

go 基本语法(简单案例)

&#xff01;注&#xff1a; go中 对变量申明很是严格&#xff0c;申明了&#xff0c;在没有使用的情况下&#xff0c;也会产生编译错误 1.行分隔符 一行就是代码&#xff0c;无&#xff1b;分割&#xff0c;如果需要在一行展示&#xff0c;需要以&#xff1b;分割&#xff0c;…

Vue3 事件处理简单应用

去官网学习→事件处理 | Vue.js 运行示例&#xff1a; 代码&#xff1a;HelloWorld.vue <template><div class"hello"><h1>Vue 事件处理</h1><button v-on:click"numb 1">点击加1-----{{ numb }}</button><br/&…

安防监控视频融合EasyCVR平台接入RTSP流后设备显示离线是什么原因?

安防监控视频EasyCVR视频汇聚融合平台基于云边端智能协同架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台支持海量视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成&#xff…

设计模式行为型——观察者模式

目录 什么是观察者模式 观察者模式的实现 观察者模式角色 观察者模式类图 观察者模式举例 观察者模式代码实现 观察者模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是观察者模式 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式…

73. 矩阵置零

题目链接&#xff1a;力扣 解题思路&#xff1a; 方法一&#xff1a;比较容易想到的方向&#xff0c;使用两个数组row和col保存有0的行或者列&#xff0c;然后将有0的那一行或那一列的所有元素都设置为0 AC代码 class Solution {public void setZeroes(int[][] matrix) {in…

Python爬虫——爬虫时如何知道是否代理ip伪装成功?

前言 在进行爬虫时&#xff0c;我们可能需要使用代理IP来伪装自己的身份&#xff0c;以避免被网站封禁。如何判断代理IP是否伪装成功呢&#xff1f;本篇文章将围绕这个问题展开讲解&#xff0c;同时提供Python代码示例。 1. 确认代理IP地址 首先&#xff0c;我们需要确认代理…