1.使能对应DMA时钟&中断
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}//注意,DMA优先级要高于串口中断
2.初始化DMA&串口
void USART3_UART_Init(u32 bound)
{
UART3_Handler.Instance = USART3; //UART3
UART3_Handler.Init.BaudRate = bound; //波特率
UART3_Handler.Init.WordLength = UART_WORDLENGTH_8B; //长度
UART3_Handler.Init.StopBits = UART_STOPBITS_1; //停止位1位
UART3_Handler.Init.Parity = UART_PARITY_NONE; //无奇偶校验
UART3_Handler.Init.Mode = UART_MODE_TX_RX; //收发模式
UART3_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控制
UART3_Handler.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&UART3_Handler) != HAL_OK)
{
}
// HAL_UART_Receive_IT(&UART3_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量(使用回调函数处理中断需要调用该函数)
// UART3_Handler.State=HAL_UART_STATE_READY;
__HAL_UART_ENABLE_IT(&UART3_Handler, UART_IT_IDLE);//使能idle中断
HAL_UART_Receive_DMA(&UART3_Handler,rx3_buffer,BUFFER_SIZE);//打开DMA接收,数据存入rx_buffer数组中。
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART3)//如果是串口3,进行串口3 MSP初始化
{
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
__HAL_RCC_USART3_CLK_ENABLE(); //使能USART3时钟
GPIO_Initure.Pin=GPIO_PIN_10; //PB10
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART3; //复用为USART1
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB10
GPIO_Initure.Pin=GPIO_PIN_11; //PB11
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB11
// __HAL_UART_DISABLE_IT(huart,UART_IT_TC);
/* USART3 DMA Init */
/* USART3_RX Init */
hdma_usart3_rx.Instance = DMA1_Stream1;
hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_rx.Init.Mode = DMA_NORMAL;
hdma_usart3_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK)
{
;//_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
// __HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); //开启接收中断
// HAL_NVIC_SetPriority(USART3_IRQn,2,0); //抢占优先级3,子优先级3
// HAL_NVIC_EnableIRQ(USART3_IRQn); //使能USART1中断通道
}
}
3.修改中断函数
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&UART3_Handler,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&UART3_Handler);//清除标志位
temp = UART3_Handler.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
temp = UART3_Handler.Instance->DR; //读取数据寄存器中的数据
HAL_UART_DMAStop(&UART3_Handler); //
if(rx3_buffer[0]!=0 && strlen((char *)rx3_buffer) > 2)
{
temp = hdma_usart3_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
rx3_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv3_end_flag = 1; // 接受完成标志位置1
if( rx3_len < BUFFER_SIZE)
{
rx3_buffer[rx3_len]= 0; /*此次数据最后一个*/
}
else
rx3_buffer[BUFFER_SIZE-1]= 0; /*接收BUF最后一个*/
}
if(BUFFER_SIZE == rx3_len)
{
__HAL_USART_ENABLE_IT( &UART3_Handler,USART_IT_RXNE);
}
else
{
HAL_UART_Receive_DMA(&UART3_Handler,rx3_buffer,BUFFER_SIZE);//重新打开DMA接收
}
}
if(__HAL_USART_GET_FLAG( &UART3_Handler, USART_IT_RXNE) != RESET)
{
__HAL_USART_CLEAR_FLAG( &UART3_Handler, USART_IT_RXNE);
__HAL_USART_DISABLE_IT( &UART3_Handler, USART_IT_RXNE);
HAL_UART_Receive_DMA(&UART3_Handler,rx3_buffer,BUFFER_SIZE);//重新打开DMA接收
}
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&UART3_Handler);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}