在使用STM32的UART的DMA功能总结如下:

首先上代码,这里采用STM32 的USART1作为Demo,RX的DMA为DMA1_Channel5,TX的DMA为DMA1_Channel4.初始化如下,红色的标记需要注意:

RX-DMA初始化

 // DMA Rx
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
DMA_Cmd(DMA1_Channel5,DISABLE);
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)RxBuf0;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = ;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5,&DMA_InitStruct);
DMA_Cmd(DMA1_Channel5,ENABLE);

中断的初始化如下:

    DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = ;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct); //ENABLE DMA TX ISR
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = ;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

TX发送函数如下:

 void USART1_SendDMA(uint8_t* buf,int len)
{
DMA_InitTypeDef DMA_InitStruct;

DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); DMA_Cmd(DMA1_Channel4,DISABLE);

DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)buf;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = len;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4,&DMA_InitStruct); DMA_Cmd(DMA1_Channel4,ENABLE);
}

两个服务函数如下:

RX-DMA中断函数,实现RX的双缓冲区功能。值得注意的是,你的DMA设置成Normal模式的时候,在中断函数中就得设置DMABufferSize,应为Normal模式完成一次传输之后,BufferSize直接清零,设置成Circle模式就不会存在这个问题,下面的中断就是设置成Circle模式的。

void DMA1_Channel5_IRQHandler()
{
if(DMA_GetITStatus(DMA1_IT_TC5))
{
if(using_buf0 ==)
{
     DMA1_Channel5->CMAR = (u32)RxBuf0;
using_buf0 = ;
}
else
{
DMA1_Channel5->CMAR = (u32)RxBuf1;
using_buf0 = ;
}
recv_flag = ;
DMA_ClearITPendingBit(DMA1_IT_TC5);
}
}

TX-DMA中断函数

void DMA1_Channel4_IRQHandler()
{
if(DMA_GetITStatus(DMA1_IT_TC4))
{
//TODO:Add code here
DMA_ClearITPendingBit(DMA1_IT_TC4);
}
}

几点说明

1)这里采用双缓冲区的方式,对于大数据量的时候是很有效的,在处理一个缓冲区数据的时候,另外一个缓冲区能够正常接收数据

2)TX的DMA中断,可以采用类似于操作系统中互斥量的操作,当一个数组还在发送的时候,另外一个数组如果检测到一个在发送,则不能够进行发送,不然这样子数据会乱掉;

3)如果DMA接收想采用循环缓冲区的方式,可以直接将RX-DMA设置成Circle方式,然后数据就会硬件上自动实现环形缓冲区的功能,省了不少时间。

4)DMA在采用Normal模式的时候,当一次任务完成后,DMA->DMA_BufferSize自动清零,并且DMA自动停止。如果想再次设置DMA的BufferSize的话,必须要进行如下操作:

step1:DMA_CMD(DMAx_Channely,DISABLE);

step2: 设置DMA_BufferLen

step3:DMA_CMD(DMAx_Channely,ENABLE)

5)DMA采用Circle模式的时候,在发送或者接受完成之后,仍然保存着BufferSize,并且DMA还处于使能状态,一直连续工作,直到用户停止DMA

STM32的串口DMA收发以及双缓冲区的实现的更多相关文章

  1. STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率

    前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...

  2. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  3. Stm32CubeMX5 配置 STM32的串口DMA接受方式 --- 基于 stm32f051k8u6

     实现的功能: 使用MDA方式把串口接受的数据在发送给串口(当然也可以做其他解析控制使用) 1. 先初始化 时钟使用外部的晶振配置系统时钟为48Mhz 2. 串口参数配置 3. 使能中断 4. 配置串 ...

  4. STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷

    STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...

  5. STM32F407的串口采用DMA收发数据

    源:STM32F407的串口采用DMA收发数据

  6. STM32串口DMA接收数据错位——暴力解决方法

    背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...

  7. STM32CubeMx——串口使用DMA收发

    用到的是DMA发送数据,接收还是普通的串口接收. 一.代码生成 1.按以前的方法设置好时钟和调试方式,这里就不多说了. 2.设置串口1. 3.在DMA Setting里点击Add添加USART1_TX ...

  8. STM32的USART DMA传输(转)

    源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...

  9. RT-Thread中的串口DMA分析

    这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...

随机推荐

  1. 【转】Linux软连接和硬链接

    再次温习一下,操作的不多.虽然感觉都会!!!! 这次再次操作一遍!! 通过上面的测试发现,删除f1之后,软连接f3就无效了,硬链接f3则不受影响. ls -F可以看到文件的类型. 连接文件的作用? - ...

  2. git fetch 和 git pull 的差别

    Git中从远程的分支获取最新的版本号到本地有这样2个命令: 1. git fetch:相当于是从远程获取最新版本号到本地,不会自己主动merge git fetch origin master git ...

  3. 第二十七篇:Windows驱动中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace

    近期有些人问我PCI设备驱动的问题, 和他们交流过后, 我建议他们先看一看<<The Windows NT Device Driver Book>>这本书, 个人感觉, 这本书 ...

  4. ZOJ 3609 Modular Inverse(扩展欧几里德)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4712 The modular modular multiplicat ...

  5. linux常见基础问题

    1,32位与64位的区别,怎么查看系统版本? 32位相比于64位处理速度更慢一些,64位同样也比32位更占内存.用户体验上没有区别:用uname  -a 查看系统版本信息 2,swap分区的作用是什么 ...

  6. 彻底弄懂px,em和rem的区别

    国内的设计大师都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? px特点: 1.IE无法调整那些使用px作为单位的字体大小: 2.国外大部分网站能够调整的原因 ...

  7. Ubuntu14.04 x64 zabbix 3.0 安装

    U buntu14.04 x64   zabbix 3.0 安装 苦于网上的文档很多,但是对初学者来说,很多都搭建不成功,我重新安装一下.记录一下. 下载deb wget http://repo.za ...

  8. su 认证失败

    jiqing@ThinkPad:~$ su 密码: su:认证失败 jiqing@ThinkPad:~$ sudo passwd root [sudo] password for jiqing: 输入 ...

  9. 简述Python中的break和continue的区别

    众所周知在Python中,break是结束整个循环体,而continue则是结束本次循环再继续循环. 但是作为一个新手的你,还是不明白它们的区别,这里用一个生动的例子说明它们的区别,如下: 1.con ...

  10. CI CD系统整合

    转载_CI 系统搭建:Git.Gerrit与Jenkins 2014-08-11 20:55 15678人阅读 评论(1) 收藏 举报 分类: 软件集成和项目管理(3) 目录(?)[+] 去年写的这五 ...