stm32串口数据中断接收(DMA、IDLE中断)

  对于stm32串口程序的编写,最好的方式还是看寄存器手册,了解寄存器的配置。对于常规的一些应用,自己设置了个模板,在此记录下来。因个人习惯,本人不喜欢在串口收发数据中定义特殊字段,如结束字符,故,串口数据接收完成均由IDLE中断实现。

一、基于HAL库的串口1的DMA中断接收

   1、环境配置

  工程模板直接使用cubMax导出的keil工程,对dma.c中内容不做更改,保留函数:

void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  /* DMA interrupt init */
  /* DMA2_Stream5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
  /* DMA2_Stream7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
  2、串口相关配置代码如下
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;

uint8_t get_data=0;
uint8_t rx_buffer[USART_REC_LEN];
/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  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_MultiProcessor_Init(&huart1, 0, UART_WAKEUPMETHOD_IDLELINE) != HAL_OK)
  {
    Error_Handler();
  }
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
 
  __HAL_UART_CLEAR_FLAG(&huart1,UART_IT_IDLE);
//  __HAL_UART_ENABLE_IT(&huart1,UART_IT_TXE);
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {

    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
  __HAL_RCC_DMA2_CLK_ENABLE();
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA2_Stream5;
    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_usart1_rx.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    hdma_usart1_rx.Init.MemBurst=DMA_MBURST_SINGLE;                 //?????????
    hdma_usart1_rx.Init.PeriphBurst=DMA_PBURST_SINGLE;              //????????  
 
  HAL_DMA_DeInit(&hdma_usart1_rx);
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

    hdma_usart1_tx.Instance = DMA2_Stream7;
    hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

    HAL_NVIC_SetPriority(USART1_IRQn, 2, 2);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
 
  __HAL_DMA_ENABLE_IT(&hdma_usart1_tx,DMA_IT_TC);
  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn , 0, 1);
    HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn );
 
  __HAL_DMA_ENABLE_IT(&hdma_usart1_rx,DMA_IT_TC);
  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn , 0, 1);
    HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
 
  HAL_UART_Receive_DMA(&huart1,rx_buffer,256);
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    HAL_DMA_DeInit(uartHandle->hdmarx);
    HAL_DMA_DeInit(uartHandle->hdmatx);

    HAL_NVIC_DisableIRQ(USART1_IRQn);

  }
}

void USART1_IRQHandler(void)
{
 //   HAL_UART_IRQHandler(&huart1);    //??HAL?????????
    if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET) //??IDLE???
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
    HAL_UART_DMAStopRx(&huart1);
    //------------------------------------------------------------------------------------
    get_data=USART_REC_LEN-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    HAL_UART_Transmit_DMA(&huart1,(uint8_t*)rx_buffer,get_data);
    //------------------------------------------------------------------------------------
    HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buffer,USART_REC_LEN);  //??????
    //------------------------------------------------------------------------------------
    printf("dma Rx\r\n");
    //------------------------------------------------------------------------------------
    }
}

void DMA2_Stream7_IRQHandler(void)
{
  if(__HAL_DMA_GET_FLAG(&hdma_usart1_tx,DMA_FLAG_TCIF3_7))//�ȴ�DMA2_Steam7�������
  {
    __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx,DMA_FLAG_TCIF3_7);//���DMA2_Steam7������ɱ�־
    HAL_UART_DMAStopTx(&huart1);      //��������Ժ�رմ���DMA
    //------------------------------------------------------------------------------------
    printf("dma Tx\r\n");
    //------------------------------------------------------------------------------------
  }
}

void DMA2_Stream5_IRQHandler(void)
{
  printf("get data\r\n");
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
 
  3、main函数内容如下
int main(void)
{
  uint8_t len,len_new;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  HAL_UART_Receive_DMA(&huart1,rx_buffer,256);
  while (1)
  {
//    HAL_UART_Transmit_DMA(&huart1,TEXT_TO_SEND,sizeof(TEXT_TO_SEND));//��������

//    HAL_Delay(1000);

  }
}
 

二、基于标准库的串口1的DMA中断接收

  1、基本环境:基于原子代码修改

u8  ReceiveBuff[RECEIVE_BUF_SIZE];   //????
u8  SendBuff[SEND_BUF_SIZE];    //???????
 
u16 UART1_ReceiveSize = 0;
 
void uart_init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    DMA_InitTypeDef  DMA_InitStructure;
 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //??GPIOA??
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//??USART1??
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2????
 
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9???USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10???USART1
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9?GPIOA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//????
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //??50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //??????
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //??
    GPIO_Init(GPIOA,&GPIO_InitStructure); //???PA9,PA10
 
    //USART1 ?????
    USART_InitStructure.USART_BaudRate = bound;//?????
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//???8?????
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//?????
    USART_InitStructure.USART_Parity = USART_Parity_No;//??????
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//????????
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //????
    USART_Init(USART1, &USART_InitStructure); //?????1
 
    USART_Cmd(USART1, ENABLE);  //????1
 
    //USART_ClearFlag(USART1, USART_FLAG_TC);
   
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//??????
 
    //Usart1 NVIC ??
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//??1????
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//?????3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;       //????3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ????
    NVIC_Init(&NVIC_InitStructure); //??????????VIC????
 
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //????1?DMA??  
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);  //????1?DMA??
 
 
    //****************************??UART1??
    DMA_DeInit(DMA2_Stream7);
    while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);//??DMA???
    /* ?? DMA Stream */
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;  //????
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA????
    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SendBuff;//DMA ???0??
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//????????
    DMA_InitStructure.DMA_BufferSize = SEND_BUF_SIZE;//?????
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//???????
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//???????
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//??????:8?
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//???????:8?
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// ??????
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//?????
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//?????????
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//????????
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);//???DMA Stream
    //DMA NVIC  
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);  
    DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
 
    //****************************??UART1??
    DMA_DeInit(DMA2_Stream5);
    while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);//??DMA???
    /* ?? DMA Stream */
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;  //????
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA????
    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ReceiveBuff;//DMA ???0??
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;//????????
    DMA_InitStructure.DMA_BufferSize = RECEIVE_BUF_SIZE;//?????
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//???????
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//???????
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//??????:8?
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//???????:8?
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// ??????
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//?????
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//?????????
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//????????
    DMA_Init(DMA2_Stream5, &DMA_InitStructure);//???DMA Stream
    //DMA NVIC  
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);  
    DMA_Cmd(DMA2_Stream5, ENABLE);  //??DMA??
   
    DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);
   
}
 
void DmaSendDataProc(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{
 
    DMA_Cmd(DMA_Streamx, DISABLE);                      //??DMA??
   
    while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}  //??DMA?????  
       
    DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //?????  
 
    DMA_Cmd(DMA_Streamx, ENABLE);                      //??DMA??
}    

//��������ֱ��װ�뷢��buffer�У��˴�ֻ�Ǵ���DMA����
//��ο�USB����cdc����÷��޸�Ϊд��buffer����ʽ��
void Uart1_DMATranmist(u16 nSendCount)
{
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //ʹ�ܴ���1��DMA����    
    DmaSendDataProc(DMA2_Stream7,nSendCount); //????DMA??!    
}
 
void DMA2_Stream7_IRQHandler(void)//DMA �����������
{
    if(DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7)!=RESET)
    {
        DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);//DMA ������������жϱ�־���
    }
}

void DMA2_Stream5_IRQHandler(void)
{
    if(DMA_GetFlagStatus(DMA2_Stream5,DMA_FLAG_TCIF5)!=RESET)//��������ж�
    {
        DMA_Cmd(DMA2_Stream5, DISABLE);
 
        UART1_ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream5);//��ȡ�������ݵĴ�С
        if(UART1_ReceiveSize !=0)
        {
            //�ڴ˴����ӽ������ݴ���
            printf("get data=%s=%d\r\n",ReceiveBuff,UART1_ReceiveSize);
        }
       
        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//??DMA2_Steam7??????
        DMA_SetCurrDataCounter(DMA2_Stream5, RECEIVE_BUF_SIZE);
        DMA_Cmd(DMA2_Stream5, ENABLE);    
    }
}

void USART1_IRQHandler(void)
{
    u16 data;
    if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
    {
        DMA_Cmd(DMA2_Stream5, DISABLE); //??DMA,?????????
 
        data = USART1->SR;
        data = USART1->DR;
       
        UART1_ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream5);
        if(UART1_ReceiveSize !=0)
        {
            //�����������ݲ������˴�
            //printf("hello=%s\r\n",ReceiveBuff);
        }
        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//??DMA2_Steam7??????
        DMA_SetCurrDataCounter(DMA2_Stream5, RECEIVE_BUF_SIZE);
        DMA_Cmd(DMA2_Stream5, ENABLE);     //??DMA,
 
    }
}

2、main函数:

int main(void)
{
 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//����ϵͳ�ж����ȼ�����2
    delay_init(168);        //��ʱ��ʼ��
    uart_init(115200);  //���ڳ�ʼ��������Ϊ115200

   
    j=sizeof(TEXT_TO_SEND);    
    for(i=0;i<SEND_BUF_SIZE;i++)//���ASCII�ַ�������
    {
        if(t>=j)//���뻻�з�
        {
            if(mask)
            {
                SendBuff[i]=0x0a;
                t=0;
            }else
            {
                SendBuff[i]=0x0d;
                mask++;
            }  
        }else//����TEXT_TO_SEND���
        {
            mask=0;
            SendBuff[i]=TEXT_TO_SEND[t];
            t++;
        }          
    }
   
    while(1)
    {
        //SendBytesInfoProc(SEND_BUF_SIZE);
        delay_ms(3000);
    }
}
posted @   511442592  阅读(1691)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示