产品选型

dma 单片机 单片机的DMA的要点难点概括

小编 2024-11-24 产品选型 23 0

单片机的DMA的要点难点概括

DMA控制器

1 stm32的dma控制器有两组 DMA1,DMA2;

2 dma的运行也就是传输数据不通过内核,直接进行传输也就是cpu不干涉

3 DMA的数据传输方向 外设到储存器 储存器到外设 储存器到储存器

4 dma1有7 个通道,dma2有5 个通道 一个通道连接多个外设

5 DMA的优先级通过dma仲裁器来协调

DMA主要特性

1 dma的优先级通过软件编程设置,具有四种优先级别 很高 高 中 低 当优先级相同时由硬件决定。

2 源和目标数据必须对齐 两边同时为 半字 字 字节

3 每个通道具有三个中断标志 DMA半传输、 DMA传输完成和DMA传输出错

4 传输数据最大长度 65535

DMA框图

请注意图片下面的三句话

1 DMA2仅存在与大容量产品和互联网型产品

2 SPI/I2S3、 UART4、 TIM5、 TIM6、 TIM7和DAC的DMA请求仅存在于大容量产品和互联型产品

3 ADC3、 SDIO和TIM8的DMA请求仅存在于大容量产品

当cpu与DMA同时获取存储器或外设的数据时dma会暂时暂停,等待cpu若干个时钟周期。

DMA处理

在发生一个事件后,外设向DMA控制器发送一个请求信号。 DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时, DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求, DMA控制器同时撤销应答信号。如果有更多的请求时,外设可以启动下一个周期。总之,每次DMA传送由3个操作组成。

从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传

输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。

存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输

时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。

执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。、

DMA中断

每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考

虑,通过设置寄存器的不同位来打开这些中断。

DMA1设备

dma1连接的外设

各个通道的表

DMA2

dma2连接的外设

dma连接的外设

通道配置过程(软件初始化通道)

下面是配置DMA通道x的过程(x代表通道号):

1. 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将

是数据传输的源或目标。

2. 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数

据将从这个地址读出或写入这个地址。

3. 在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。

4. 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。

5. 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外

设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。

6. 设置DMA_CCRx寄存器的ENABLE位,启动该通道。

一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。

瑞萨单片机基于DMA的串口通讯实例

单片机程序开发中,经常用到串口通讯,一般大家都是采用中断的方式实现,但是如果要求通讯波特率很高,那么就会导致程序频繁地进行中断处理,更甚者导致主循环得不到运行,这时候一般都会选择DMA+UART的方式进行设计,接收和发送交给DMA,释放MCU去做别的事情。

这里以瑞萨单片机为例,接收和发送均通过DMA实现,上实例代码,包括DMA和UART的配置以及详细的注释,用到同款单片机的朋友可以参考。

//DMA+USART的配置 250字节的定长发送和250字节的定长接收

INT8U sciTxBuf[256];//定长发送缓冲数组,DMA接收的目标地址

INT8U sciRxBuf[256];//定长接收缓冲数组,DMA发送的源地址

void dmac0_init(void)//接收DMA通道0

{

IEN(DMAC,DMAC0I) = 0; /* 禁用DMAC0I中断请求 */

DMAC0.DMCNT.BIT.DTE = 0; /* 禁用DMA0传送数据*/

ICU.DMRSR0 = 219; /* DMAC0的请求源: RXI1 ,(RXI中断向量号为219) */

DMAC0.DMAMD.BIT.DM = 2; /* 目标地址更新方式:递增,值为10b */

DMAC0.DMAMD.BIT.SM = 0; /* 源地址更新方式:固定,值为00b */

DMAC0.DMAMD.BIT.DARA = 0; /* 目标地址扩展重复区域:不指定 */

DMAC0.DMAMD.BIT.SARA = 0; /* 源地址扩展重复区域 :不指定*/

DMAC0.DMTMD.BIT.DCTG = 1; /* DMA 请求源: 外设中断 */

DMAC0.DMTMD.BIT.SZ = 0; /* 数据传送长度: 8 bits */

DMAC0.DMTMD.BIT.MD = 0; /* 传送模式: 正常传送 */

DMAC0.DMCSL.BIT.DISEL = 0; /* 传送结束后,将启动源的中断标志清0 */

DMAC0.DMSAR = (void *)&SCI1.RDR; /* 源地址: SCI1.RDR register */

DMAC0.DMDAR = (void *)sciRxBuf; /* 目标地址: 接收缓存 */

DMAC0.DMCRA = 250; /* DMCRA.DMCRAL = 0, 指定传送个数 1024*/

/* DMCRA.DMCRAH = 0, 指定备份传送个数1024 */

IPR(DMAC,DMAC0I) = 10; /* DMAC0I中断优先级: Level 12 */

DMAC0.DMINT.BIT.DTIE = 1; /* 允许传送结束中断请求 */

IEN(DMAC,DMAC0I) = 1; /* 允许DMAC0I的中断请求 */

DMAC0.DMCNT.BIT.DTE = 1; /* 允许DMA传送数据 */

}

void dmac1_init(void)//发送DMA通道1

{

IEN(DMAC,DMAC1I) = 0; /* 禁用DMAC1I的中断请求 */

DMAC1.DMCNT.BIT.DTE = 0; /* 禁用DMA传送 */

ICU.DMRSR1 = 220; /* DMAC1的请求源:TXI ,(TXI中断向量号为220)*/

DMAC1.DMAMD.BIT.DM = 0; /* 目标地址更新方式:固定 ,值为00b */

DMAC1.DMAMD.BIT.SM = 2; /* 源地址更新方式:递增 , 值为10b */

DMAC1.DMAMD.BIT.DARA = 0; /* 目标地址扩展重复区域:不指定 */

DMAC1.DMAMD.BIT.SARA = 0; /* 源地址扩展重复区域 :不指定*/

DMAC1.DMTMD.BIT.DCTG = 1; /* DMA 请求源: 外设中断 */

DMAC1.DMTMD.BIT.SZ = 0; /* 数据传送长度: 8 bits */

DMAC1.DMTMD.BIT.MD = 0; /* 传送模式: 正常传送 */

DMAC1.DMCSL.BIT.DISEL = 0; /* 传送结束后,将启动源的中断标志清0 */

DMAC1.DMSAR = (void *)sciTxBuf; /* 源地址: 传送缓存 */

DMAC1.DMDAR = (void *)&SCI1.TDR; /* 目标地址: SCI1.TDR 发送寄存器 */

DMAC1.DMCRA = 250; /* 指定传送个数 */

IPR(DMAC,DMAC1I) = 10; /* DMAC1I 中断优先级: Level 12 */

DMAC1.DMINT.BIT.DTIE = 1; /* 允许传送结束中断请求 */

IEN(DMAC,DMAC1I) = 1; /* 允许DMAC1I的中断请求 */

DMAC1.DMCNT.BIT.DTE = 0; /* 允许DMA数据传送 */

}

void init_uart(void)

{

dmac0_init(); /* 初始化DMAC0,用于串口SCI1接收 */

dmac1_init(); /* 初始化DMAC1,用于串口SCI1发送 */

SYSTEM.PRCR.WORD = 0xA502;

MSTP(SCI1) = 0;

SYSTEM.PRCR.WORD = 0xA500;

IEN(SCI1,ERI1) = 0; /* 禁用SCI1.ERI1中断 */

IEN(SCI1,RXI1) = 0; /* 禁用SCI1.RXI1中断 */

IEN(SCI1,TXI1) = 0; /* 禁用SCI1.TXI1中断 */

IEN(SCI1,TEI1) = 0; /* 禁用SCI1.TEI1中断 */

/*SCI1 module stop state cancel*/

SCI1.SCR.BYTE = 0x00; /* 禁用发送和接收 */

while (0x00 != (SCI1.SCR.BYTE & 0xF0)){}/* Confirm that bit is actually 0 */

/*only RE/TE/RIE/TIE==0 can write register*/

MPC.PWPR.BIT.B0WI = 0;

MPC.PWPR.BIT.PFSWE = 1;

MPC.P30PFS.BYTE = 0x0A;//RXD1

MPC.P26PFS.BYTE = 0x0A;//TXD1

MPC.PWPR.BIT.PFSWE = 0;

MPC.PWPR.BIT.B0WI = 1;

/*MPC=RXD and TXD*/

PORT3.PMR.BYTE |= 0x01U;//PORT3.PMR.BIT.B0 = 1;//串口管脚配置

/*PMR=peripheral*/

SCI1.SCR.BIT.CKE = 0; /* 使用内部波特率发生器*/

SCI1.SMR.BYTE = 0x20; /* 时钟源:PCLK */

/* 1个停止位,偶校验,数据位:8,异步通信 */

SCI1.SCMR.BYTE = 0xF2; /* SCI1通信模式:串行通信 */

SCI1.SEMR.BIT.ABCS = 1; /* ABCS值为0: 16个基本时钟为1bit的传送时间 */

/* ABCS值为1: 8个基本时钟为1bit的传送时间 */

SCI1.BRR = 0; /* 波特率: 0->781250bps ,所以最后波特率是1.5M*/

/*interrupt priority*/

IPR(SCI1, ) = 10;

IR(SCI1,RXI1) = 0;

IR(SCI1,TXI1) = 0;

IR(SCI1,ERI1) = 0;//

SCI1.SCR.BIT.RIE = 1;

SCI1.SCR.BIT.RE = 1;

IEN(SCI1,RXI1)=1;

IEN(SCI1,ERI1)=1;

DMAC.DMAST.BYTE = 0x01; /* DMAC启动 */

}

void uart_send(INT8U*pdata,INT8U len)//DMA定长模式发送250字节

{

int i = 0;

if(len>=250)

{

return;//发送长度不对

}

for(i = 0; i < 250; i++)

{

if(i < len)

{

sciTxBuf[i] = pdata[i];

}

else

{

sciTxBuf[i] = 0x00;

}

}

DMAC1.DMCNT.BYTE = 0x00;

DMAC1.DMSAR = (void *)sciTxBuf; /* 源地址: 传送缓存 */

DMAC1.DMCRA = 250; /* 指定传送个数,250字节 */

DMAC1.DMCNT.BYTE = 0x01;

PORT2.PMR.BIT.B6 = 1;

SCI1.SCR.BIT.TIE = 1;

SCI1.SCR.BIT.TE = 1;

IEN(SCI1,TXI1)=1;

}

void Excep_SCI1_ERI1(void)//串口接收错误中断

{

INT8U dummy;

dummy = SCI1.RDR;

dummy+=0;

init_uart_terminal();//重新配置串口

}

void Excep_DMAC_DMAC0I(void)// DMAC DMAC0I RCV

{

INT16U i;

for(i=0;i<250;i++)

{

message_buff[i]=sciRxBuf[i];// 接收内容缓存到message_buff

}

dmac0_init();

}

void Excep_DMAC_DMAC1I(void)// DMAC1 SEND

{

IEN(SCI1,TXI1) = 0;

SCI1.SCR.BIT.TIE = 0;

while(0 != SCI1.SCR.BIT.TIE){}

IR(SCI1,TXI1) = 0;

while(0 == SCI1.SSR.BIT.TEND){}

SCI1.SCR.BIT.TE = 0;

}

这里有一个问题需要大家在使用的时候思考并解决,在通讯过程中因串口丢失数据会导致DMA接收对不齐,也就是上一次的接收和下一次的接收内容会拼在仪器产生一个DMA接收中断,且该次中断的数据无效,并且只要一出现对不齐,如果不采取措施的话,那么以后永远都对不齐了。这个问题大家自行解决,也可以在评论区分享自己的见解。

相关问答

STM32中 DMA 有什么好处?

用和不用当然都可以发送。不用DMA发送是需要单片机实时参与,由单片机一个一个地发送数据并进行监控。但是如果用DMA,设置了起始地址,数据大小等参数后,就直接...

5通道 dma 是啥?

在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率,可以大大节省...

DMA 是什么,有什么功能?

DMA(DirectMemoryAccess,直接内存存取)是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于CPU的大量中断负载。否则,CPU需要从...

stm32系列 单片机 区别?

1、内核:51单片机采用的是51Core,8Bit@2MHzMax(分频后),0.06DMIPS;STM32采用的是ARMCortex-M3,32Bit@72MHz,1.25DMIPS2、地...

单片机 通讯协议有哪些?

1、单片机与其他单片机或芯片级的通讯协议有:RS232、IIC、SPI、并口(I/O)、DMA(如msp430、ARM);2、单片机通过电缆与PC或其他设备通讯协议有:RS232、RS485...

单片机 如何通过ADC模块采集模拟信号?

朋友们好,我是电子及工控技术,我来回答这个问题。众所周知单片机是一种超大规模的集成电路,它只能“读懂”并处理数字信号,对于连续量的模拟信号则无能为力。...

单片机 和cpu区别?

一、不同的指代1、CPU:作为计算机系统的操作和控制核心,是信息处理和程序操作的最终执行单元。2、单片机:又称mcu,是适当降低中央处理器的频率和规格,将存...

单片机 控制卡原理图

你说的是Rabbit5000吗。Rabbit5000是第一个具备16位内部总线架构的Rabbit微处理器,对于使用外扩16位内存设备提供了明显的性能提升。它也支持8...

手机的CPU算 单片机 么?

手机芯片也是单片机,不过这个单片机功能比一般的单片机强大很多。它们大多是32位的单片机,大多是ARM内核。不像我们平时用的都是4位或者是8位的,而且它们可以...

s3c2410是 单片机 吗?

S3C2410处理器是Samsung公司基于ARM公司的ARM920T处理器核,采用FBGA封装,采用0.18um制造工艺的32位微控制器。该处理器拥有:独立的16KB指令Cache和16KB数据Ca...

猜你喜欢