本文参考了STM32论坛应用笔记,由于原笔记修改了底层HAL库,Cube更新代码时会导致修改被覆盖,因此,在原笔记基础上做了修改。
理论上本笔记适用于所有带IDLE中断的MCU。
这里以STM32L051为例
首先配置Cube工程如下:
启用串口接收DMA
启用串口中断
接下来时代码部分:
首先在main函数初始化后插入:
HAL_UART_Receive_DMA(&huart1, __UART_RX_Buf, __BUFFER_SIZE);
/* Enable the UART IDLE Interrupt*/
SET_BIT(huart1.Instance->CR1, USART_CR1_IDLEIE);//启用IDLE中断
原文中启用IDLE中断代码位于HAL_UART_Receive_DMA函数内,这里移出来,避免修改底层程序,就不怕Cube更新工程时代码覆盖了
在uart.c开头插入:
uint8_t __UART_RX_Buf[__BUFFER_SIZE] = {0};
uint32_t __Rev_Size = 0;
为了方便跨文件调用,在uart.h插入
#define __BUFFER_SIZE 50 //可根据情况设置,要大于可能最长的一帧
extern uint8_t __UART_RX_Buf[__BUFFER_SIZE];
extern uint32_t __Rev_Size;
在stm32l0xx_it.c文件中的USART1_IRQHandler函数专门为用户预留了插入代码空间,刚好可以把我们需要的功能插入:
/**
* @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
UART_HandleTypeDef *huart = &huart1;
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
//Modification 2
if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
{
//Record the received bytes number
__Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->CNDTR;
//clear the IDLE flag
__HAL_UART_CLEAR_IDLEFLAG(huart);
//Abord the received process
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));
HAL_UART_AbortReceive_IT(huart);
// return;
}
/* USER CODE END USART1_IRQn 1 */
}
注意原笔记基于F4,与L0有区别:
串口寄存器
F4
USART_SR_IDLE
STM32L051为
USART_ISR_IDLE
DMA中寄存器,F4为
huart->hdmarx->Instance->NDTR
STM32L051为
huart->hdmarx->Instance->CNDTR
接下来定义回调函数,这里会在一帧数据成功接收后被调用
void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)
{
//Print received Bytes
printf("nr[IDLE]Received %d Bytes:",__Rev_Size);
for(uint16_t i = 0; i < __Rev_Size; i++)
{
printf(" 0x%02X", __UART_RX_Buf
);
}
HAL_UART_Transmit(huart, __UART_RX_Buf, __Rev_Size, 100);
//Re-start receiving
HAL_UART_Receive_DMA(huart, __UART_RX_Buf, __BUFFER_SIZE);
/* Enable the UART IDLE Interrupt*/
SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
至此,修改完成。
本文参考了STM32论坛应用笔记,由于原笔记修改了底层HAL库,Cube更新代码时会导致修改被覆盖,因此,在原笔记基础上做了修改。
理论上本笔记适用于所有带IDLE中断的MCU。
这里以STM32L051为例
首先配置Cube工程如下:
启用串口接收DMA
启用串口中断
接下来时代码部分:
首先在main函数初始化后插入:
HAL_UART_Receive_DMA(&huart1, __UART_RX_Buf, __BUFFER_SIZE);
/* Enable the UART IDLE Interrupt*/
SET_BIT(huart1.Instance->CR1, USART_CR1_IDLEIE);//启用IDLE中断
原文中启用IDLE中断代码位于HAL_UART_Receive_DMA函数内,这里移出来,避免修改底层程序,就不怕Cube更新工程时代码覆盖了
在uart.c开头插入:
uint8_t __UART_RX_Buf[__BUFFER_SIZE] = {0};
uint32_t __Rev_Size = 0;
为了方便跨文件调用,在uart.h插入
#define __BUFFER_SIZE 50 //可根据情况设置,要大于可能最长的一帧
extern uint8_t __UART_RX_Buf[__BUFFER_SIZE];
extern uint32_t __Rev_Size;
在stm32l0xx_it.c文件中的USART1_IRQHandler函数专门为用户预留了插入代码空间,刚好可以把我们需要的功能插入:
/**
* @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
UART_HandleTypeDef *huart = &huart1;
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
//Modification 2
if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
{
//Record the received bytes number
__Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->CNDTR;
//clear the IDLE flag
__HAL_UART_CLEAR_IDLEFLAG(huart);
//Abord the received process
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));
HAL_UART_AbortReceive_IT(huart);
// return;
}
/* USER CODE END USART1_IRQn 1 */
}
注意原笔记基于F4,与L0有区别:
串口寄存器
F4
USART_SR_IDLE
STM32L051为
USART_ISR_IDLE
DMA中寄存器,F4为
huart->hdmarx->Instance->NDTR
STM32L051为
huart->hdmarx->Instance->CNDTR
接下来定义回调函数,这里会在一帧数据成功接收后被调用
void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)
{
//Print received Bytes
printf("nr[IDLE]Received %d Bytes:",__Rev_Size);
for(uint16_t i = 0; i < __Rev_Size; i++)
{
printf(" 0x%02X", __UART_RX_Buf
);
}
HAL_UART_Transmit(huart, __UART_RX_Buf, __Rev_Size, 100);
//Re-start receiving
HAL_UART_Receive_DMA(huart, __UART_RX_Buf, __BUFFER_SIZE);
/* Enable the UART IDLE Interrupt*/
SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
至此,修改完成。
举报