FreeRTOS系列第4篇——串口通信
本文介绍了基于STM32H723ZGT6芯片的FreeRTOS串口控制LED实现方案。主要内容包括:1)使用STM32CubeMX配置芯片外设(串口PA2/PA3、LED引脚PC8)和FreeRTOS环境;2)创建两个任务分别处理LED控制和串口指令解析;3)通过消息队列实现任务间通信;4)实现了"Func=LED_ON/OFF;"指令控制LED开关功能。测试结果显示系统能成功
目录
一、工程简介
1.芯片:STM32H723ZGT6芯片型号
2.用到的外设功能:
PA3——SCREEN_RX
PA2——SCREEN_TX
PC8——灯的亮灭。
二、STM32cubemax的配置
1.新建工程_选择对应的芯片。

2.调试管脚的配置

3.FreeRTOS的环境配置


4.串口配置——串口配置成中断接收。

5.配置灯的管脚——重命名为LED。

6.配置FreeRTOS的选项——我们这里使用V2版本的。

7.创建任务——两个任务,一个控制灯的亮灭,一个是解析串口指令协议。

8.构建存储结构体的队列
——构建用于通信存储的数据。串口收发是使用uint8_t类型的。
——构建用于控制灯亮灭的数据。控制灯亮灭和颜色,这里是使用结构体进行传递。这里使用指针类型。

9.配置时钟——配置最高时钟。

10.生成代码
。


11.在工程目录添加文件夹——用于存放.c文件和.h文件。


12.将新建文件夹目录路径添加进来。

13.文件夹的创建


14.在main函数里面添加这个头文件


15.在串口中断中添加这些代码,这些代码主要是把串口中断产生的数据压入队列中进行任务交互。

16.新建的KEL工程需要勾选这个。

三、需要添加的代码
1.总共需要重新编写四个文件

2.inclides文件——主要用于主函数包含所有的结构体和头文件
//.h文件
#ifndef __INCLUDES_H
#define __INCLUDES_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "cmsis_os.h"
#include "FreeRTOS.h"
#include "LedTask.h"
#include "UpperTask.h"
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDES_H */
3.UpperTask文件——用于处理串口接收数据
//.c文件
#include "upperTask.h"
#include "string.h"
#include "stdio.h"
/* 类型定义和结构体优化 */
typedef struct {
const char* cmd_template; // 命令模板
int buffer_index; // 使用的buffer索引
uint8_t buffer_size; // buffer大小
void (*handler)(void); // 命令处理函数
} CommandMap;
static void prvHandLedStatus_OFF(void);
static void prvHandLedStatus_ON(void);
/* 命令映射表 */
static const CommandMap cmd_map[] = {
{"Func=LED_ON;", 0,sizeof("Func=LED_ON;")-1, prvHandLedStatus_ON},
{"Func=LED_OFF;", 0,sizeof("Func=LED_OFF;")-1, prvHandLedStatus_OFF},
};
// 接收缓冲区
#define RX_BUFFER_SIZE 128 //缓存区大小
char RxBuffer[RX_BUFFER_SIZE]={0};// 用于存储接收到的指令
uint8_t RxIndex = 0;// 指令接收状态
void ExecuteCommand(char *cmd);
void SendResponse(const char* resp);
void ParseAndExecuteCommand(char* cmd);
void MCU_usart_handle(char Rxdata);
extern UART_HandleTypeDef huart2;
/*--------------------------------------------*/
void UpperStartTask(void *argument)
{
usart2_receive_start();//串口初始化
char Rxdata=0;
for(;;)
{
osMessageQueueGet(CommandQueueHandle,&Rxdata,0,osWaitForever);
MCU_usart_handle(Rxdata);/*数据处理*/
}
}
/* 回调处理函数 */
void MCU_usart_handle(char Rxdata){
if (Rxdata !='\n') // 检查指令结束
{
if(Rxdata!=' ')//不等于空格
{
RxBuffer[RxIndex]=Rxdata;
RxIndex++; // 增加接收索引
}
}
else
{
RxBuffer[RxIndex] = '\0'; // 替换换行符为字符串结束符
RxIndex = 0; // 重置接收索引
ParseAndExecuteCommand(RxBuffer);
}
}
/* 统一命令解析 */
void ParseAndExecuteCommand(char* cmd) {
for(int i=0; i<sizeof(cmd_map)/sizeof(CommandMap); i++){
if(strncmp(cmd, cmd_map[i].cmd_template, cmd_map[i].buffer_size) == 0){
if(cmd_map[i].handler) {
cmd_map[i].handler();
} else {
ExecuteCommand(cmd);
}
return;
}else
{
if(i==sizeof(cmd_map)/sizeof(CommandMap)-1)
{
SendResponse("undefined COMMAND\r\n");
}
}
}
}
void ExecuteCommand(char *cmd) {
SendResponse("undefined COMMAND\r\n");
}
/*--处理灯关灯-----------------------------------------------------------*/
static void prvHandLedStatus_OFF(void) {
char response[100]={0};
//LEDMessage *message=malloc(sizeof(LEDMessage));/*使用单片机的内存,需要使用对应的函数进行free释放内存*/
LedMessage *message=pvPortMalloc(sizeof(LedMessage));/*使用freeRTOS分配的内存,需要使用对应的pvfree释放内存*/
message->color=1;//
message->state=0;//关灯成功
// LEDMessage*pMessage =&message;
osMessageQueuePut(LedQueueHandle,(&message),0,osWaitForever);
snprintf(response, sizeof(response), "LED OFF SUCESS");
SendResponse(response);
}
static void prvHandLedStatus_ON(void) {
char response[100]={0};
//LEDMessage *message=malloc(sizeof(LEDMessage));/*使用单片机的内存,需要使用对应的函数进行free释放内存*/
LedMessage *message=pvPortMalloc(sizeof(LedMessage));/*使用freeRTOS分配的内存,需要使用对应的pvfree释放内存*/
message->color=1;//
message->state=1;//开灯成功
// LEDMessage*pMessage =&message;
osMessageQueuePut(LedQueueHandle,(&message),0,osWaitForever);
snprintf(response, sizeof(response), "LED ON SUCESS");
SendResponse(response);
}
/* 响应发送统一封装 ----------------------------------------------------------------------------------*/
void SendResponse(const char* resp) {
HAL_UART_Transmit(&huart2, (uint8_t*)resp, strlen(resp), 1000);
}
//.h文件
#ifndef __UPPERTASK_H
#define __UPPERTASK_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
void usart2_receive_start(void);
/* Private defines -----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* __UPPERTASK_H */
4.ledTask文件——用于控制灯的亮灭及其颜色。
//.c文件
#include "ledTask.h"
void LedStartTask(void *argument)
{
/* Infinite loop */
for(;;)
{
LedMessage *message;
osMessageQueueGet(LedQueueHandle,&message,0,osWaitForever);
switch(message->color)
{
case 0:
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,message->state?GPIO_PIN_SET:GPIO_PIN_RESET);
break;
case 1:
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,message->state?GPIO_PIN_SET:GPIO_PIN_RESET);
break;
}
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
//osDelay(2000);
}
}
//.h文件
#ifndef __LEDTASK_H
#define __LEDTASK_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* __LEDTASK_H */
四、串口调试结果——成功控制。


---------------------------------------------------------------------------------------------------------------------------------
愿学者在学习的路上不迷路~
以上仅仅属于本人学习心得,可供学习参考,禁止商用~
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)