OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8536|回复: 6

SPI 的DMA 模式 只有第一次成功

[复制链接]

233

主题

958

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1796
金钱
1796
注册时间
2011-10-9
在线时间
223 小时
发表于 2016-1-18 17:38:39 | 显示全部楼层 |阅读模式
27金钱
本帖最后由 simms01 于 2016-1-18 18:02 编辑

程序主题大概如下
void dma(void)
{
  u8 buf[16];
u16 j,i;

for (i=0;i<16;i++)
{
buf=i;
}


//初始化spi2
SPI2_Init(MSB);
//设置dma
MYDMA_Config(DMA1_Channel5 ,(u32)&SPI2->DR,(u32)buf,16);//DMA1通道4,外设为SPI2,存储器为SendBuff,长度5168.
//传输2000次
for (j=0;j<2000;j++)
{

MYDMA_Enable(DMA1_Channel5);
  //等待传输完成
  while( ( DMA1->ISR & (1<<17) ) == 0  ) ;
}
}

//**************************//*************************
只有开机第一次call 这个 dma()  spi的数据发出来是正常的  再call 就错了

buf[]的数据没有错 只要不用DMA 用硬件SPI发出来是正确的

//***************************DMAd的设置
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC->AHBENR|=1<<0;   //开启DMA1时钟
//RCC->AHBENR|=1<<1;   //开启DMA2时钟
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;   //非存储器到存储器模式     
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_CHx->CCR&=~(1<<0);       //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0;          //开启DMA传输
}   

最佳答案

查看完整内容[请看2#楼]

我有一次不小心也遇到过类似问题。 先说结论: DMA的源地址千万不要设置为局部变量(数组)的地址! DMA的源地址千万不要设置为局部变量(数组)的地址! DMA的源地址千万不要设置为局部变量(数组)的地址! 针对你的问题,DMA能发送,说明DMA肯定配置好了。 你把DMA的源地址指向一个局部变量buf,但你知否,一旦void dma(void)这个函数执行完毕,buf这个存储在栈的数组要被弹出来的! 因此,DMA的源地址是一个野指 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-1-18 17:38:40 | 显示全部楼层
我有一次不小心也遇到过类似问题。

先说结论:
DMA的源地址千万不要设置为局部变量(数组)的地址!
DMA的源地址千万不要设置为局部变量(数组)的地址!
DMA的源地址千万不要设置为局部变量(数组)的地址!



针对你的问题,DMA能发送,说明DMA肯定配置好了。
你把DMA的源地址指向一个局部变量buf,但你知否,一旦void dma(void)这个函数执行完毕,buf这个存储在栈的数组要被弹出来的!
因此,DMA的源地址是一个野指针,野指针!!

解决方法,把buf的定义放在函数外面,或者定义成静态的。

另外,你的函数能编译通过吗?
buf=i;

这不会报错??
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

233

主题

958

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1796
金钱
1796
注册时间
2011-10-9
在线时间
223 小时
 楼主| 发表于 2016-1-18 17:43:25 | 显示全部楼层
本帖最后由 simms01 于 2016-1-18 17:44 编辑

dma.jpg
只有第一个正确的

dma2.jpg
错误的也有数据 就是数据是错的

回复

使用道具 举报

233

主题

958

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1796
金钱
1796
注册时间
2011-10-9
在线时间
223 小时
 楼主| 发表于 2016-1-20 10:32:27 | 显示全部楼层
xkwy 发表于 2016-1-18 19:44
我有一次不小心也遇到过类似问题。

先说结论:

谢谢老大 解答得很详细

那个buf=i 是手误呵,帖子上的代码手敲的 呵

回复

使用道具 举报

233

主题

958

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1796
金钱
1796
注册时间
2011-10-9
在线时间
223 小时
 楼主| 发表于 2016-1-20 10:35:23 | 显示全部楼层
本帖最后由 simms01 于 2016-1-20 10:38 编辑
xkwy 发表于 2016-1-18 17:38
我有一次不小心也遇到过类似问题。

先说结论:


大概明白了 执行完第一个循环 dma发送完一次后 buf的值或者 地址 被改变了或者不可预计了。
回复

使用道具 举报

3

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2016-8-30
在线时间
12 小时
发表于 2017-2-9 20:55:03 | 显示全部楼层
我的问题是只有第一次DMA有数据,后面的DMA数据,SPI都没有发,这个是什么原因
回复

使用道具 举报

1

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2019-7-30
在线时间
29 小时
发表于 2022-8-17 10:25:01 | 显示全部楼层
我的问题是,初次上电dma数据错误,看波形是丢了几位。但是单片机重启就好了。冷启动就用问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 07:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表