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读取错误的地址。

 

posted on 2025-04-18 18:51  Aliang2020  阅读(45)  评论(0)    收藏  举报