• STM32 串口DMA方式接收(转)


    STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M。最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USART1~USART5),支持DMA方式通信,DMA方式由于不需要CPU的参与,而是直接由DMA控制器完成串口数据的读写,因而可以很大程度的提高CPU的利用率。在使用STM32串口之前需要做一系列的初始化工作:

    1.RCC(复位和时钟控制寄存器)初始化,启用GPIO、DMA、USART时钟。

    2.NVIC(嵌套向量中断控制寄存器)初始化,完成各个硬件中断的配置。

    3.USART初始话,配置串口,设置DMA通道等。

    4.DMA初始化,完成DMA的配置。

    最后是使能USART和DMA。下面是通过DMA的方式从串口USART1接收数据,STM32工作后串口数据由DMA控制器接收存到指定buffer,读取数据直接从DMA buffer中读取即可。发送数据采用非DMA方式,首先将待发送的数据存入到发送队列,然后在任务循环中将队列中的数据发送给USART1。实例代码如下:

      1 //**********************************************************************************************
      2 //  STM32F10x USART Test
      3 //  compiler: Keil UV3
      4 //  2011-03-28 , By friehood
      5 //**********************************************************************************************
      6 static int8u rDMABuffer[64];   // DMA buffer
      7 static int16u rDMARear = sizeof(rDMABuffer); 
      8 
      9 static int8u USART_RevBuf[64]; // 串口接收buffer
     10 static int8u USART_SndBuf[64]; // 串口发送buffer
     11 static int8u Head=0,Tail=0;    // 发送buffer的头尾
     12 
     13 
     14 // 串口任务
     15 void Task_USART(void)
     16 {
     17     int16u end;
     18     if (USART1->SR & (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE))
     19     {
     20         USART_ReceiveData(USART1);
     21     }
     22 
     23     // DMA接收
     24     end = DMA_GetCurrDataCounter(DMA1_Channel5);
     25     /*if((sizeof(rDMABuffer)-end)>0)
     26         dbgprt("DMA available datalen=%d/n",sizeof(rDMABuffer)-end); */
     27     while(rDMARear != end)
     28     {
     29         USART_receive(rDMABuffer[sizeof(rDMABuffer)-rDMARear]);
     30         if (!(--rDMARear))
     31         {
     32             rDMARear = sizeof(rDMABuffer);
     33         }
     34     }
     35 
     36     //发送
     37     if(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET)
     38     {
     39         int8u chr;
     40         // 从发送队列取出一个字符
     41         if(PopFront(&chr))
     42         {
     43             USART_SendData(USART1, chr);
     44             dbgprt("USART_SendData:0x%02x/n",chr);
     45             while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
     46               {
     47               }
     48         }
     49     }
     50 }
     51 
     52 
     53 // USART串口初始化
     54 void dev_USART_init(void)
     55 {
     56     USART_InitTypeDef USART_InitStructure;
     57     GPIO_InitTypeDef  GPIO_InitStructure;
     58     DMA_InitTypeDef   DMA_InitStructure;
     59 
     60     /* DMA1 Channel5 (triggered by USART1 Rx event) Config */        //参见 STM32 datasheet
     61     DMA_DeInit(DMA1_Channel5);  
     62     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
     63     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)rDMABuffer;
     64     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
     65     DMA_InitStructure.DMA_BufferSize = sizeof(rDMABuffer);
     66     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     67     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
     68     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
     69     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
     70     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
     71     DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
     72     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
     73     DMA_Init(DMA1_Channel5, &DMA_InitStructure);
     74 
     75     USART_InitStructure.USART_BaudRate = 9600;
     76     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
     77     USART_InitStructure.USART_StopBits = USART_StopBits_1;
     78     USART_InitStructure.USART_Parity = USART_Parity_No;
     79     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
     80     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
     81 
     82     //配置IO: GPIOA9和GPIOA10分别作为串口TX、RX端。  见STM32 datasheet
     83     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     84     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     85     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
     86     GPIO_Init(GPIOA,&GPIO_InitStructure);
     87 
     88     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     89     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
     90     GPIO_Init(GPIOA,&GPIO_InitStructure);
     91 
     92     /* Configure USART1 */
     93     USART_Init(USART1, &USART_InitStructure);
     94     /* Enable USART1 DMA Rxrequest */
     95     USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
     96     /* Enable DMA1 Channel5 */
     97       DMA_Cmd(DMA1_Channel5, ENABLE);
     98     /* Enable the USART1 */
     99     USART_Cmd(USART1, ENABLE);
    100 }
    101 
    102 // 向串口发送数据
    103 void USART_send(const int8u *pBuf, int8u len)
    104 {
    105     int i;
    106     if(pBuf == NULL)
    107     {
    108         return;
    109     }
    110        // 将数据压入到发送队列
    111     dbgprt("USART_PushBack:");
    112     for(i=0;i<len;i++)
    113     {
    114            PushBack(*pBuf);
    115         dbgprt("0x%02x ",*pBuf);
    116         pBuf++;
    117     }
    118     dbgprt("/n");
    119 }
    120 
    121 // 向发送队列尾部插入一个字节
    122 void PushBack(int8u byte)
    123 {
    124     USART_SndBuf[Tail++]= byte;
    125     if(Tail >= ARRAYSIZE(USART_SndBuf))
    126         Tail = 0;
    127     if(Tail == Head)
    128         Head = Tail+1;      
    129 }
    130 
    131 // 从发送队列头部取出一个字节
    132 bool PopFront(int8u *byte)
    133 {
    134     if(Head >= ARRAYSIZE(USART_SndBuf))
    135         Head = 0;
    136     if(Head == Tail)
    137         return FALSE;
    138     *byte = USART_SndBuf[Head++];
    139     return TRUE;
    140 }
    141 
    142 // 处理接收到的串口数据
    143 void USART_receive(int8u byte)
    144 {
    145     // Treate received data
    146     // Place Code here
    147         // ...
    148 }
    149 
    150 // CRC校验
    151 bool CheckCRC(const int8u *str, int8u len, const int8u *crcstr)
    152 {
    153     int8u checkSum;
    154     if(str == NULL || crcstr== NULL)
    155         return FALSE;
    156     GetCRC(str,len,&checkSum);
    157     if(checkSum != *crcstr)
    158         return FALSE;
    159     else
    160         return TRUE;
    161 }
    162 
    163 // 获取CRC
    164 bool GetCRC(const int8u *str, int8u len, int8u *crcstr)
    165 {
    166     int8u i;
    167     int8u checkSum;
    168     if(str == NULL || crcstr== NULL)
    169         return FALSE;
    170     checkSum = *str;
    171     for(i=1; i<len; i++)
    172     {
    173         checkSum ^= *(str+i);
    174     }
    175     *crcstr = checkSum;
    176     return TRUE;
    177 }
  • 相关阅读:
    下雪诗
    华视身份证阅读器100UC HTTP模式二次开发
    C# Action 和 Func 区别
    网站部署——文件系统
    前端-JavaScript DOM和BOM
    IO多路复用
    python-协程
    python-线程
    python-进程
    计算机与操作系统简介
  • 原文地址:https://www.cnblogs.com/skl374199080/p/3524596.html
Copyright © 2020-2023  润新知