0.简介
DMA用于在存储器和外围功能模块之间传送数据,能够在CPU不参与的情况下实现存储器之间,存储器与外围功能模块之间的数据交换。
拥有2个DMA控制单元,共8个独立通道,可独立操作不同的DMA传输。每个DMA控制单元中包含4个通道,每个通道可以独立配置传输功能。
4个通道优先级顺序为:通道0>通道1>通道2>通道3。
当一个DMA单元有多个通道请求传输时将按优先级顺序执行。但已处于传输中的通道不会被打断,高优先通道需等当前通道传输完成后才会启动。
每个通道的启动源通过独立的触发源选择寄存器配置
每次请求传输一个数据块。数据块最小为1个数据,最多可以是1024个数据。每个数据的宽度可配置为8bit、16bit或32bit。
源地址和目标地址可以独立配置为固定,自增,自减,循环或指定偏移量的跳转
DMA的控制功能较为复杂,如不连续地址传输、连锁传输、中断等。本文仅介绍一些常规的操作。
如使用DMA的目的就是为了减少中断,因此一般来讲既然使用了DMA就不会使用中断了,本文就不介绍中断了。
DMA的具体配置与HC32F4A0基本一致,可参见《HC32F4A0_DMA控制器》
1. HC32F460_DMA例程
1.1 全局变量
unsigned char m_ucRevBuf[32]; //接收DMA数据的缓存
unsigned char m_ucRevTail=0; //接收缓存的尾指针
#define DMA_UNIT (M4_DMA1) //1号DMA单元
#define DMA_CH (DmaCh0) //第0个通道
#define DMA_TRG_SEL (EVT_USART2_RI) //触发事件是串口2的接收事件
1.2 初始配置
void DmaInit(void)
{
stc_dma_config_t stcDmaInit;
/* Enable peripheral clock */
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1,Enable); //使能DMA时钟
/* Enable DMA. */
DMA_Cmd(DMA_UNIT,Enable); //使能DMA1
/* Initialize DMA. */
MEM_ZERO_STRUCT(stcDmaInit);
stcDmaInit.u16BlockSize = 1u; //1个数据块
stcDmaInit.u32SrcAddr = ((uint32_t)(&M4_USART2->DR)+2ul); //源地址接收寄存器
stcDmaInit.u32DesAddr = (uint32_t)(&(m_ucRevBuf[0])); //目标初始地址寄存器
stcDmaInit.u16DesRptSize = 32; //m_ucRevBuf的长度为32字节
stcDmaInit.stcDmaChCfg.enSrcInc = AddressFix; //固定源地址
stcDmaInit.stcDmaChCfg.enDesInc = AddressIncrease; //递增目的寄存器
stcDmaInit.stcDmaChCfg.enIntEn = Disable; //禁能中断
stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit; //每个数据8位
stcDmaInit.stcDmaChCfg.enDesRptEn = Enable; //使能重复区域
DMA_InitChannel(DMA_UNIT, DMA_CH, &stcDmaInit);
/* Enable the specified DMA channel. */
DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);
/* Enable peripheral circuit trigger function. */
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS,Enable); //使能AOS系统
DMA_SetTriggerSrc(DMA_UNIT, DMA_CH, DMA_TRG_SEL); //使能触发源
}
1.3 接收处理
short Sci_Recv( unsigned char *pucBuf , unsigned short usBufSize)
{//(M4_DMA1->MONDAR1 为目标地址寄存器的当前位置
unsigned short usHead = (M4_DMA1->MONDAR1 - (uint32_t)(&(m_ucRevBuf[0]))) &0x1F;
unsigned short usLen = (usHead - m_ucRevTail) & 0x1F; //
if(usHead > m_ucRevTail) //线性的
memcpy( pucBuf , m_ucRevBuf + m_ucRevTail , usLen );
else if( usHead < m_ucRevTail) //循环的
{
unsigned short usHalfLen = 32 -m_ucRevTail;
memcpy( pucBuf , m_ucRevBuf + m_ucRevTail , usHalfLen);
memcpy( pucBuf + usHalfLen , m_ucRevBuf , usLen - usHalfLen );
}
m_ucRevTail = usHead;
return usLen;
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/liyangchun_2/article/details/149153981
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/liyangchun_2/article/details/149153981
|