STM32的串口DMA收发以及双缓冲区的实现
在使用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收发以及双缓冲区的实现的更多相关文章
- STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率
前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...
- STM32之串口DMA接收不定长数据
STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...
- Stm32CubeMX5 配置 STM32的串口DMA接受方式 --- 基于 stm32f051k8u6
实现的功能: 使用MDA方式把串口接受的数据在发送给串口(当然也可以做其他解析控制使用) 1. 先初始化 时钟使用外部的晶振配置系统时钟为48Mhz 2. 串口参数配置 3. 使能中断 4. 配置串 ...
- STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷
STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...
- STM32F407的串口采用DMA收发数据
源:STM32F407的串口采用DMA收发数据
- STM32串口DMA接收数据错位——暴力解决方法
背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...
- STM32CubeMx——串口使用DMA收发
用到的是DMA发送数据,接收还是普通的串口接收. 一.代码生成 1.按以前的方法设置好时钟和调试方式,这里就不多说了. 2.设置串口1. 3.在DMA Setting里点击Add添加USART1_TX ...
- STM32的USART DMA传输(转)
源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...
- RT-Thread中的串口DMA分析
这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...
随机推荐
- Base Conversion In PHP and javascript
http://www.exploringbinary.com/base-conversion-in-php-using-built-in-functions/ http://www.binarycon ...
- {head first} --- networking 1
Head first系列的书确实非常好,深入浅出解说网络的组成.让曾经那些生涩的概念生动起来. Chapter 1 维修物理网络 CAT5电缆: 两端为RJ-45接头(水晶头).内部为UTP(非屏蔽双 ...
- iOS_开发中遇到的那些问题_1
[自编号:60][AutoLayout中,怎样让ImageView保持固定的宽高比?比如1:1] 先将imageViewframe手动写成:宽20,高20,再勾选Aspect Ratio加入宽高比约束 ...
- 谈论javascript闭包
闭包看似很简单,其实牵扯了很多东西,例如:上下文作用域(事件处理程序).内存占用.局部以及全局变量.回调函数以及编程模式等 首先我们谈论一个问题,为什么需要闭包? 1.var全局定义(全局污染)- 指 ...
- linux 下查看一个进程执行路径
在linux下查看进程大家都会想到用 ps -ef|grep XXX 但是看到的不是全路径.怎么看全路径呢? 每一个进程启动之后在 /proc以下有一个于pid相应的路径 比如:ps -ef|grep ...
- Message: unknown error: Element is not clickable at point
Message: unknown error: Element is not clickable at point google chrome - Debugging "Element is ...
- 2015-2016 ACM-ICPC Pacific Northwest Regional Contest (Div. 2)V - Gears
Problem V | limit 4 secondsGearsA set of gears is installed on the plane. You are given the center c ...
- 在mac下设置环境变量
在mac下设置环境变量 在基于unix/linux的操作系统下进行程序开发,使用环境变量将会方便.通过设置环境变量将可以在任意目录通过输入程序名来执行设定目录下的程序.不需要通过cd将工作目录改变 ...
- poj 3621(最优比率环)
Sightseeing Cows Farmer John has decided to reward his cows for their hard work by taking them on a ...
- AT2004 Anticube
https://www.zybuluo.com/ysner/note/1304774 题面 给定\(n\)个数\(s_i\),要求从中选出最多的数,满足任意两个数之积都不是完全立方数. \(n\leq ...