HAL库STM32CubeMX_串口DMA空闲中断接收
主要转载来自【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)(仅供学习交流,侵删)
主要是为了简单记录一下,以便后日使用。
CubeMX配置
代码修改
usart.c
- 前面添加相关定义
/* USER CODE BEGIN 0 */
volatile uint8_t rx_len = 0; //接收一帧数据的长度
volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志
uint8_t rx_buffer[BUFFER_SIZE]={0}; //接收数据缓存数组
/* USER CODE END 0 */
- 在
void MX_USART1_UART_Init(void)
中添加
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//开启第一次的接收
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
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();
}
/* USER CODE BEGIN USART1_Init 2 */
//下方为自己添加的代码
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度
/* USER CODE END USART1_Init 2 */
}
usart.h
- 添加相关定义
/* USER CODE BEGIN Private defines */
#define BUFFER_SIZE 10
extern volatile uint8_t rx_len ; //接收到一帧数据的长度
extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志
extern uint8_t rx_buffer[BUFFER_SIZE]; //接收数据缓存数组
/* USER CODE END Private defines */
stm32f1xx_it.c
- 在前面添加引用
#include “usart.h”
- 在
void USART1_IRQHandler(void)
中添加
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_DMAStop(&huart1);
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
rx_len = BUFFER_SIZE - temp;
recv_end_flag = 1;
}
#include "usart.h"
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
//temp = huart1.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
//temp = huart1.Instance->DR; //读取数据寄存器中的数据
//这两句和上面那句等效
HAL_UART_DMAStop(&huart1); //
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数
//temp = hdma_usart1_rx.Instance->NDTR;//读取NDTR寄存器 获取DMA中未传输的数据个数,
//这句和上面那句等效
rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
使用例:
#include <string.h>
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
if(recv_end_flag == 1){
//如果两个字符串的长度和内容一样,返回0
if(strcmp(rx_buffer,"hello")==0){//若收到“hello”,发送“yes”
HAL_UART_Transmit_DMA(&huart1, "yes", 3);
}
memset(rx_buffer, 0, rx_len);//清空接收到的内容
rx_len = 0;//清除计数
recv_end_flag = 0;//清除接收结束标志位
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
再次申明:主要转载来自【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)(仅供学习交流,侵删)