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

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

[复制链接]
STMCU小助手 发布时间:2022-5-8 19:00
前言: T0 n; M, N8 a
DMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接
# Y) V; R! p1 h$ G/ n0 @* q# Y控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备
# {1 t2 S5 E1 F开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。' \9 C& C* C( E9 q" g. [' [

2 U$ t; \6 W1 G, @% m! g6 d一、配置步骤) [/ p4 \$ X& ?' j' Q/ `" v/ \) o
1)使能 DMA 时钟

) `+ U7 g, E6 V& U
. f% W  y% t& |7 {% q8 U
  1. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
复制代码
3 N5 A3 G* Q; S* C( z" J" e+ o
5 Z; d2 K/ u1 c
2)初始化 DMA 通道 4 参数
( _6 I# z1 D/ D4 [& }5 {

+ G) g) [; [. H
  1. void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
复制代码
  1. DMA_InitTypeDef DMA_InitStructure;6 X( N$ ]$ o6 k  o
  2. DMA_InitStructure.DMA_PeripheralBaseAddr = &USART1->DR; //DMA 外设 ADC 基地址: Z0 M! @$ e" z2 k) ~$ n% E
  3. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
    3 m; g( V2 w( r2 {2 S) Z9 t, S% x! v
  4. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //从内存读取发送到外设
    4 N4 n: V. ?1 a' Z: n' O
  5. DMA_InitStructure.DMA_BufferSize = 64; //DMA 通道的 DMA 缓存的大小
    ( v3 ^3 A( a7 J- e- L/ H" S
  6. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变% Z7 c5 V" V5 z/ V& ^
  7. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址递增' Y+ x* n# v2 a# l; B' F2 Z9 E7 A
  8. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //8 位# m: t* I6 n7 J% M- Z
  9. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8 位
    4 q8 b/ h. p1 @; c# q$ a/ h
  10. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
    ' u' j: s+ O* x1 Q/ I  z: k
  11. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA 通道 x 拥有中优先级
    . {4 Y7 U* K  K
  12. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输
    7 m  W8 s/ O4 u! w$ G8 \0 x
  13. DMA_Init(DMA_CHx, &DMA_InitStructure); //根据指定的参数初始化
复制代码
3 F1 f# [4 t! n' z
3)使能串口 DMA 发送
  1. USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
复制代码

/ f4 i, n# R8 c4)使能 DMA1 通道 4,启动传输# X8 y- s% G2 h) C: ]$ q6 {

5 q5 v8 B- S& }% U$ l. L
  1. DMA_Cmd(DMA_CHx, ENABLE);
复制代码

9 k2 w) o* K. M: b) g. v9 E5)查询 DMA 传输状态
% D2 h+ S$ Q) _5 k3 N. {2 V5 J2 t: A; d8 ~% B" f! S/ T% u
在 DMA 传输过程中,我们要查询 DMA 传输通道的状态:9 m0 C/ c/ J9 B; B" {& w+ _7 [

8 z- K- D& w& D. TFlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)# P" }8 _0 D. j
1 P+ i; f. [1 q4 K, x  X
比如我们要查询 DMA 通道 4 传输是否完成:% Q% O' R$ m  C& Q

- Y" N/ e' ?! hDMA_GetFlagStatus(DMA2_FLAG_TC4);
4 X5 H! H- ]. {/ R- I9 Z& `5 l' r7 O' u3 E( }
获取当前剩余数据量大小的函数:
  1. uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
复制代码
4 G% R& x. A# ?- c
比如我们要获取 DMA 通道 4 还有多少个数据没有传输:
  1. DMA_GetCurrDataCounter(DMA1_Channel4);
复制代码

2 z6 t3 p5 b4 }4 R二、代码实例
. m+ O/ N& q/ F6 U我们需要创建dma.c 文件和其头文件 dma.h,- g7 w- {3 b: Y- P/ D% R0 L+ b
同时我们要引入 DMA 相关的库函数文件 stm32f10x_dma.c 和 stm32f10x_dma.h。
5 l! o$ U- P! v' M0 R
3 c# P, o. \  G6 b2 d' R9 j! p——dma.c 文件
9 Y+ i- T: N- B5 J2 y2 P) Z
- |+ Z) Q# t+ [# c4 E) ^
  1. #include "dma.h", W. r; I5 M7 c2 M
  2. DMA_InitTypeDef DMA_InitStructure;& l% _- A5 w& E) }; d% u+ @
  3. u16 DMA1_MEM_LEN;//保存 DMA 每次数据传送的长度 - Y! W6 g/ P# S3 e0 I5 P* B, @$ ]
  4. //DMA1 的各通道配置3 D5 S9 _9 i) }( N9 s3 _" P
  5. //这里的传输形式是固定的,这点要根据不同的情况来修改* n! l) P% I0 \% `; _% X
  6. //从存储器->外设模式/8 位数据宽度/存储器增量模式) Q7 Y+ w$ U' h' m/ B
  7. //DMA_CHx:DMA 通道 CHx8 e, X6 ~& x# R$ a6 q% S
  8. //cpar:外设地址/ i7 g- U- n7 C0 H  p
  9. //cmar:存储器地址  Z/ m' o2 n& F2 C! x' U0 n
  10. //cndtr:数据传输量
    1 ]( j: |% R: A, Y) `- j
  11. void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
    ( d" H* b5 ]9 b) f) Y
  12. {9 F: T( k, U9 E* ?* S& q: |. A
  13. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟0 |( ]* H5 h" t2 @3 [2 @4 N
  14. DMA_DeInit(DMA_CHx); //将 DMA 的通道 1 寄存器重设为缺省值. ]; y8 Y) l9 d& ?
  15. DMA1_MEM_LEN=cndtr;' G- }) N& Q1 J: o- Y% u
  16. DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA 外设 ADC 基地址: V, P; c! Y7 q+ n2 e
  17. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
    6 R/ |* k2 D5 Q+ y7 B% o
  18. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向内存到外设
    ! g; Q8 [, _% T* t+ C. v
  19. DMA_InitStructure.DMA_BufferSize = cndtr; //DMA 通道的 DMA 缓存的大小" J5 }7 q7 {. K8 R3 W! p
  20. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不变
    0 Y9 N7 Z: l; n8 p( ?' ^
  21. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增
    ; B2 v$ D2 _3 S$ \: e5 ~
  22. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    * W" @( Y+ v5 h2 r7 f
  23. //数据宽度为 8 位' r, D1 B- D7 t  j6 w* l
  24. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度
    0 M: a# e/ D3 w4 @+ ~8 n7 j: R
  25. //为 8 位
    , s. ^2 E! {- V8 Z, l
  26. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
    + I8 v) Y$ E1 c  [9 E- O4 {
  27. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DM 通道拥有中优先级
    : y7 f" z* V/ r
  28. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输4 {! W4 [# E. ^, v* d( j
  29. DMA_Init(DMA_CHx, &DMA_InitStructure); //初始化 DMA 的通道- M; O# A. \: ~
  30. }
    / Q4 N/ a$ V5 @9 x- O
  31. //开启一次 DMA 传输0 \2 x$ ^8 b" C. l/ X2 H
  32. void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
    , \# ~2 J( |! f* y, D, |' |
  33. { 3 q  w6 H$ S+ k7 ]: r& E
  34. DMA_Cmd(DMA_CHx, DISABLE ); //关闭 USART1 TX DMA1 所指示的通道 & R) s; J# P0 g
  35. DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//设置 DMA 缓存的大小
    ; b, c: v5 }% M1 U) {- H" A2 q
  36. DMA_Cmd(DMA_CHx, ENABLE); //使能 USART1 TX DMA1 所指示的通道$ _% J/ ~3 W3 k, b  ]% S1 n  H
  37. }+ F# d1 F2 Y' L7 w6 A
复制代码

: t1 h( T0 e# }2 u
收藏 评论0 发布时间:2022-5-8 19:00

举报

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