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

【经验分享】STM32 DMA总结库函数串口使用DMA

[复制链接]
STMCU小助手 发布时间:2022-5-8 19:00
前言
/ s- w7 ~# V  V1 DDMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接' Z& a8 M4 n( P0 z
控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备
) b* E' A  M' S* c# @; }& o. H! B开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。
, f0 o+ p5 m( U  O9 O0 J. z5 N9 ^# Q( n5 F2 L
一、配置步骤/ P0 ~/ _, ~7 W
1)使能 DMA 时钟
- U4 f: j4 B1 R

- U: @( h  l% J) w0 \0 A
  1. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
复制代码
5 Z1 W( ^& [' W6 F1 j
4 i: u2 h$ _1 `
2)初始化 DMA 通道 4 参数
( S8 G2 I( @7 r, s+ x
  I& b* s! I2 L, C5 ?9 G
  1. void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
复制代码
  1. DMA_InitTypeDef DMA_InitStructure;
    ' s. C0 D" q- z/ ^8 e
  2. DMA_InitStructure.DMA_PeripheralBaseAddr = &USART1->DR; //DMA 外设 ADC 基地址
    , J, a" n- g9 L- z, |
  3. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
    1 x6 X9 w: C7 v' L# j+ k! b% I4 f) ]
  4. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //从内存读取发送到外设7 |# A2 H( L8 P9 S4 c
  5. DMA_InitStructure.DMA_BufferSize = 64; //DMA 通道的 DMA 缓存的大小2 ?0 Q! B  l# f$ z/ \0 {( L
  6. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
    ; S: n! J3 x  I! w
  7. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址递增$ ^# @, n9 C6 {. u$ @
  8. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //8 位1 x8 \+ [' j, a" H0 s
  9. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8 位& _. @7 j* u6 @& X+ r
  10. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
    " S/ T* t) s2 ?  y+ f: d
  11. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA 通道 x 拥有中优先级% ~. U5 J7 i  \: f* E6 ]* C
  12. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输
    5 x* j! s" ]( M# E& V) T
  13. DMA_Init(DMA_CHx, &DMA_InitStructure); //根据指定的参数初始化
复制代码

) `; c; g0 ?& u9 X& e( _8 C3)使能串口 DMA 发送
  1. USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
复制代码
* u& R" O- `  j; p
4)使能 DMA1 通道 4,启动传输
, m: X& B/ P+ u. `9 P& ]0 L" U# B8 E
; H- I1 B" E: G% S2 ], X  l5 p
  1. DMA_Cmd(DMA_CHx, ENABLE);
复制代码

! P- X) S" m# C& ~+ f5)查询 DMA 传输状态
+ [# ~7 a/ @0 o, g* D
: F; t' z- {+ _+ F6 I% d在 DMA 传输过程中,我们要查询 DMA 传输通道的状态:
3 p) q2 |( \& R( z, Z2 C/ f; M
6 Y2 g& U4 C- L6 ?FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
" E$ |* p5 j5 R( h6 l: a5 m* X, {; K$ l/ r% i4 s8 j
比如我们要查询 DMA 通道 4 传输是否完成:, _- D* ^6 r4 t
  H' ]) E* Q* \
DMA_GetFlagStatus(DMA2_FLAG_TC4);
! i  ^# E: ^. B7 N, }# Z1 ~
7 q* u; R5 B0 v5 C% l1 J( q/ L获取当前剩余数据量大小的函数:
  1. uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
复制代码

7 x  e& c5 I; I$ M" R! a$ d比如我们要获取 DMA 通道 4 还有多少个数据没有传输:
  1. DMA_GetCurrDataCounter(DMA1_Channel4);
复制代码

: V8 n; n6 h0 D0 M8 J9 l$ i二、代码实例
/ y3 z  J; I# s) A# K我们需要创建dma.c 文件和其头文件 dma.h,9 h* {* l: W5 o4 f0 w
同时我们要引入 DMA 相关的库函数文件 stm32f10x_dma.c 和 stm32f10x_dma.h。8 Z; x5 l2 o2 y1 L8 R5 Q

0 D+ j& G$ M( e8 R/ Y/ g" [2 T: A3 t/ p——dma.c 文件
; Y% W* N6 S( C3 \) ~  i, l* `" D% A% T# |
  1. #include "dma.h"
    8 Y9 Q1 T( J, X0 p' O3 i# ]1 v
  2. DMA_InitTypeDef DMA_InitStructure;
    8 g5 U) l2 g9 K( g
  3. u16 DMA1_MEM_LEN;//保存 DMA 每次数据传送的长度
    2 c/ C2 |, R/ \8 r) r. t9 q( `0 K
  4. //DMA1 的各通道配置
    ' U2 ^$ k7 z3 r$ [; y
  5. //这里的传输形式是固定的,这点要根据不同的情况来修改
    % }% d' c' S/ ?# t& ~, M5 Y
  6. //从存储器->外设模式/8 位数据宽度/存储器增量模式" M6 E% P6 ?# p$ D
  7. //DMA_CHx:DMA 通道 CHx$ [$ l4 w5 [5 G& c$ s7 i
  8. //cpar:外设地址# B2 z# T+ i6 y. y; N( S
  9. //cmar:存储器地址8 q' w, T9 _' X2 L) z3 ^( S5 E
  10. //cndtr:数据传输量
    7 f5 Q* W: p' c0 I9 j- z8 o
  11. void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
    % j' k. }  {5 p3 l5 ~: n  l
  12. {
    $ m# s/ f/ @  U+ G
  13. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
    6 ?$ y7 X3 Z* Q+ r) j7 V& l
  14. DMA_DeInit(DMA_CHx); //将 DMA 的通道 1 寄存器重设为缺省值! n% y) u9 j/ a' \8 P
  15. DMA1_MEM_LEN=cndtr;% l+ {. l. F8 y6 w% n. c
  16. DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA 外设 ADC 基地址
    . x% }5 g. H/ `
  17. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
    ; k5 Y) Z* F0 ^8 J
  18. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向内存到外设
    ; n- z6 |- s5 C. _* |( g; m0 f
  19. DMA_InitStructure.DMA_BufferSize = cndtr; //DMA 通道的 DMA 缓存的大小
    ( N( l$ U5 c( |$ D7 A! |# b2 k7 R. D
  20. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不变# t0 F) e) M* \# T& e6 Q
  21. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增
    , n+ i, \; e/ Y8 v& b. Q
  22. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    7 @1 P* p, O. t9 |( ^( J; k* x4 `
  23. //数据宽度为 8 位% g$ B6 |$ j! \) e
  24. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度( H+ W& D" x# w' J5 S2 R5 ?) u
  25. //为 8 位
    ; y+ n0 n1 ?3 i. ^6 w* [, e
  26. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
    . t8 _# Z6 l! c1 v0 W
  27. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DM 通道拥有中优先级
    3 b2 G. r$ c+ k( P
  28. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输; C# F! L6 U4 ^: N8 V. s' V
  29. DMA_Init(DMA_CHx, &DMA_InitStructure); //初始化 DMA 的通道
    # E0 l& z( O: B. e9 A
  30. } * N/ y/ N" j# }- I
  31. //开启一次 DMA 传输3 a' w; Y# w! ~0 }: H/ g$ q& g5 P, W
  32. void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)7 e# G. K" ?5 }6 r& y
  33. { : P' ?+ o: M- q3 B/ l# K/ k
  34. DMA_Cmd(DMA_CHx, DISABLE ); //关闭 USART1 TX DMA1 所指示的通道 5 g. G4 H+ g; y* j& k! @6 B" k
  35. DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//设置 DMA 缓存的大小1 ^: e# b, z# g( F7 Y! V; u0 A  ]- a
  36. DMA_Cmd(DMA_CHx, ENABLE); //使能 USART1 TX DMA1 所指示的通道
    . v- k6 p7 C1 G7 v0 P  q$ n: z
  37. }
    % W8 n8 K3 t* \& b# t
复制代码
7 a) L/ y! d. @' `
收藏 评论0 发布时间:2022-5-8 19:00

举报

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