STM32——DMA接收和发送的实现
最近写程序,需要一段一段数据的接收,再通过其他串口发送出去。
老司机们建议用DMA通信,以节约CPU资源。然后,我听了,发现挺好用的。特此,把自己写的代码贴上了。
DMA发送接收的步骤如下:
1.初始化。
a.IO时钟+串口时钟+DMA时钟使能。
b.IO初始化
c.串口初始化
d.DMA初始化
e.中断向量设置
2.串口中断服务函数
3.DMA中断服务函数
具体实现如下:
一。初始化
//串口1的初始化 //bound:波特率
/************************************************/
void uart1_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
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初始化
USART_DeInit(USART1); //¸´Î»´®¿Ú1
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö
GPIO_Init(GPIOA, &GPIO_InitStructure); //³õʼ»¯PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
GPIO_Init(GPIOA, &GPIO_InitStructure); //³õʼ»¯PA10
3.串口初始化
USART_InitStructure.USART_BaudRate = bound;//Ò»°ãÉèÖÃΪ9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ
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); //³õʼ»¯´®¿ USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);//¿ªÆôÖжÏ
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);//串口发送DMA使能
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//串口接收DMA使能
USART_Cmd(USART1, ENABLE);//ʹÄÜ´®¿Ú
USART_ClearFlag(USART1,USART_FLAG_TC);//Çå³ý·¢ËÍÍê³É±êÖ¾
4。DMA初始化
//DMA1_Channel5 -> USART1_Rx
DMA_Cmd(DMA1_Channel5,DISABLE);
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//ÍâÉèΪUSART2->DR
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_Receive_Data;//ÄÚ´æ»ùµØÖ·
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//ÍâÉè×÷ΪÊý¾Ý´«ÊäµÄÄ¿µÄµØ£¬½ÓÊÕ
DMA_InitStructure.DMA_BufferSize = ;//ÄÚ´æ´óС
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ÄÚ´æµØÖ·¼Ä´æÆ÷µÝÔö
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//¹¤×÷ÔÚÕý³£»º´æÄ£Ê½
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMAͨµÀ5¾ßÓиßÓÅÏȼ¶
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMAͨµÀ6ûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä
DMA_Init(DMA1_Channel5,&DMA_InitStructure);
DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);//ʹÄÜ´«ÊäÍê³ÉÖжÏ
DMA_Cmd(DMA1_Channel5,ENABLE);
//DMA1_Channel4 -> USART1_Tx
DMA_Cmd(DMA1_Channel4,DISABLE);
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//ÍâÉèΪUSART2->DR
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART_Send.USART1_Send_Data;//ÄÚ´æ»ùµØÖ·
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//ÍâÉè×÷ΪÊý¾Ý´«ÊäµÄÀ´Ô´£¬·¢ËÍ
DMA_InitStructure.DMA_BufferSize = ;//ÄÚ´æ´óС
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ÄÚ´æµØÖ·¼Ä´æÆ÷µÝÔö
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//Êý¾Ý¿í¶ÈΪ8λ
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//¹¤×÷ÔÚÕý³£»º´æÄ£Ê½
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMAͨµÀ5¾ßÓиßÓÅÏȼ¶
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMAͨµÀ6ûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä
DMA_Init(DMA1_Channel4,&DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//ʹÄÜ´«ÊäÍê³ÉÖжÏ
DMA_Cmd(DMA1_Channel4,ENABLE);
5.中断向量设置
//USART1_NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= ;//ÇÀÕ¼ÓÅÏȼ¶1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; //×ÓÓÅÏȼ¶0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ
//DMA_Channel5 NVIC -> USART1_Rx
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA_Channel4 NVIC -> USART1_Tx
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//以上的话,初始化就完成了~~~~~,下面是USART中断服务函数
二。串口中断函数
#if EN_USART1_RX //Èç¹ûʹÄÜÁ˽ÓÊÕ
void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò
{
u16 DATA_LEN;
u16 i = ;
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_IDLE ) != RESET) //¿ÕÏÐÖжÏ
{
Res = USART1->SR;
Res = USART1->DR;//Çå³ý¿ÕÏÐÖжϱêÖ¾ DMA_Cmd(DMA1_Channel5,DISABLE);//¹Ø±ÕDMA,·ÀÖ¹´¦ÀíÆä¼äÓÐÊý¾Ý
DATA_LEN = - DMA_GetCurrDataCounter(DMA1_Channel5);//»ñÈ¡Êý¾Ý³¤¶È
//±£´æ½ÓÊÕµ½µÄÊý¾Ý,·ÅÖõ½USART2_SendData
USART_Send.USART1_Len_R = DATA_LEN; //±£´æÊý¾Ý³¤¶È
for(i=;i<DATA_LEN;i++)
{
USART_Send.USART1_Receive_Data[i] = USART1_Receive_Data[i];//±£´æÊý¾Ý
}
USART_Send.USART1_Rx_Finish = ;//±êÖ¾ÖÃ1£¬±íʾÊý¾Ý±£´æÍê±Ï DMA1_Channel5->CNDTR = ;//ÖØÐÂÉèÖÃDMA1_Channel5µÄÊý¾Ý´«ÊäÊýÁ¿
DMA_Cmd(DMA1_Channel5,ENABLE);//¿ªÆôDMA1_Channel5
} }
三。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 = ;
u8 Res;
DMA_ClearITPendingBit(DMA1_IT_TC5);//Çå³ýÖжÏÍê³É±êÖ¾
DMA_Cmd(DMA1_Channel5,DISABLE);//¹Ø±ÕDMA,·ÀÖ¹´¦ÀíÆÚ¼äÓÐÊý¾Ý DATA_LEN = - DMA_GetCurrDataCounter(DMA1_Channel5);//»ñÈ¡Êý¾Ý³¤¶È
//±£´æ½ÓÊÕµ½µÄÊý¾Ý,·ÅÖõ½USART2_SendData
USART_Send.USART1_Len_R = DATA_LEN; //±£´æÊý¾Ý³¤¶È
for(i=;i<DATA_LEN;i++)
{
USART_Send.USART1_Receive_Data[i] = USART1_Receive_Data[i];//±£´æÊý¾Ý
}
USART_Send.USART1_Rx_Finish = ;//±êÖ¾ÖÃ1£¬±íʾÊý¾Ý±£´æÍê±Ï DMA1_Channel5->CNDTR = ;//ÖØÐÂÌî×°
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 = ;
}
}
很困,别的+注释这周补上。。。
STM32——DMA接收和发送的实现的更多相关文章
- MM32F0140 UART1 DMA RX and TX 中断接收和发送数据
目录: 1.MM32F0140简介 2.DMA工作原理简介 3.初始化MM32F0140 UART1 4.配置MM32F0140 UART1 DMA接收 5.配置MM32F0140 UART1 DMA ...
- STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷
STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...
- STM32之串口DMA接收不定长数据
STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...
- STM32串口DMA接收数据错位——暴力解决方法
背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...
- STM32—无需中断来实现使用DMA接收串口数据
本节目标: 通过DMA,无需中断,接收不定时长的串口数据 描述:当在串口多数据传输下,CPU会产生多次中断来接收串口数据,这样会大大地降低CPU效率,同时又需要CPU去做其它更重要的事情,我们应该如何 ...
- STM32输入捕获模式设置并用DMA接收数据
参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...
- STM32的PWM输入模式设置并用DMA接收数据
参考 :STM32输入捕获模式设置并用DMA接收数据 PWM input mode This mode is a particular case of input capture mode. The ...
- STM32 DMA模块的配置与使用
DMA有什么用? 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输.无须CPU的干预,通过DMA数据可以快速地移动.这就节省了CPU的资源来做其他操作. 有多少个DMA资源 ...
- STM32 DMA使用详解
DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧.下面用问答的形式表达我的思路. DMA有什么用? 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数 ...
随机推荐
- Markdown中插入数学公式的方法
Markdown中插入数学公式的方法 文章来源:http://blog.csdn.net/xiahouzuoxin/article/details/26478179 自从使用Markdown以来,就开 ...
- php操作ini配置文件
有些配置化的数据放到配置文件可以方便管理,比如数据库信息,路由信息,先建立配置文件,test.ini [database_setting] host=127.0.0.1 user=root passw ...
- mysql:SQL语句操作数据库中表和字段的COMMENT值
转载:http://blog.163.com/inflexible_simple/blog/static/167694684201182601221758/ 参考文档不太给力啊,表注释和字段注释的资料 ...
- IaaS/PaaS/SaaS
如果你是一个网站站长,想要建立一个网站.不采用云服务,你所需要的投入大概是:买服务器,安装服务器软件,编写网站程序.现在你追随潮流,采用流行的云计算,如果你采用IaaS服务,那么意味着你就不用自己买服 ...
- java 计算 1到10 的 阶层的和(采用递归的方法)
package hibernate; public class t { public static void main(String[] args) { System.out.println(jiec ...
- unity5.3 安卓广告插件打包出错的理解
今天打包带广告插件的安卓包,出现了问题 ,上网找了很多解决的办法.整理一下. 1,有的说法是unity5的BUG 因为同一个项目 用unity4.6打包就没问题 到5就出问题,当然 姑且可以这么认为 ...
- SPSS数据分析—因子分析
我们知道主成分分析是一种降维方法,但是其本质上只是一种矩阵变换的过程,提取出来的主成分并不都具有实际含义,而这种含义往往是我们所需要的,接下来的因子分析可以解决这个问题 因子分析可以看做是主成分分析的 ...
- OPENGL半透明图像产生黑色光环
OPENGL提供了多种多样的混合方法,我们很容易就能实现诸如 叠加.变亮等图像混合. 我们知道一般带透明度的图像是RGBA四个通道来存储,最常的glBlendFunc是 glBlendFunc(GL_ ...
- linux 挂载光盘:mount: you must specify the filesystem type
尝试挂载光盘镜像时出现mount: you must specify the filesystem type 使用-t auto -t iso9660 或不加参数都搞不定,最后在以下链接找到解决办法: ...
- GbkToUtf8 Utf8ToGbk PackHttp
void CFunc::GbkToUtf8(CString &strGBK) { , (LPCTSTR)strGBK, -, NULL, ); unsigned ]; memset(wszUt ...