请选择 进入手机版 | 继续访问电脑版
搜索
查看: 4492|回复: 25

【说出你的故事】在外设与存储器之间

  [复制链接]

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2020-9-28
发表于 2016-2-21 22:08:21 | 显示全部楼层 |阅读模式
    偶然看到自己刚来社区时发的一个关于DMA的跟帖 说的是使用DMA写SD。在社区STM32的交流QQ群里也经常看到很多小伙伴在讨论DMA,那今天就说说我常用的几个例子。

参考手册上是这样介绍DMA的:用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。从上面我们可以看到DMA就好比是个“包邮的快递”一样,可以不收钱(不占用CPU)帮我们送快递(传递数据),有这等便宜岂能放过,我们必须要“用用用”!

1、DMA写SD卡
我最开始使用DMA是写SD卡,因为STM32的SPI在连续传递数据时字节和字节之间有很大的时间间隔,这导致了写一个扇区需要很长的时间,经过很多测试发现字节之间的间隔没法很好的被优化掉,所以就考虑用DMA写SD卡了。使用DMA写SD卡时只需设置好要写的数据,然后使能DMA传输完成中断,在中断中判断写数据是否成功。
如果使用常规的SPI写SD没有问题,那么修改为SPI的DMA模式写SD就卡就比较简单了。只需要修改下面几个函数即可。
1) 在写512字节时使用DMA传输
1.jpg
2.jpg

2) 在中断函数中进行判断即可
  1. <font size="4" face="Tahoma">void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
  2. {
  3.                 uint8_t t,s;
  4.                 //扇区写完后发送校验字节
  5.                 SPI2_ReadWriteByte(0xFF);
  6.                 SPI2_ReadWriteByte(0xFF);
  7.                 for(s = 0;s < 255;s++)
  8.                 {
  9.                         //接收响应        
  10.                         t = SPI2_ReadWriteByte(0xFF);
  11.                         if((t&0x1F)==0x05)        
  12.                         {
  13.                                 SD_DMA_Write_Status = Status_OK;
  14.                                 break;
  15.                         }
  16.                 }
  17.                 if(s == 0xff)
  18.                 {
  19.                         s = s;
  20.                 }
  21.                 SD_DisSelect();

  22. }</font>
复制代码
2、DMA传输多通道ADC采集数据

这个测试使用NUCLEO-STM32F410RB,我们先初始化4个通道的ADC输出,然后用DMA将转换的数据传到数组中。
  4个通道配置如下:

adc_1.jpg
ADC1初始化如下:
adc_2.jpg
然后在main函数中开始adc的转换:
  1. <font size="4" face="Tahoma">#include "main.h"

  2. __IO uint16_t uhADCxConvertedValue[4];
  3. int main(void)
  4. {
  5.         HAL_Init();
  6.         SystemClock_Config();
  7.         LED_Init();
  8.         USART2_Init();
  9.         ADC1_Init();
  10.         ADC1_Config();
  11.         HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&uhADCxConvertedValue, 4);

  12.         while(1)
  13.         {
  14.                
  15.         }               
  16. }
  17. </font>
复制代码
首先悬空4个输入引脚,从转换结果可以看到ADC的值为随机值,这也说明了可以使用悬空ADC引脚的方法来产生随机数是可行的

adc_3.jpg adc_4.jpg
将其中的2个通道接地,可以看到ADC的值接近0


adc5.png


3、使用DMA和串口空闲中断接收不定长数据
这个测试也使用NUCLEO-STM32F410RB。串口在接收数据时使用空闲中断和DMA接收不定长的数据,在发送时使用DMA发送。使用这个方法能够很方便的接收不定长的数据,但是也有一些限制,实际使用中如果出现问题要根据需要优化。

需要注意的是使用HAL库要自己写个回调函数如下:
232_0.jpg
在main中我们将PC端发送的数据返回到PC端:
  1. <font size="4" face="Tahoma">#include "main.h"

  2. int main(void)
  3. {
  4.         HAL_Init();
  5.         SystemClock_Config();
  6.         LED_Init();
  7.         USART2_Init();
  8.         while(1)
  9.         {
  10.                 if(U1_Rxlen)
  11.                 {
  12.                         HAL_UART_Transmit_DMA(&UARTHandle,aU3RxBuff,U1_Rxlen);
  13.                         U1_Rxlen = 0;
  14.                 }
  15.         }               
  16. }
  17. </font>
复制代码

发送不同长度的数据,可以看到都能够正确接收:
232_1.jpg

      上面只是DMA的几个最简单的使用,因为比较常用而且简单,所以并没有详细的叙述,具体可以参考代码。测试代码是使用hal写的,明白了原理很容易转换为标准库。DMA在其他的外设也有很多可以使用的场合,合理使用DMA能起到事倍功半的效果。

    周末撸代码不易,希望人品能够给力赶上这个活动的末班车 :)  @苏柚

  测试代码:
SPI SD DMA.rar (4.36 KB, 下载次数: 60)
回复

使用道具 举报

该用户从未签到

16

主题

3025

帖子

2

蝴蝶豆

论坛元老

最后登录
2020-8-18
发表于 2016-2-21 22:24:38 | 显示全部楼层
这贴子不错,长知识。
回复 支持 反对

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2020-9-28
 楼主| 发表于 2016-2-21 23:09:37 | 显示全部楼层
lising 发表于 2016-2-21 22:24
这贴子不错,长知识。

感谢支持  
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

97

帖子

0

蝴蝶豆

高级会员

最后登录
2020-3-24
发表于 2016-2-23 14:16:08 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

5

主题

76

帖子

0

蝴蝶豆

高级会员

最后登录
2019-6-11
发表于 2016-3-1 17:41:47 | 显示全部楼层
这个可以,最开始为难了好久
回复 支持 反对

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2020-9-28
 楼主| 发表于 2016-3-1 18:41:37 | 显示全部楼层
idodoyo 发表于 2016-3-1 17:41
这个可以,最开始为难了好久

是的,刚开始接触的时候的确有点难搞。
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

15

帖子

0

蝴蝶豆

初级会员

最后登录
2018-9-3
发表于 2016-3-2 08:52:09 | 显示全部楼层
学习了。。。
回复

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2020-9-28
 楼主| 发表于 2016-3-2 08:59:32 | 显示全部楼层

                                
回复 支持 反对

使用道具 举报

该用户从未签到

2

主题

25

帖子

0

蝴蝶豆

初级会员

最后登录
2020-3-22
发表于 2016-3-2 21:39:38 | 显示全部楼层
谢谢分享,支持一个!
回复 支持 反对

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2020-9-28
 楼主| 发表于 2016-3-2 23:22:02 | 显示全部楼层
雪山飞狼 发表于 2016-3-2 21:39
谢谢分享,支持一个!

感谢支持!!!
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

站长推荐上一条 /2 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2020-10-21 01:27 , Processed in 0.098906 second(s), 25 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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