CUBEMX配置
开启USART2全局中断
DMA配置如图
代码
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RECEIVE_DATA,LEN); //重新启动接受
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT); //关闭传输过半中断(要写!!)
将上面代码放入USER CODE 2注释对中,此注释对在main之后,while循环之前
调用HAL_UARTEx_RxEventCallback函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
rx_len = LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx); //获取接受数组长度
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RECEIVE_DATA,LEN); //重新启动接受
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT); //关闭传输过半中断(要写!!)
}
这里如果报错没有找到hdma_usart2_rx这个变量
extern DMA_HandleTypeDef hdma_usart2_rx;
将这段代码放入你使用的.c对应的.h文件中即可
拓展理解(只需要DMA接收不定长数据的可以不看)
1、extern DMA_HandleTypeDef hdma_usart2_rx; 使用CubeMX生成会导致改变量定义在usart.c文件中,所以需要继承一下
2、这里HAL_UARTEx_ReceiveToIdle_DMA必须要用HAL_UARTEx_RxEventCallback接收,拓展库的对应拓展库的回调,如果你使用的是HAL_UART_Receive_DMA则需要手动开启以下中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //空闲中断
之后再USART2_IRQHandle中修改代码,以下代码很简单自己理解一下(总之不如上面简单
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
USER_UART_IRQHandler(&huart2);
/* USER CODE END USART2_IRQn 1 */
}
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{ // 判断是否是串口2
if(USART2 == huart2.Instance)
{ // 判断是否是空闲中断
if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))
{ // 清除空闲中断标志(否则会一直不断进入中断)
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
// 调用中断处理函数
USAR_UART_IDLECallback(huart);
}
}
}
extern uint8_t RECEIVE_DATA[LEN];
void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)
{
HAL_UART_DMAStop(&huart2);
uint8_t data_length = LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
HAL_UART_Receive_DMA(&huart2, (uint8_t*)RECEIVE_DATA, LEN);
}
3、介绍一下传输完成中断HAL_UART_RxCpltCallback。一句话:能够进入回调函数HAL_UART_RxCpltCallback的条件之一:接收到的data_buff数据的大小 = 你设定的接收数据的大小此时才能触发串口中断进入回调函数。