概述
STM32微控制器广泛用于嵌入式系统,其HAL(Hardware Abstraction Layer)库简化了硬件访问,提高了开发效率。在STM32中,使用DMA(Direct Memory Access)进行串口通信可以显著提高数据传输效率,减少CPU负载。本文将介绍如何在STM32中正确使用串口DMA空闲中断,并解析SBUS信号。
串口DMA空闲中断
在STM32中,串口DMA传输完成后,可以通过配置空闲中断(IDLE interrupt)来处理接收到的数据。空闲中断在接收到的数据帧之间检测到空闲信号时触发。
1. 配置DMA和串口
首先,需要配置串口和DMA以实现数据的接收。
#include "stm32f4xx_hal.h"
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
void MX_USART2_UART_Init(void) {
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
}
void MX_DMA_Init(void) {
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_usart2_rx.Instance = DMA1_Stream5;
hdma_usart2_rx.Init.Channel = DMA_CHANNEL_7;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart2_rx);
__HAL_LINKDMA(&huart2, hdmarx, hdma_usart2_rx);
}
2. 启用空闲中断
在初始化串口时,需要启用空闲中断。
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance == USART2) {
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
}
3. 处理空闲中断
在中断服务例程中处理空闲中断。
void USART2_IRQHandler(void) {
HAL_UART_IRQHandler(&huart2);
}
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART2) {
// 处理接收到的数据
}
}
解析SBUS信号
SBUS是一种串行总线协议,常用于遥控飞机和无人机。SBUS信号解析包括读取数据、解码和应用。
1. 读取SBUS数据
使用DMA接收SBUS数据。
uint8_t sbus_data[25]; // SBUS数据帧大小为25字节
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART2) {
// 解析SBUS数据
parse_sbus(sbus_data);
HAL_UART_Receive_DMA(&huart2, sbus_data, 25);
}
}
2. 解析SBUS数据
解析SBUS数据帧,提取控制信号。
void parse_sbus(uint8_t *data) {
int16_t channels[16];
for (int i = 0; i < 16; i++) {
channels[i] = (data[2 * i] << 8) | data[2 * i + 1];
channels[i] -= 172; // 偏移量
channels[i] = (channels[i] * 100) / 33; // 缩放
}
// 应用控制信号
}
注意事项
- DMA配置:确保DMA配置正确,包括通道、优先级和数据对齐。
- 中断优先级:合理配置中断优先级,避免中断冲突。
- 数据同步:在多任务环境中,注意数据同步和互斥。
通过上述步骤和代码示例,你应该能够在STM32中正确使用串口DMA空闲中断,并解析SBUS信号。这为开发高性能的嵌入式系统提供了有力支持。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇