STM32的串口采用DMA方式接收數(shù)據(jù)測(cè)試
主機(jī):WINXP
本文引用地址:http://www.ex-cimer.com/article/201611/318289.htm開(kāi)發(fā)環(huán)境:MDK4.23
MCU:STM32F103CBT6
說(shuō)明:
串口可以配置成用DMA的方式接收數(shù)據(jù),不過(guò)DMA需要定長(zhǎng)才能產(chǎn)生接收中斷,如何接收可變長(zhǎng)度的數(shù)據(jù)呢?
方法有以下3種:
1.將RX腳與一路時(shí)鐘外部引腳相連,當(dāng)串口一幀發(fā)完,即可利用此定時(shí)器產(chǎn)生超時(shí)中斷.這個(gè)實(shí)時(shí)性較高,可以做到1個(gè)字節(jié)實(shí)時(shí)監(jiān)測(cè).
2.不改變硬件,開(kāi)啟一個(gè)定時(shí)器監(jiān)控DMA接收,如果超時(shí)則產(chǎn)生中斷.這個(gè)實(shí)時(shí)性不高,因?yàn)槌瑫r(shí)時(shí)間必須要大于需要接收幀的時(shí)間,精度不好控制.
3.STM32單片機(jī)有的串口可以監(jiān)測(cè)總線是否處于空閑,如果空閑則產(chǎn)生中斷.可以用它來(lái)監(jiān)測(cè)DMA接收是否完畢.這種方式實(shí)時(shí)性很高.
本文采用第3種方式.在波特率576000下大數(shù)據(jù)包沖擊證明可行.
源代碼:
//串口接收DMA緩存#define UART_RX_LEN 128extern uint8_t Uart_Rx[UART_RX_LEN];
//串口接收DMA緩存uint8_t Uart_Rx[UART_RX_LEN] = {0};
//---------------------串口功能配置---------------------//打開(kāi)串口對(duì)應(yīng)的外設(shè)時(shí)鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); //串口發(fā)DMA配置 //啟動(dòng)DMA時(shí)鐘RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA發(fā)送中斷設(shè)置NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);//DMA1通道4配置DMA_DeInit(DMA1_Channel4);//外設(shè)地址DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//內(nèi)存地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer;//dma傳輸方向單向DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//設(shè)置DMA在傳輸時(shí)緩沖區(qū)的長(zhǎng)度DMA_InitStructure.DMA_BufferSize = 100;//設(shè)置DMA的外設(shè)遞增模式,一個(gè)外設(shè)DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//設(shè)置DMA的內(nèi)存遞增模式DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//外設(shè)數(shù)據(jù)字長(zhǎng)DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//內(nèi)存數(shù)據(jù)字長(zhǎng)DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//設(shè)置DMA的傳輸模式DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//設(shè)置DMA的優(yōu)先級(jí)別DMA_InitStructure.DMA_Priority = DMA_Priority_High;//設(shè)置DMA的2個(gè)memory中的變量互相訪問(wèn)DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel4,&DMA_InitStructure);DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//使能通道4//DMA_Cmd(DMA1_Channel4, ENABLE);//串口收DMA配置 //啟動(dòng)DMA時(shí)鐘RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1通道5配置DMA_DeInit(DMA1_Channel5);//外設(shè)地址DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//內(nèi)存地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx;//dma傳輸方向單向DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//設(shè)置DMA在傳輸時(shí)緩沖區(qū)的長(zhǎng)度DMA_InitStructure.DMA_BufferSize = UART_RX_LEN;//設(shè)置DMA的外設(shè)遞增模式,一個(gè)外設(shè)DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//設(shè)置DMA的內(nèi)存遞增模式DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//外設(shè)數(shù)據(jù)字長(zhǎng)DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//內(nèi)存數(shù)據(jù)字長(zhǎng)DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//設(shè)置DMA的傳輸模式DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//設(shè)置DMA的優(yōu)先級(jí)別DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//設(shè)置DMA的2個(gè)memory中的變量互相訪問(wèn)DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel5,&DMA_InitStructure);//使能通道5DMA_Cmd(DMA1_Channel5,ENABLE);//初始化參數(shù) //USART_InitStructure.USART_BaudRate = DEFAULT_BAUD; 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_InitStructure.USART_BaudRate = DEFAULT_BAUD; //初始化串口 USART_Init(USART1,&USART_InitStructure); //TXE發(fā)送中斷,TC傳輸完成中斷,RXNE接收中斷,PE奇偶錯(cuò)誤中斷,可以是多個(gè) //USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//中斷配置USART_ITConfig(USART1,USART_IT_TC,DISABLE);USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //配置UART1中斷 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //通道設(shè)置為串口1中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //中斷占先等級(jí)0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //中斷響應(yīng)優(yōu)先級(jí)0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打開(kāi)中斷 NVIC_Init(&NVIC_InitStructure); //采用DMA方式發(fā)送USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);//采用DMA方式接收USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//啟動(dòng)串口 USART_Cmd(USART1, ENABLE);
//串口1接收中斷 void USART1_IRQHandler(void) { uint32_t temp = 0;uint16_t i = 0;if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET){//USART_ClearFlag(USART1,USART_IT_IDLE);temp = USART1->SR;temp = USART1->DR; //清USART_IT_IDLE標(biāo)志DMA_Cmd(DMA1_Channel5,DISABLE);temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);for (i = 0;i < temp;i++){Data_Receive_Usart = Uart_Rx[i];//啟動(dòng)串口狀態(tài)機(jī)usart_state_run(); }//設(shè)置傳輸數(shù)據(jù)長(zhǎng)度DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN);//打開(kāi)DMADMA_Cmd(DMA1_Channel5,ENABLE);} __nop(); }
測(cè)試結(jié)果:
條件:單片機(jī)運(yùn)行于72M,與PC通信速率為460800.PC每隔100ms發(fā)送一個(gè)9個(gè)字節(jié)的包:c5 5c 6 0 6F 10 5 4e f7.
測(cè)試:單片機(jī)每次收到此包,一個(gè)IO作電平跳轉(zhuǎn),然后處理返回一包.
示波器顯示:
放大顯示:
評(píng)論