STMCU小助手
发布时间:2022-2-24 19:50
|
一. 前言 目标要求:系统时钟 8Mhz,6 个 PWM 脉冲。 二.实现方式 实现上述目标的方法有很多种,比如两个定时器级连,定时器定时中断翻转 IO 口,等等,这里使用DMA 的方式去实现。 2.1 参考基于 F1 标准外设库& [# H/ h7 U5 F6 v 软件环境:STM32F10x_StdPeriph_Lib_V3.5.0 版本的标准外设库函数中的- i* r# Y o$ A8 _3 h Project->STM32F10x_StdPeriph_Examples->TIM->DMABurst 的示例代码;. Q, y7 K! V2 Q5 S) c; x 硬件环境:STM32F10V-128K-EVAL,MCU 型号为 STM32F103VBT6;8 I- V. X+ G; s! @3 {# f Z 该示例的代码稍微解释下,就会明白 DMA 的寄存器的作用。部分代码如下: TIM1_DMAR_ADDRESS 地址的定义:8 B# |) D% j; [8 g$ Y$ O # k) w6 ^! ~ ^$ o3 p
/ j9 Y3 } @* q, `( d( N DMA 的初始化:" k. R3 d$ e4 {8 R. F$ [2 A' S - e' O7 r- T& G: _* P
4 v5 J ?; M3 K0 y3 V& D 逐个寄存器简要说明: DMA_PeripheralBaseAddr9 p: j: C% M3 q! k6 N 0 |- D& n2 U6 ^5 a: V
8 d2 h2 r4 |; e/ `: v+ ? 该语句是对寄存器 DMA_CPARx 赋值,存入要操作的是哪种外设,该外设的数据寄存器的基地址,它作为数据传输的源或目标,在此例中,是作为数据传输的目标的基地址。% `% g) o- e/ O4 O 通道 5,它的 CPAR 值是 0x40012C4C,表明通道 5 的寄存器偏移地址 DMA_CPAR5 是 0x10+0d20 *4 = 0x60,所以 DMA_CPAR5 的真实地址是 0x40020000 +0x60 = 0x40020060,该地址里面存储的是0x40012C4C,是 TIM1_DMAR 的地址。即可以理解为操作的是 TIM1 的外设。 / q' b3 C1 x% o" R3 c
& V7 J$ K# |! z/ a DMA_MemoryBaseAddr 0 S% g- Y1 m& A0 w( S
该语句是对寄存器 DMA_CMARx 赋值,设置的是相应通道的存储器的基地址,作为数据传输的源或目标,在此例中,是作为数据传输的源的基地址。(uint32_t)SRC_Buffer;2 z! ]4 w$ C. z5 C8 w+ F DMA_DIR 数据传输方向,从外设读或者从存储器读,该示例中是从存储器读;外设作为目标地址。4 p7 `6 p: `4 {0 B" Y3 h DMA_BufferSize
, R# [+ L5 N. |+ Z! g; h9 Y. L2 K 定义数据传输的数量,指示剩余的待传输字节数目,寄存器内容在每次 DMA 传输后递减。- M- A9 V* d1 g. A5 u( V. W DMA_PeripheralInc,DMA_MemoryInc% Y! C, Q6 w2 M$ V" D, {/ N0 U 该示例中,不执行外设地址增量操作,执行存储器地址增量操作。0 c$ J: a0 H- @ u* D+ @ k DMA_PeripheralDataSize,DMA_MemoryDataSize 定义外设数据宽度,存储器数据宽度。 DMA_Mode/ v$ L" g* q2 z( v 分为非循环模式和循环模式, 在非循环模式中,在数据传输结束后,DMA_CNDTRx 寄存器的内容会变为 0,此时无论通道是否开启,都不会发生任何数据传输。2 _0 K# T, D7 j _" I. U% K 在循环模式中,在数据传输结束后,DMA_CNDTRx 寄存器的内容会自动加载变为之前配置的数值,重新开始数据传输。 DMA_Priority,DMA_M2M: o$ @3 \ g! \) i 本例中,通道优先级设为高,启动非存储器到存储器模式。 " S8 W; H4 P u' L" O3 B 2.2 基于 Cube 库函数的可控 PWM 脉冲 直接打开\STM32Cube_FW_L0_V1.1.0\Projects\STM32L053R8-! J0 J/ W8 _/ q* ~- Z' C1 T Nucleo\Examples\TIM\TIM_DMABurst 中的示例项目,修改配置符合自己当初的设想:选取 Timer2 的channel1(PA5),系统时钟通过 HSI 的分频倍频,通过 PLL 实现系统时钟为 8MHz。GPIO 口的设置:Max output speed 的速度为 High。定时器 PWM 模式的设置:向上计数,计数时钟为 8MHz,占空比50%。! L+ m* s) F/ S! W: ^6 d- k GPIO 口的设定:
这里要记住一点,如果参数设置中,周期和占空比寄存器设定的计数值已经达到最小,当再使用 DMA产生中断时,可能会来不及响应。允许的话,可以利用分频 Prescaler 先对定时计数器的时钟分频。% s) z9 Z) L% Y 定时器的配置:" e8 h( `" x1 G1 ?1 U : ^' o3 [. b7 D0 }+ c; V/ E
; ^5 W3 \# j1 @2 b9 x4 t% t* _ DMA 的配置: ) A& j/ c8 I8 E( C
其中,对于 DMA 配置中,BUFFER_SIZE 是代表要向目标地址发送的数据的个数。) M6 R+ p1 H5 _5 @: E# O+ v - K& _: B) |3 i% y& _7 K
/ N+ f# X8 w4 ]2 T2 z 上述需要在程序中添加设置 TIM2_DMAR_Address 的偏移索引地址,在定时器的章节可以看到。不需要打开 DMA 传输完成的中断。 下面的是启动 DMA 传输,利用定时器的更新事件(TIM_UP 指定时器的周期,TIM_CH1 指占空比)去触发 DMA 传输数据。$ H& q3 ^: n% u6 A1 A) E( Q: X 9 P+ ]" y! l5 H# u" `8 `
这儿传输的方向是将 aSRC_Buffer 数组中数值,逐个向 TIM_DAMBase_CR1 寄存器中写入,控制定时器的计数使能位,达到控制 PWM 个数的目的。7 j5 l1 K6 b, B" C/ @: W; K* z % F$ G O" U9 W# A
BUFFER_SIZE 的数值为 6,目的是产生 6 个脉冲。7 s1 U( U: {0 A) P. Q1 _ 运行程序:2 `6 @1 y3 `# V0 y0 n* X
e; I5 t3 a; Q" V; @% k! [ 波形截取成功。 W8 ^. o" S' _- y; f |
微信公众号
手机版