首页 > 代码库 > STM32——DMA接收和发送的实现

STM32——DMA接收和发送的实现

最近写程序,需要一段一段数据的接收,再通过其他串口发送出去。

老司机们建议用DMA通信,以节约CPU资源。然后,我听了,发现挺好用的。特此,把自己写的代码贴上了。

DMA发送接收的步骤如下:

1.初始化。

a.IO时钟+串口时钟+DMA时钟使能。

b.IO初始化

c.串口初始化

d.DMA初始化

e.中断向量设置

2.串口中断服务函数

3.DMA中断服务函数

 

具体实现如下:

一。初始化

1 //串口1的初始化2 //bound:波特率3 /************************************************/4 void uart1_init(u32 bound)5 {6     GPIO_InitTypeDef GPIO_InitStructure;7     USART_InitTypeDef USART_InitStructure;8     NVIC_InitTypeDef NVIC_InitStructure;9     DMA_InitTypeDef DMA_InitStructure;

1。IO时钟+串口时钟+DMA时钟使能。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //串口1时钟初始化+GPIOA时钟初始化
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);   //DMA1初始化

2.IO初始化

 1     USART_DeInit(USART1);  //¸´Î»´®¿Ú1 2     //USART1_TX   PA.9 3   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 4   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 5   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //¸´ÓÃÍÆÍìÊä³ö 6   GPIO_Init(GPIOA, &GPIO_InitStructure); //³õʼ»¯PA9 7   //USART1_RX      PA.10 8   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 9   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë10   GPIO_Init(GPIOA, &GPIO_InitStructure);  //³õʼ»¯PA10

3.串口初始化

 1     USART_InitStructure.USART_BaudRate = bound;//Ò»°ãÉèÖÃΪ9600; 2     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ 3     USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ 4     USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ 5     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ 6     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //ÊÕ·¢Ä£Ê½ 7   USART_Init(USART1, &USART_InitStructure); //³õʼ»¯´®¿ 8      9     USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);//¿ªÆôÖжÏ10     USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);//串口发送DMA使能11     USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//串口接收DMA使能12   USART_Cmd(USART1, ENABLE);//ʹÄÜ´®¿Ú 13     USART_ClearFlag(USART1,USART_FLAG_TC);//Çå³ý·¢ËÍÍê³É±êÖ¾

4。DMA初始化

 1 //DMA1_Channel5 -> USART1_Rx 2     DMA_Cmd(DMA1_Channel5,DISABLE); 3     DMA_DeInit(DMA1_Channel5); 4     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//ÍâÉèΪUSART2->DR 5     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_Receive_Data;//ÄÚ´æ»ùµØÖ· 6     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//ÍâÉè×÷ΪÊý¾Ý´«ÊäµÄÄ¿µÄµØ£¬½ÓÊÕ 7     DMA_InitStructure.DMA_BufferSize = 1024;//ÄÚ´æ´óС 8     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä 9     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ÄÚ´æµØÖ·¼Ä´æÆ÷µÝÔö10     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ11     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ12     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//¹¤×÷ÔÚÕý³£»º´æģʽ13     DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMAͨµÀ5¾ßÓиßÓÅÏȼ¶14     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMAͨµÀ6ûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä15     DMA_Init(DMA1_Channel5,&DMA_InitStructure);16     DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);//ʹÄÜ´«ÊäÍê³ÉÖжÏ17     DMA_Cmd(DMA1_Channel5,ENABLE);18     //DMA1_Channel4 -> USART1_Tx19     DMA_Cmd(DMA1_Channel4,DISABLE);20     DMA_DeInit(DMA1_Channel4);21     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//ÍâÉèΪUSART2->DR22     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART_Send.USART1_Send_Data;//ÄÚ´æ»ùµØÖ·23     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//ÍâÉè×÷ΪÊý¾Ý´«ÊäµÄÀ´Ô´£¬·¢ËÍ24     DMA_InitStructure.DMA_BufferSize = 1024;//ÄÚ´æ´óС25     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä26     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ÄÚ´æµØÖ·¼Ä´æÆ÷µÝÔö27     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ28     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ29     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//¹¤×÷ÔÚÕý³£»º´æģʽ30     DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMAͨµÀ5¾ßÓиßÓÅÏȼ¶31     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMAͨµÀ6ûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä32     DMA_Init(DMA1_Channel4,&DMA_InitStructure);33     DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//ʹÄÜ´«ÊäÍê³ÉÖжÏ34     DMA_Cmd(DMA1_Channel4,ENABLE);

5.中断向量设置

 1     //USART1_NVIC 2   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 3     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//ÇÀÕ¼ÓÅÏȼ¶1 4     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //×ÓÓÅÏȼ¶0 5     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQͨµÀʹÄÜ 6     NVIC_Init(&NVIC_InitStructure);    //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ 7     //DMA_Channel5 NVIC -> USART1_Rx 8     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; 9     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;10     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;11     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;12     NVIC_Init(&NVIC_InitStructure);13     //DMA_Channel4 NVIC -> USART1_Tx14     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;15     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;16     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;17     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;18     NVIC_Init(&NVIC_InitStructure);
}

//以上的话,初始化就完成了~~~~~,下面是USART中断服务函数

二。串口中断函数

 1 #if EN_USART1_RX   //Èç¹ûʹÄÜÁ˽ÓÊÕ 2 void USART1_IRQHandler(void)                    //´®¿Ú1ÖжϷþÎñ³ÌÐò 3 { 4     u16 DATA_LEN; 5     u16 i = 0; 6     u8 Res; 7     if(USART_GetITStatus(USART1, USART_IT_IDLE ) != RESET)  //¿ÕÏÐÖÐ¶Ï 8     { 9         Res = USART1->SR;10         Res = USART1->DR;//Çå³ý¿ÕÏÐÖжϱêÖ¾11         12         DMA_Cmd(DMA1_Channel5,DISABLE);//¹Ø±ÕDMA,·ÀÖ¹´¦ÀíÆä¼äÓÐÊý¾Ý13         DATA_LEN = 1024 - DMA_GetCurrDataCounter(DMA1_Channel5);//»ñÈ¡Êý¾Ý³¤¶È14         //±£´æ½ÓÊÕµ½µÄÊý¾Ý,·ÅÖõ½USART2_SendData15         USART_Send.USART1_Len_R = DATA_LEN; //±£´æÊý¾Ý³¤¶È16         for(i=0;i<DATA_LEN;i++)17         {18             USART_Send.USART1_Receive_Data[i] = USART1_Receive_Data[i];//±£´æÊý¾Ý19         }20         USART_Send.USART1_Rx_Finish = 1;//±êÖ¾ÖÃ1£¬±íʾÊý¾Ý±£´æÍê±Ï21         22         DMA1_Channel5->CNDTR = 1024;//ÖØÐÂÉèÖÃDMA1_Channel5µÄÊý¾Ý´«ÊäÊýÁ¿23         DMA_Cmd(DMA1_Channel5,ENABLE);//¿ªÆôDMA1_Channel524     } 25 26 } 

三。DMA通道中断服务函数

//DMA1_Channel5-RxÖжϷþÎñº¯Êý,usart1_Rxvoid DMA1_Channel5_IRQHandler(void){    DMA_ClearITPendingBit(DMA1_IT_TE5);//Çå³ý´íÎóÖÐ¶Ï    if(DMA_GetITStatus(DMA1_IT_TC5))//·¢ÉúÁË´«ÊäÍê³ÉÖÐ¶Ï    {        u16 DATA_LEN;        u16 i = 0;        u8 Res;        DMA_ClearITPendingBit(DMA1_IT_TC5);//Çå³ýÖжÏÍê³É±êÖ¾        DMA_Cmd(DMA1_Channel5,DISABLE);//¹Ø±ÕDMA,·ÀÖ¹´¦ÀíÆÚ¼äÓÐÊý¾Ý                DATA_LEN = 1024 - DMA_GetCurrDataCounter(DMA1_Channel5);//»ñÈ¡Êý¾Ý³¤¶È        //±£´æ½ÓÊÕµ½µÄÊý¾Ý,·ÅÖõ½USART2_SendData        USART_Send.USART1_Len_R = DATA_LEN; //±£´æÊý¾Ý³¤¶È        for(i=0;i<DATA_LEN;i++)        {            USART_Send.USART1_Receive_Data[i] = USART1_Receive_Data[i];//±£´æÊý¾Ý        }        USART_Send.USART1_Rx_Finish = 1;//±êÖ¾ÖÃ1£¬±íʾÊý¾Ý±£´æÍê±Ï                DMA1_Channel5->CNDTR = 1024;//ÖØÐÂÌî×°        DMA_Cmd(DMA1_Channel5,ENABLE);//´¦ÀíÍê³Éºó£¬ÖØ¿ªDMA            }}
//DMA1_Channel4-TxÖжϷþÎñº¯Êý,usart1_Txvoid DMA1_Channel4_IRQHandler(void){    DMA_ClearITPendingBit(DMA1_IT_TE4);//Çå³ý´íÎóÖжϱêÖ¾    if(DMA_GetITStatus(DMA1_IT_TC4))//·¢Éú´«ÊäÍê³ÉÖжϱêÖ¾    {        DMA_ClearITPendingBit(DMA1_IT_TC4);//Çå³ýÖжϱêÖ¾        DMA_Cmd(DMA1_Channel4,DISABLE);//¹Ø±ÕÖÐ¶Ï        USART_Send.USART1_Tx_Finish = 0;    }    }

很困,别的+注释这周补上。。。

             

 

STM32——DMA接收和发送的实现