新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 串口DMA方式接收

        STM32 串口DMA方式接收

        作者: 時間:2016-11-19 來源:網絡 收藏
        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。實例代碼如下:
        [cpp] view plaincopy
        //**********************************************************************************************
        // STM32F10x USART Test
        // compiler: Keil UV3
        // 2011-03-28 , By friehood
        //**********************************************************************************************
        static int8u rDMABuffer[64]; // DMA buffer
        static int16u rDMARear = sizeof(rDMABuffer);

        本文引用地址:http://www.104case.com/article/201611/318286.htm

        static int8u USART_RevBuf[64]; // 串口接收buffer
        static int8u USART_SndBuf[64]; // 串口發送buffer
        static int8u Head=0,Tail=0; // 發送buffer的頭尾

        // 串口任務
        void Task_USART(void)
        {
        int16u end;
        if (USART1->SR & (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE))
        {
        USART_ReceiveData(USART1);
        }

        // DMA接收
        end = DMA_GetCurrDataCounter(DMA1_Channel5);
        /*if((sizeof(rDMABuffer)-end)>0)
        dbgprt("DMA available datalen=%d/n",sizeof(rDMABuffer)-end); */
        while(rDMARear != end)
        {
        USART_receive(rDMABuffer[sizeof(rDMABuffer)-rDMARear]);
        if (!(--rDMARear))
        {
        rDMARear = sizeof(rDMABuffer);
        }
        }

        //發送
        if(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET)
        {
        int8u chr;
        // 從發送隊列取出一個字符
        if(PopFront(&chr))
        {
        USART_SendData(USART1, chr);
        dbgprt("USART_SendData:0x%02x/n",chr);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
        {
        }
        }
        }
        }

        // USART串口初始化
        void dev_USART_init(void)
        {
        USART_InitTypeDef USART_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;

        /* DMA1 Channel5 (triggered by USART1 Rx event) Config */ //參見 STM32 datasheet
        DMA_DeInit(DMA1_Channel5);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)rDMABuffer;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = sizeof(rDMABuffer);
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel5, &DMA_InitStructure);

        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        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;

        //配置IO: GPIOA9和GPIOA10分別作為串口TX、RX端。 見STM32 datasheet
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        /* Configure USART1 */
        USART_Init(USART1, &USART_InitStructure);
        /* Enable USART1 DMA Rxrequest */
        USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
        /* Enable DMA1 Channel5 */
        DMA_Cmd(DMA1_Channel5, ENABLE);
        /* Enable the USART1 */
        USART_Cmd(USART1, ENABLE);
        }

        // 向串口發送數據
        void USART_send(const int8u *pBuf, int8u len)
        {
        int i;
        if(pBuf == NULL)
        {
        return;
        }
        // 將數據壓入到發送隊列
        dbgprt("USART_PushBack:");
        for(i=0;i{
        PushBack(*pBuf);
        dbgprt("0x%02x ",*pBuf);
        pBuf++;
        }
        dbgprt("/n");
        }

        // 向發送隊列尾部插入一個字節
        void PushBack(int8u byte)
        {
        USART_SndBuf[Tail++]= byte;
        if(Tail >= ARRAYSIZE(USART_SndBuf))
        Tail = 0;
        if(Tail == Head)
        Head = Tail+1;
        }

        // 從發送隊列頭部取出一個字節
        bool PopFront(int8u *byte)
        {
        if(Head >= ARRAYSIZE(USART_SndBuf))
        Head = 0;
        if(Head == Tail)
        return FALSE;
        *byte = USART_SndBuf[Head++];
        return TRUE;
        }

        // 處理接收到的串口數據
        void USART_receive(int8u byte)
        {
        // Treate received data
        // Place Code here
        // ...
        }

        // CRC校驗
        bool CheckCRC(const int8u *str, int8u len, const int8u *crcstr)
        {
        int8u checkSum;
        if(str == NULL || crcstr== NULL)
        return FALSE;
        GetCRC(str,len,&checkSum);
        if(checkSum != *crcstr)
        return FALSE;
        else
        return TRUE;
        }

        // 獲取CRC
        bool GetCRC(const int8u *str, int8u len, int8u *crcstr)
        {
        int8u i;
        int8u checkSum;
        if(str == NULL || crcstr== NULL)
        return FALSE;
        checkSum = *str;
        for(i=1; i{
        checkSum ^= *(str+i);
        }
        *crcstr = checkSum;
        return TRUE;
        }




          關鍵詞: STM32串口DMA方

          評論


          技術專區

          關閉
          主站蜘蛛池模板: 浦江县| 鹿泉市| 鸡西市| 龙川县| 交口县| 会东县| 高淳县| 墨脱县| 朝阳区| 长垣县| 普安县| 黄浦区| 新安县| 固始县| 龙陵县| 理塘县| 库尔勒市| 繁峙县| 阜南县| 余江县| 乐陵市| 平湖市| 资兴市| 梅河口市| 大宁县| 宽甸| 双柏县| 长丰县| 报价| 威海市| 阿尔山市| 九龙城区| 石台县| 贺兰县| 南乐县| 金堂县| 库车县| 潞城市| 无极县| 巴林右旗| 莆田市|