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

news2024/11/24 5:06:08

作者: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++;
				}				
				else
					osDelay(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.coloradmin.cn/o/848913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】—— 进程等待 waitwaitpid

序言: 之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。因此,为了解决这个问题,就需要用到有关 “进程等待” 的基本知识!!&am…

form-create-designer整合element-plus使用方法

最近在使用form-create-designer生成表单的时候遇到了很多问题和各种报错,按照官方文档的方法一步步来做,发现行不通,后来经过不断尝试,终于找到了使用方法,这里做一下总结。 1、安装所需的依赖包 npm install eleme…

PE半透明屏,在建筑行业中,有哪些应用展示?

PE半透明屏是一种新型的屏幕材料,具有半透明的特点。 它由聚乙烯(PE)材料制成,具有良好的透明度和柔韧性。 PE半透明屏广泛应用于建筑、广告、展览等领域,具有很高的市场潜力。 PE半透明屏的特点之一是其半透明性。…

【数据结构】双链表

【数据结构】双链表 一. 前言二. 带头双向链表接口实现1.准备工作2. 创建一个节点 三. 初始化4. 打印5. 尾插6. 尾删7. 头插8. 头删9. 计算节点个数10. 查找数据11. 在任意位置插入数据12. 在任意位置删除数据13. 销毁 四. 如何10分钟内完成一个完整双链表 一. 前言 带头双向循…

JAVA实现图书管理系统(思路,和完整代码)

因为文件过多每个文件之间的关系如下(每个文件中都只有一个类): 因为JAVA属于面向对象编程的语言,所以我们想要实现图书管理系统就得分以下几步: 找出其中的所有的对象实现所有的对象完成对象之间的交互 在图书管理系…

微服务架构基础--第3章Spring Boot核心功能讲解

第3章Spring Boot核心功能讲解 一.预习笔记 1.使用maven创建SpringBoot项目 1-1:创建一个maven项目 1-2:在pom文件中导入依赖 1-3:编写启动类(注意启动类的位置) 1-4:编写测试类 1-5:运行SpringBoot启动类 2.了解p…

Visual Studio 2022安装

Visual Studio下载网址

基于智慧路灯杆的智慧交通应用示例

智慧路灯杆的身影已经越来越频繁出现在我们的生活之中,无论是我们开车在路上,还是行走在商业街,造型美轮美奂,功能丰富多样的智慧路灯杆,也已经成为了一道独特靓丽的街景。 智慧路灯杆如何发挥其智慧功能?对…

[国产MCU]-BL602开发实例-看门狗定时器(WDG)

看门狗定时器(WDG) 文章目录 看门狗定时器(WDG)1、看门狗定时器(WDG)介绍2、看门狗定时器驱动API介绍3、看门狗定时器使用实例看门狗(Watchdog),又叫看门狗定时器(Watchdog Timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器…

入门Echarts数据可视化:从基础到实践

目录 引言数据可视化的重要性Echarts资源与拓展 Echarts简介及开发准备什么是EchartsEcharts的特点与优势安装Echarts引入Echarts库 第一个图表使用Echarts绘制一个简单的柱状图数据准备与图表配置数据格式要求图表标题与标签设置 实践与性能优化提升图表渲染性能的技巧响应式设…

代码分析Java中的BIO与NIO

开发环境 OS:Win10(需要开启telnet服务,或使用第三方远程工具) Java版本:8 BIO 概念 BIO(Block IO),即同步阻塞IO,特点为当客户端发起请求后,在服务端未处理完该请求之前&#xff…

ffmpeg 4.4版本对MP4文件进行AES-CTR加密,和流式加密

对于ffmpeg的AES-CTR加密有两种方式,一个是普通的整个视频做加密,另一个是对视频做切片处理,然后进行加密。 一、对于普通的加密方式 直接使用下面的命令就行 ffmpeg -i animal.mp4 -vcodec copy -acodec copy -encryption_scheme cenc-aes…

VR漫游的“沉浸式”体验,你get到了吗?

信息化时代,几乎每隔一段时间都会出现新的词汇,而“沉浸式”一词仿佛自带流量一般,在很多场景中都有所使用,接下来我们就带大家一起感受下VR漫游所表现出来的“沉浸式”漫游体验。 VR漫游通过专业的全景相机采集高清的图片素材&am…

AWS-自定义ami的S3存取使用

需要提前配置好aws-cli哈 对应的区域 要统一 示例:即AWS-CLI 和 EC2、AMI、S3以上资源均要使用同已区域,以下拿新加坡举例 1.新建自定义AMI 2.查看ami状态 确认是可用状态,才能开始操作 3.aws-cli 开始存入s3 只能使用桶的根目录 开始上…

jdk1.7与jdk1.8的HashMap区别2-底层原理区别

jdk1.7与jdk1.8的HashMap区别1-基本结构与属性对比_ycsdn10的博客-CSDN博客 一、代码区别 1.代码数:JDK1.7与JDK1.8相差了一倍的代码 2.方法数:JDK1.7是40个,JDK1.8是51个(只算基本方法) 二、Hash差别 1.JDK1.7 st…

【Pytorch+torchvision】MNIST手写数字识别

深度学习入门项目,含代码详细解析 在本文中,我们将在PyTorch中构建一个简单的卷积神经网络,并使用MNIST数据集训练它识别手写数字。 MNIST包含70,000张手写数字图像: 60,000张用于培训,10,000张用于测试。图像是灰度(即…

融云:从「对话框」跳进魔法世界,AIGC 带给社交的新范式

8 月 17 日(周四),融云将带来直播课-《北极星如何协助开发者排查问题与预警风险?》欢迎点击上方报名~ AIGC 与社交结合的应用主要分两种,一是发乎于 AIGC,以大模型为基础提供虚拟伴侣等服务的 App&#xff…

7个月的测试经验,来面试居然开口要18K,我一问连5K都不值...

2021年8月份我入职了深圳某家创业公司,刚入职还是很兴奋的,到公司一看我傻了,公司除了我一个测试,公司的开发人员就只有3个前端2个后端还有2个UI,在粗略了解公司的业务后才发现是一个从零开始的项目,目前啥…

网络防御(7)

课堂实验 R1 [Huawei] int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 100.1.12.2 24 protocolAug 1 2023 10:24:09-08:00 Huawei gOlIFNET/4/LINK STATE(1)[4]:The1ineIp on the interface GigabitEthernet0/0/0 has entered the Up state. [Huawei-GigabitEthernet0/0/…

lab7 proxylab

前情提要,如果看了书本,这个lab难度不高,但是如果不看书,难度还是挺高的,并且这个lab会用到cachelab中学到的东西,需要阅读 第十章:系统编程第十一章:网络编程第十二章:…