wenbo2005.online

学习记录 / STM32

USART+DMA

STM322025-05-13

串口实现USART的接受与发送:

(一),开启串口1,开启RX 与 TX 的DMA通道,默认即可;

(二),开启串口中断,并且保证 两个DMA通道 与 串口 的中断等级一致,如1;

例如:

USART空闲中断:优先级0 DMA接收中断(半满/满传输):优先级0

DMA发送中断:优先级2(更低)

最佳实践​:将串口接收中断与RX DMA中断设为相同最高优先级​(如0),且均高于发送中断

(三),添加代码:

注意:DMA 编号小的通道优先级高!!

在 stm32f1xx_it.c 中添加如下代码:

#define BUFFERSIZE 255    //可接收的最大数据量
extern uint8_t Rx_len ;
extern uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区
extern uint32_t rx_time ;

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 */
    uint32_t temp;
    if(USART1 == huart1.Instance)//判断是否为串口1中断
    {
        if(RESET != __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))//如果为串口1空闲
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart1);                    //清除中断标志
            HAL_UART_DMAStop(&huart1);                            //停止DMA接收
            temp  = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);            //获取DMA当前还有多少未填充
            Rx_len =  BUFFERSIZE - temp;                             //计算串口接收到的数据个数
//            HAL_UART_Transmit_DMA(&huart1,ReceiveBuff,Rx_len);        //发送数据,引起发送回调函数(将数据回传)
            rx_time = uwTick;
//            Rx_len=0;//接收数据长度清零
            HAL_UART_Receive_DMA(&huart1,ReceiveBuff,BUFFERSIZE);        //开启下一次接收
        }  
    }
  /* USER CODE END USART1_IRQn 1 */
}

在 main.c 中添加代码:

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能串口1 IDLE中断
HAL_UART_Receive_DMA(&huart1,ReceiveBuff,BUFFERSIZE);//使能接收

#define BUFFERSIZE 255//可以接收的最大字符个数
uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区
uint8_t Rx_len;//接收完成中断标志,接收到的字符长度
extern DMA_HandleTypeDef hdma_usart1_rx;

//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)        //发送回调函数
//{
//    if(huart==&huart1)//判断是否是串口1中断
//    {
//        Rx_len=0;
//        memset(ReceiveBuff,'\0',sizeof(ReceiveBuff));
//    }
//}

void Rx_proc()
{
    if(uwTick - rx_time<80)
    rx_time = uwTick;

    if(Rx_len > 0 )
    {  
        //接收判断区
        if(ReceiveBuff[0]=='1' && ReceiveBuff[1]=='2'&& ReceiveBuff[2]=='3' && ReceiveBuff[5]=='2')
        {
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//引脚C13电平反转
            HAL_UART_Transmit_DMA(&huart1,ReceiveBuff,Rx_len);
        }
        Rx_len=0;
        memset(ReceiveBuff,'\0',sizeof(ReceiveBuff));
    }
}

可以只开启接收中断,发送用printf :

void Rx_proc()
{
    if(uwTick - rx_time<80)
    rx_time = uwTick;

    if(Rx_len > 0 )
    {  
        //接收判断区
        if(ReceiveBuff[0]=='1' && ReceiveBuff[1]=='2'&& ReceiveBuff[2]=='3' && ReceiveBuff[5]=='2')
        {
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//引脚C13电平反转
            printf("%s\r\n",ReceiveBuff);
        }
        Rx_len=0;
        memset(ReceiveBuff,'\0',sizeof(ReceiveBuff));
    }
}