你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【零基础学习STM32】第十一讲:DMA实验——存储器到存储器...

[复制链接]
kkhkbb 发布时间:2018-4-3 11:48
本帖最后由 kkhkbb 于 2018-4-3 21:17 编辑 " v) M* O8 H6 }) ^. ~, V1 W
# j- o. f: r1 e( p" M9 b
一、概述:. v9 p* ^0 V& s
1、DMA简介
; z9 q# ]1 B. H7 P" Q
      DMA的英文拼写是"Direct Memory Access",汉语的意思就是直接内存访问,是一种不经过CPU而直接从内存存取数据的数据交换模式。在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率,可以大大节省系统资源。DMA模式又可以分为Single-Word DMA(单字节DMA)Multi-Word DMA(多字节DMA)两种。9 \) V- [/ ]  r: z" U- k
2、 DMA工作原理
; x$ U0 d& O/ ~( z; x0 ~
      DMA 允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把他们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。
5 Q% g; J$ G+ [; K
      DMA 传输主要地将一个内存区从一个装置复制到另外一个。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存去。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。所以,DMA传输对于高效能嵌入式系统算法和网络是很重要的。
: a8 ~1 s: W/ D* r# t! h. e
3、DMA类别6 w- o% F3 m. j% Y
     按键主要有两种类型:单字节DMA、多字节DMA
0 [* a; R: q: z- G8 X% p. ^, P
        单字节DMA:一次传送一个字节,效率较低,但它会保证在两次DMA传送之间,CPU有机会获得总线控制权,执行一次CPU总线周期。- l  J1 ^( e* z! }( }
       多字节DMA:一次请求传送一个数据块,效率高,但在整个DMA传送期间,CPU长时间无法控制总线(无法响应其他DMA请求,无法处理其他中断等)。
二、实验原理:
      DMA(直接存储器访问)传输不需要占用CPU,可以在存储器至实现高速的数据传输。本实验采用DMA2控制器的数据流0,选用通道0进行数据传输。通过LED的颜色来判断传输是否成功。
三、源代码
1.主函数及DMA设置7 {3 ^/ \+ s! e! T0 ]
  1. /*6 j/ s) x) F5 ]) B8 J
  2. * Name                : main
    ) o5 J* o/ @3 H% R3 d6 L, C
  3. * Description         : ---. d! ~1 P0 L2 Q+ O  Q4 e4 ~2 x8 C
  4. * Author              : ysloveivy.8 J% P& Z. I6 y+ {  {. L
  5. *1 e' W( o: {7 r/ X" e
  6. * History( J2 [2 Y6 J0 \; H, e0 b0 @
  7. * --------------------
    9 B. t( u9 s& p( X4 N7 U
  8. * Rev                 : 0.009 ~3 H  M$ K3 d" M
  9. * Date                : 11/21/2015% C6 v+ R4 C# ]& n/ p, h
  10. *
    & l3 {1 h, i4 B& l2 i
  11. * create.% y+ g- ?+ g" ~8 e# b4 @
  12. * --------------------( i5 m9 D8 M: Z5 o+ P- \! A- J  _
  13. */
    5 K* |+ ?: R7 x8 ?
  14. int main(void)5 a6 H; f+ O) G) d. \
  15. {( h2 A8 E: c& h2 g
  16.         int i,k;2 D" q: B! q# |* L2 T5 o
  17.         DMA_InitTypeDef  DMA_InitStructure;
    1 G0 R. G( U' S# D2 z9 h
  18. . A3 Z- L# q$ S
  19.         led.initialize();
    + ^3 E6 m& ]- E- R( k5 \4 `0 T
  20.         dma.initialize();* l4 c7 G" N9 ^$ c- R

  21. 6 ^+ [8 J6 A. d9 R8 S+ b
  22.         //测试DMA,测试成功蓝灯闪烁,测试失败,红灯闪烁
    ' _6 t8 y+ N" h
  23.         DMA_InitStructure.DMA_Channel = DMA_Channel_0;                              //选择通道0
    + j- t; d4 o: y) f
  24.         DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long int)src_buffer;     //DMA外设基地址
    * Q) i0 k6 Q6 C- [
  25.         DMA_InitStructure.DMA_Memory0BaseAddr = (unsigned long int)dst_buffer;    //DMA存储器地址  d; d6 g# ^& t4 s% m
  26.         DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;               //方向为存储器到存储器
    ' J# C8 s+ T6 s  c0 J7 @
  27.         DMA_InitStructure.DMA_BufferSize = (unsigned long int)BUFFER_SIZE;         //数据传输量
    1 w$ D9 K. J4 l3 c
  28.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;    //外设增量模式
    8 c+ a; d6 u, Z
  29.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     //存储器增量模式7 h9 a7 H; Q7 ]+ c2 v8 ]* L  t3 B% g
  30.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //设置外设数据宽度
    , t& I+ a  w  W) q: l9 e" G
  31.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;      //设置存储器数据宽度
    $ C0 i" x- u+ x+ m; S9 p5 X" R
  32.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                          //运行模式为普通模式
    ! ?2 z% i( ]( _
  33.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;                     //优先级级别为高! {3 Q9 i$ @+ a
  34.         DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                    //FIFO模式禁止
    ! S+ D% ~4 g$ |) C- H, b0 y- Z# }6 t- E
  35.         DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;        //FIFO阈值! g* j% A6 l( n3 W
  36.         DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;            //存储器突发单次传输* r; n- x) J" d- }
  37.         DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;   //外设突发单次传输" }1 B1 d  e+ ~, m% u, U  M
  38.         DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    " `5 X! p! F& {. R
  39.         DMA_Cmd(DMA2_Stream0, ENABLE);       //使能DMA2_Stream0                                      
    + r$ x# |& _9 o5 _! Q3 @9 j

  40. ( A# h; F  a, i1 M# B( Z
  41.         while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);
    0 D6 @) [! ?8 o1 s9 W$ @) w* R6 Y

  42. 4 ^9 a$ h: l2 k9 ^; q
  43.         for(i = 0;i < BUFFER_SIZE;i++){
    ; S4 n. K/ w5 i
  44.                 if(dst_buffer[i] != src_buffer[i]){
    2 ~: }7 G% |. S) i
  45.                         //测试失败
    7 q. ^3 m" A. w8 `  C! \3 A
  46.                         while(1){
    ( t: w4 g/ M1 ~! e
  47.                                         for(k = 0;k < 10000000;k++);- a; r( n7 D; W- \
  48.                                         LED_RED_ON;
    . @) P: Y) h  ?2 w5 p: `
  49.                                         for(k = 0;k < 10000000;k++);
      |; F: [9 M: u" U" p
  50.                                         LED_RED_OFF;/ _7 {" N( b* g5 j* b3 A
  51.                         }
    & ?4 b: ], D1 ~( i: J' x  S
  52.                 }# o% d  {6 w2 m2 C, {6 F  o$ z' U
  53.         }
    + z9 d. K0 S' Y" n) t
  54.         //测试成功
    3 A0 P. g% U3 d2 x- }
  55.         while(1){
    ; k- A+ N: n2 y" c& L
  56.                 for(k = 0;k < 10000000;k++);& L# I/ A6 h, z- P5 ^
  57.                 LED_BLUE_ON;
    2 c  z( X8 }! f& S" @' u
  58.                 for(k = 0;k < 10000000;k++);
    : E7 ^  d8 \+ ]
  59.                 LED_BLUE_OFF;
    ' j5 o( b9 {! ^/ w9 ^9 q  x: |$ m8 I: W
  60.         }
    ' X3 Y' Q" ~, O; p. |7 {
  61. }; {- M9 w! J: Q0 k# x& z9 Q
复制代码
2DMA初始化函数" a+ ~; O4 P" K4 m' ^9 V
  1. /*9 t. Q6 ]1 h6 E- Z, t6 ?2 h, S- o5 D5 O
  2. * Name                : initialize- e: X  ?6 E9 _" `+ M( b1 D" \* ^, a
  3. * Description         : ---
    0 z6 ^* _* D6 `$ b% ^- r: ]* s
  4. * Author              : ysloveivy.
    9 o. R3 z. W4 y
  5. *! S7 B* K/ x1 B( M
  6. * History: w+ V, |& w: w  i
  7. * --------------------
    3 Q% ?) Y5 Q. R  W0 O
  8. * Rev                 : 0.00
    5 o6 q$ L: _- r: I) }5 o# ^  Y4 p, J
  9. * Date                : 11/29/2015% b$ I7 {. [( m8 ]; Z
  10. *
    4 i% R  N& a* X" |& b8 O
  11. * create.
    & W: E5 P/ T. ?& r/ e& r9 R+ ~
  12. * --------------------% k' T, d/ s( q2 J# T2 _
  13. */
      A3 P2 {, S2 j9 c! h  q

  14. * m7 Z# P& @# E7 P/ G8 S
  15. static int initialize(void). h( Z' M" k9 m6 ^# Q' D& B
  16. {
    * b; y& U9 O9 J1 [
  17.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);     
    6 A1 g0 |+ x6 F5 F
  18. //使能DMA2时钟" m/ ]1 `* `* L2 w% @4 g
  19.   DMA_DeInit(DMA2_Stream0);                                                        //配置DMA2
    - A8 H( y& R' T0 s* u
  20.   while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE)                                //等待DMA可配置
    ! F1 m5 {3 f+ l: \; H( n
  21.   {
    ' q& U2 H: {! a
  22.   }
    & K9 i/ E& b% G3 ]- C3 S

  23. - A: K& E3 N& p* }7 X: L$ A
  24.         return 0;
    ( }0 x$ U) X( G3 }) T* W6 ?
  25. }
复制代码
3、小知识
     在DMA的设置中我们遇到了关于DMA设置的结构体,我们通过配置其相关参数,以实现我们想要的功能,其解释如下:
  1. typedef struct
    % {; z$ i3 ~4 F" H
  2. {
    5 w$ F+ J( h. K+ u& d
  3.     uint32_t DMA_Channel;                   //选择通道3 u" Z& L, ]/ _+ M- ^9 u
  4.     uint32_t DMA_PeripheralBaseAddr;     //DMA外设基地址& c& {- s) l. @
  5.     uint32_t DMA_Memory0BaseAddr;         //DMA存储器地址                     
    8 u7 G9 O1 u+ g! [; \3 E* L
  6.     uint32_t DMA_DIR;                       //DMA传输方向
    " v. C, L3 D& T6 O9 m8 i* f
  7.     uint32_t DMA_BufferSize;               //数据传输量
    ; p' X2 R! x7 k6 V! Q
  8.     uint32_t DMA_PeripheralInc;           //外设增量模式选择+ c; c- I3 L2 P2 }9 o$ n
  9.     uint32_t DMA_MemoryInc;                //存储器增量模式5 s' Y9 _6 r; w+ @" K0 }
  10.     uint32_t DMA_PeripheralDataSize;     //设置外设数据宽度
    ; [: t5 W1 j- f2 f! ~- D, S# ^
  11.     uint32_t DMA_MemoryDataSize;          //设置存储器数据宽度
    6 l- f4 c) D+ H6 X' ?$ w/ x2 ?
  12.     uint32_t DMA_Mode;                      //运行模式选择2 l8 d; d, w. N5 h+ p- P1 f- ~% r2 i* R
  13.     uint32_t DMA_Priority;                 //优先级选择
    4 ]3 y) |6 X/ h5 b9 r# @
  14.     uint32_t DMA_FIFOMode;                 //FIFO模式选择5 \& j8 N8 w( ~# ^* y
  15.     uint32_t DMA_FIFOThreshold;           //FIFO阀值
      ]# W# k5 a" P8 i% Q& {) V
  16.     uint32_t DMA_MemoryBurst;             //存储器突发单次传输
    ' S, ~- u: b& u  t$ g# j
  17.     uint32_t DMA_PeripheralBurst;        //外设突发单次传输                        & }) I* O# @+ ]) f
  18. }DMA_InitTypeDef;
复制代码
四、实验现象
      试验成功蓝色LED灯闪烁,试验反败红色LED灯闪烁。
五、代码包下载连接

# Y) S/ Z: m8 q5 z# \

$ y4 i, s3 x1 o: @& m# N; V( l% B( I
0 t# V- ~( d$ A6 Q7 T; S3 H) s; ]: ?
5 f$ h0 Z/ K" u% V$ u

9 o4 O7 h( Y+ ?$ \
7 P( o1 z9 ^8 X

评分

参与人数 1 ST金币 +2 收起 理由
MrJiu + 2 赞一个!

查看全部评分

收藏 评论5 发布时间:2018-4-3 11:48

举报

5个回答
大陶 回答时间:2018-4-3 16:19:07
谢谢分享
MrJiu 回答时间:2018-4-4 09:40:00
非常不错!!!
a110-130038 回答时间:2018-4-4 14:49:16
谢谢分享
西点钟灵毓秀 回答时间:2018-4-4 23:14:59
不错,是要好好学习了
samhong 回答时间:2018-5-11 06:52:54
学习了。

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版