STM32 DMA单字节传输失败的原因分析---寄存器版本
套用正点原子 实验18 DMA实验
u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度 //DMA1的各通道配置 //这里的传输形式是固定的,这点要根据不同的情况来修改 //从存储器->外设模式/8位数据宽度/存储器增量模式 //DMA_CHx:DMA通道CHx //cpar:外设地址 //cmar:存储器地址 //cndtr:数据传输量 void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { RCC->AHBENR|=1<<0; //开启DMA1时钟 delay_ms(5); //等待DMA时钟稳定 DMA_CHx->CPAR=cpar; //DMA1 外设地址 DMA_CHx->CMAR=(u32)cmar; //DMA1,存储器地址 DMA1_MEM_LEN=cndtr; //保存DMA传输数据量 DMA_CHx->CNDTR=cndtr; //DMA1,传输数据量 DMA_CHx->CCR=0X00000000; //复位 DMA_CHx->CCR|=1<<4; //从存储器读 DMA_CHx->CCR|=0<<5; //普通模式 DMA_CHx->CCR|=0<<6; //外设地址非增量模式 DMA_CHx->CCR|=1<<7; //存储器增量模式 DMA_CHx->CCR|=0<<8; //外设数据宽度为8位 DMA_CHx->CCR|=0<<10; //存储器数据宽度8位 DMA_CHx->CCR|=1<<12; //中等优先级 DMA_CHx->CCR|=0<<14; //非存储器到存储器模式 }
我的项目是需要通过SPI传输单字节数据给DAC;
u8 cmd [2]= {0xee}; u8 cmd1 = 0xee; MYDMA_Config(DMA1_Channel3,(u32)&SPI1->DR,(u32)cmd1,1); //SCLK时钟正常输出,MOSI引脚无波形输出 MYDMA_Config(DMA1_Channel3,(u32)&SPI1->DR,(u32)cmd,2); //SLKC时钟正常输出,MOSI引脚波形正常输出
经过看STM32指南手册发现:CPAR和CMAR二者都是地址。
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
回头看函数参数定义:u32 cpar,u32 cmar 定义上看不出来,只能说是32bit的数
MYDMA_Config(DMA1_Channel4,(u32)&USART1->DR,(u32)SendBuff,(TEXT_LENTH+2)*100); //原程序串口DMA定义
CPAR是(u32)&USART1->DR,在输入前就已经提取地址(&取地址符合),而CMAR是SendBuff。
-
在 C 语言中,数组名(如
SendBuff
)本身代表的是数组的首元素的地址,换句话说,SendBuff
等同于&SendBuff[0]
。 -
当你执行
adb = SendBuff;
时,adb
被赋值为SendBuff
的地址(即SendBuff
的首元素地址),这意味着adb
现在指向了SendBuff
数组的起始位置。
因为SendBuff是数组,在CMAR=SendBuff时,直接赋值的是SendBuff首元素的地址;
u8 cmd1 = 0xee; MYDMA_Config(DMA1_Channel3,(u32)&SPI1->DR,(u32)cmd1,1);
在上面这种情况下:直接将cmd1的值赋值给CMAR,而不是cmd1的数据地址,导致DMA读取错误的地址。