STM32——DMA接收和发送的实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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_Tx 19 DMA_Cmd(DMA1_Channel4,DISABLE); 20 DMA_DeInit(DMA1_Channel4); 21 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//ÍâÉèΪUSART2->DR 22 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_Tx 14 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_SendData 15 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_Channel5 24 } 25 26 }
三。DMA通道中断服务函数
//DMA1_Channel5-RxÖжϷþÎñº¯Êý,usart1_Rx void 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_Tx void 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接收和发送的实现的主要内容,如果未能解决你的问题,请参考以下文章
stm32f412 SPI dma接收和UART dma发送问题解决