c
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "main.h"
/*------------------变量和宏-----------------------*/
extern UART_HandleTypeDef huart1; // UART1句柄
extern DMA_HandleTypeDef hdma_usart1_rx; // DMA接收句柄
#define RX_BUFFER_SIZE 128 // 接收缓冲区大小
extern uint8_t rxBuffer[RX_BUFFER_SIZE]; // 接收缓冲区
extern volatile uint8_t commandReady; // 完成标志
extern volatile uint16_t rxLength; // 实际接收到的数据长度
/*------------------函数声明-----------------------*/
// 初始化DMA
void MX_DMA_Init(void);
// 初始化UART1
void MX_USART1_UART_Init(void);
// 自定义空闲中断处理函数
void UASART_EDLE_Interrupt(UART_HandleTypeDef *huart);
// 解析命令
void ParseCommand(uint8_t *command);
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
c
#include "usart.h"
#include <string.h>
#include <stdio.h>
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
uint8_t rxBuffer[RX_BUFFER_SIZE];
volatile uint8_t commandReady = 0;
volatile uint16_t rxLength = 0;
/*------------------------功能函数------------------------------*/
// 重定向printf到USART1
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
// 解析接收到的命令
void ParseCommand(uint8_t *command)
{
// 处理命令
if (strcmp((char *)command, "LED_ON") == 0)
{
printf("LED ON\r\n");
// 在这里添加LED开启的代码
// HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
else if (strcmp((char *)command, "LED_OFF") == 0)
{
printf("LED OFF\r\n");
// 在这里添加LED关闭的代码
// HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
else if (strcmp((char *)command, "STATUS") == 0)
{
printf("System OK, Received: %d bytes\r\n", rxLength);
}
else if (rxLength > 0) // 只有接收到数据才提示未知命令
{
printf("UNKNOWN COMMAND: %s (len=%d)\r\n", command, rxLength);
}
}
/*------------------------中断服务函数(自包含)------------------------------*/
// USART1中断服务函数 - 包含空闲中断处理
void USART1_IRQHandler(void)
{
// 处理标准 UART 中断
HAL_UART_IRQHandler(&huart1);
// 处理空闲中断
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
UASART_EDLE_Interrupt(&huart1);
}
}
// 自定义的函数(没有提供默认的空闲中断回调)
void UASART_EDLE_Interrupt(UART_HandleTypeDef *huart)
{
// 清除空闲中断标志
__HAL_UART_CLEAR_IDLEFLAG(huart);
// 停止 DMA 传输
HAL_UART_DMAStop(huart);
// 计算实际接收到的数据长度
rxLength = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
// 如果接收到了有效数据
if (rxLength > 0)
{
// 去除末尾的换行符或回车符
while (rxLength > 0 && (rxBuffer[rxLength - 1] == '\r' || rxBuffer[rxLength - 1] == '\n'))
{
rxBuffer[--rxLength] = '\0';
}
// 设置命令准备标志
commandReady = 1;
}
// 重新启动 DMA 接收
HAL_UART_Receive_DMA(huart, rxBuffer, RX_BUFFER_SIZE);
}
/*------------------------初始化函数------------------------------*/
// DMA初始化函数
void MX_DMA_Init(void)
{
// 使能DMA1时钟
__HAL_RCC_DMA1_CLK_ENABLE();
// 配置DMA1_Channel5中断优先级
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
// USART1初始化函数
void MX_USART1_UART_Init(void)
{
// 初始化USART1参数
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
printf("USART1 + DMA + IDLE Self-Contained Module Initialized\r\n");
// 清空接收缓冲区
memset(rxBuffer, 0, RX_BUFFER_SIZE);
// 启用空闲中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
// 启动DMA接收
HAL_UART_Receive_DMA(&huart1, rxBuffer, RX_BUFFER_SIZE);
}
// UART MSP初始化函数
void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 判断是哪个USART
if (uartHandle->Instance == USART1)
{
// 使能时钟
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/**USART1 GPIO配置 (STM32F103)
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
// TX引脚 - 复用推挽输出
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// RX引脚 - 浮空输入
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置DMA
hdma_usart1_rx.Instance = DMA1_Channel5; // 指定 DMA 通道为 DMA1_Channel5
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; // 数据传输方向:从外设(USART1_RX)到内存
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址不自增(固定为 USART1 数据寄存器地址)
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; // 内存地址自增(每接收一个字节,存储到下一个内存地址)
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // 外设数据对齐方式:字节对齐
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // 内存数据对齐方式:字节对齐
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR; // 配置为循环模式,DMA 传输结束后自动从头开始
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM; // 设置 DMA 优先级为中等优先级
// 初始化DMA
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
// 关联DMA和UART
__HAL_LINKDMA(uartHandle, hdmarx, hdma_usart1_rx);
// 配置USART1中断优先级
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
// UART MSP解除初始化函数
void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
{
if (uartHandle->Instance == USART1)
{
// 禁用USART1时钟
__HAL_RCC_USART1_CLK_DISABLE();
// 解除GPIO初始化
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
// 解除DMA关联
HAL_DMA_DeInit(uartHandle->hdmarx);
// 禁用中断
HAL_NVIC_DisableIRQ(USART1_IRQn);
HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);
}
}