新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > stm32的串口空閑中斷接收數據

        stm32的串口空閑中斷接收數據

        作者: 時間:2016-11-09 來源:網絡 收藏
        舉個例子:

        1、后臺數據->USART1-> USART2->其它設備,其它設備數據->USART2-> USART1->后臺,這兩個數據過程也可能同時進行。

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

        2、由于硬件的限制,USART1和USART2的傳輸波特率不一樣,比如USART1使用GPRS通信,USART2使用短距離無線通信;或者USART1使用以太網通信,USART2使用485總線通信。

        現在我把我實現的過程簡單描述一下:

        1、 初始化設置:USART1_RX DMA1_ Channel5,USART2_RX DMA1_ Channel6,USART1_TX DMA1_ Channel4,USART2_TX DMA1_ Channel7(具體設置請看程序包)
        2、 當數據發送給USART1接收完畢時候會引起USART1的串口總線中斷,計算DMA1_ Channel5內存數組剩余容量,得到接收的字符長度。將接收的字符給DMA1_ Channel4內存數組,啟動DMA1_ Channel4通道傳輸數據,(傳輸完成需要關閉。)下一次數據接收可以在啟動DMA1_ Channel4時候就開始,不需要等待DMA1_ Channel4數據傳輸完成。但是上一次DMA1_ Channel4完成之前,不可以將數據給DMA1_ Channel4內存數組,會沖掉以前數據。

        3、 USART2類同USART1。

        源程序:

        IO口定義:
        void GPIO_Configuration(void)
        {
        GPIO_InitTypeDef GPIO_InitStructure;
        /* 第1步:打開GPIO和USART部件的時鐘 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        /* 第2步:將USART Tx的GPIO配置為推挽復用模式 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        /* 第3步:將USART Rx的GPIO配置為浮空輸入模式
        由于CPU復位后,GPIO缺省都是浮空輸入模式,因此下面這個步驟不是必須的
        但是,我還是建議加上便于閱讀,并且防止其它地方修改了這個口線的設置參數
        */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        /* 第1步:打開GPIO和USART2部件的時鐘 */
        //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
        /* 第2步:將USART2 Tx的GPIO配置為推挽復用模式 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        /* 第3步:將USART2 Rx的GPIO配置為浮空輸入模式
        由于CPU復位后,GPIO缺省都是浮空輸入模式,因此下面這個步驟不是必須的
        但是,我還是建議加上便于閱讀,并且防止其它地方修改了這個口線的設置參數
        */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        /* 第3步已經做了,因此這步可以不做
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        */
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        }

        串口初始化:
        void USART_Configuration(void)
        {
        USART_InitTypeDef USART_InitStructure;
        /* 第4步:配置USART參數
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        */
        USART_InitStructure.USART_BaudRate = 19200;
        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;

        USART_Init(USART1, &USART_InitStructure);

        //配置USART1空閑中斷

        USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);

        /* 第5步:使能 USART, 配置完畢 */
        USART_Cmd(USART1, ENABLE);
        /* CPU的小缺陷:串口配置好,如果直接Send,則第1個字節發送不出去
        如下語句解決第1個字節無法正確發送出去的問題 */
        USART_ClearFlag(USART1, USART_FLAG_TC);/* 清發送完成標志,Transmission Complete flag */
        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;

        USART_Init(USART2, &USART_InitStructure);

        //配置USART2空閑中斷

        USART_ITConfig(USART2, USART_IT_IDLE , ENABLE);
        USART_Cmd(USART2, ENABLE);
        /* CPU的小缺陷:串口配置好,如果直接Send,則第1個字節發送不出去
        如下語句解決第1個字節無法正確發送出去的問題 */
        USART_ClearFlag(USART2, USART_FLAG_TC);/* 清發送外城標志,Transmission Complete flag */

        }

        DMA配置:
        void DMA_Configuration(void)
        {
        DMA_InitTypeDef DMA_InitStructure;
        /* DMA clock enable */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//開啟DMA1外設時鐘
        /* DMA1 Channel4 (triggered by USART1 Tx event) Config */
        DMA_DeInit(DMA1_Channel4);
        DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_SEND_DATA;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = 512;
        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_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel4, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
        DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);
        /* Enable USART1 DMA TX request */
        USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
        DMA_Cmd(DMA1_Channel4, DISABLE);
        /* DMA1 Channel5 (triggered by USART2 Tx event) Config */
        DMA_DeInit(DMA1_Channel7);
        DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_SEND_DATA;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = 512;
        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_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel7, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
        DMA_ITConfig(DMA1_Channel7, DMA_IT_TE, ENABLE);
        /* Enable USART1 DMA TX request */
        USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
        DMA_Cmd(DMA1_Channel7, DISABLE);
        /* DMA1 Channel5 (triggered by USART1 Rx event) Config */
        DMA_DeInit(DMA1_Channel5);
        DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RECEIVE_DATA;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = 512;
        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_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel5, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
        DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);
        /* Enable USART1 DMA RX request */
        USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
        DMA_Cmd(DMA1_Channel5, ENABLE);
        /* DMA1 Channel6 (triggered by USART1 Rx event) Config */
        DMA_DeInit(DMA1_Channel6);
        DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RECEIVE_DATA;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = 512;
        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_Medium;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel6, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
        DMA_ITConfig(DMA1_Channel6, DMA_IT_TE, ENABLE);
        /* Enable USART2 DMA RX request */
        USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
        DMA_Cmd(DMA1_Channel6, ENABLE);

        }

        中斷優先級配置:
        void NVIC_Configuration(void)
        {
        NVIC_InitTypeDef NVIC_InitStructure;
        /* Configure one bit for preemption priority */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        /* Enable the USART1 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        /* Enable the USART2 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        //Enable DMA Channel4 Interrupt
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        //Enable DMA Channel7 Interrupt
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        /*Enable DMA Channel5 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        /*Enable DMA Channel6 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        }

        數組定義,含義如題名:
        u8 USART1_SEND_DATA[512];
        u8 USART2_SEND_DATA[512];
        u8 USART1_RECEIVE_DATA[512];
        u8 USART2_RECEIVE_DATA[512];
        u8 USART1_TX_Finish=1;// USART1發送完成標志量

        u8 USART2_TX_Finish=1;// USART2發送完成標志量

        USART1中斷服務函數
        void USART1_IRQHandler(void)
        {
        u16 DATA_LEN;
        u16 i;
        if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//如果為空閑總線中斷
        {
        DMA_Cmd(DMA1_Channel5, DISABLE);//關閉DMA,防止處理其間有數據
        //USART_RX_STA = USART1->SR;//先讀SR,然后讀DR才能清除
        //USART_RX_STA = USART1->DR;
        DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel5);
        if(DATA_LEN > 0)
        {
        while(USART1_TX_Finish==0)//等待數據傳輸完成才下一次
        {
        ;

        }

        //將數據送DMA存儲地址
        for(i=0;iTA_LEN;i )
        {
        USART1_SEND_DATA=USART1_RECEIVE_DATA;
        }
        //USART用DMA傳輸替代查詢方式發送,克服被高優先級中斷而產生丟幀現象。
        DMA_Cmd(DMA1_Channel4, DISABLE);//改變datasize前先要禁止通道工作
        DMA1_Channel4->CNDTR=DATA_LEN;//DMA1,傳輸數據量
        USART1_TX_Finish=0;//DMA傳輸開始標志量
        DMA_Cmd(DMA1_Channel4, ENABLE);
        }
        //DMA_Cmd(DMA1_Channel5, DISABLE);//關閉DMA,防止處理其間有數據
        DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清標志
        DMA1_Channel5->CNDTR = 512;//重裝填
        DMA_Cmd(DMA1_Channel5, ENABLE);//處理完,重開DMA
        //讀SR后讀DR清除Idle
        i = USART1->SR;
        i = USART1->DR;
        }
        if(USART_GetITStatus(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出錯
        {
        USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE);
        }
        USART_ClearITPendingBit(USART1, USART_IT_TC);
        USART_ClearITPendingBit(USART1, USART_IT_IDLE);

        }

        USART2中斷服務函數
        void USART2_IRQHandler(void)
        {
        u16 DATA_LEN;
        u16 i;
        if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)//如果為空閑總線中斷
        {
        DMA_Cmd(DMA1_Channel6, DISABLE);//關閉DMA,防止處理其間有數據
        //USART_RX_STA = USART1->SR;//先讀SR,然后讀DR才能清除
        //USART_RX_STA = USART1->DR;
        DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel6);
        if(DATA_LEN > 0)
        {
        while(USART2_TX_Finish==0)//等待數據完成才下一次
        {
        ;
        }
        //將數據送DMA存儲地址
        for(i=0;iTA_LEN;i )
        {
        USART2_SEND_DATA=USART2_RECEIVE_DATA;
        }
        //USART用DMA傳輸替代查詢方式發送,克服被高優先級中斷而產生丟幀現象。
        DMA_Cmd(DMA1_Channel7, DISABLE);//改變datasize前先要禁止通道工作
        DMA1_Channel7->CNDTR=DATA_LEN; //DMA1,傳輸數據量
        USART2_TX_Finish=0;//DMA傳輸開始標志量
        DMA_Cmd(DMA1_Channel7, ENABLE);
        }
        //DMA_Cmd(DMA1_Channel5, DISABLE);//關閉DMA,防止處理其間有數據
        DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);//清標志
        DMA1_Channel6->CNDTR = 512;//重裝填
        DMA_Cmd(DMA1_Channel6, ENABLE);//處理完,重開DMA
        //讀SR后讀DR清除Idle
        i = USART2->SR;
        i = USART2->DR;
        }
        if(USART_GetITStatus(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出錯
        {
        USART_ClearITPendingBit(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE);
        }
        USART_ClearITPendingBit(USART2, USART_IT_TC);
        USART_ClearITPendingBit(USART2, USART_IT_IDLE);

        }

        DMA1_Channel5中斷服務函數
        void DMA1_Channel5_IRQHandler(void)
        {
        DMA_ClearITPendingBit(DMA1_IT_TC5);
        DMA_ClearITPendingBit(DMA1_IT_TE5);
        DMA_Cmd(DMA1_Channel5, DISABLE);//關閉DMA,防止處理其間有數據
        DMA1_Channel5->CNDTR = 580;//重裝填
        DMA_Cmd(DMA1_Channel5, ENABLE);//處理完,重開DMA

        }

        DMA1_Channel6中斷服務函數
        void DMA1_Channel6_IRQHandler(void)
        {
        DMA_ClearITPendingBit(DMA1_IT_TC6);
        DMA_ClearITPendingBit(DMA1_IT_TE6);
        DMA_Cmd(DMA1_Channel6, DISABLE);//關閉DMA,防止處理其間有數據
        DMA1_Channel6->CNDTR = 580;//重裝填
        DMA_Cmd(DMA1_Channel6, ENABLE);//處理完,重開DMA

        }

        DMA1_Channel4中斷服務函數
        //USART1使用DMA發數據中斷服務程序
        void DMA1_Channel4_IRQHandler(void)
        {
        DMA_ClearITPendingBit(DMA1_IT_TC4);
        DMA_ClearITPendingBit(DMA1_IT_TE4);
        DMA_Cmd(DMA1_Channel4, DISABLE);//關閉DMA
        USART1_TX_Finish=1;//置DMA傳輸完成

        }

        DMA1_Channel7中斷服務函數
        //USART2使用DMA發數據中斷服務程序
        void DMA1_Channel7_IRQHandler(void)
        {
        DMA_ClearITPendingBit(DMA1_IT_TC7);
        DMA_ClearITPendingBit(DMA1_IT_TE7);
        DMA_Cmd(DMA1_Channel7, DISABLE);//關閉DMA
        USART2_TX_Finish=1;//置DMA傳輸完成

        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 尚义县| 金塔县| 承德县| 青田县| 南京市| 普陀区| 保山市| 葵青区| 孙吴县| 赣州市| 梁山县| 乐山市| 重庆市| 合川市| 淳化县| 赫章县| 三原县| 涪陵区| 桐梓县| 贺州市| 修水县| 灵石县| 镇安县| 五莲县| 河北省| 醴陵市| 苏州市| 汪清县| 龙州县| 阜城县| 乐山市| 滦南县| 上饶市| 茂名市| 陈巴尔虎旗| 仲巴县| 平安县| 聂拉木县| 阿拉善盟| 梅河口市| 通河县|