文章目录
- GD - GD32350R_EVAL - PWM实验和验证1
- 概述
- 笔记
- 实验设计
- 实验环境
- GD32350R_EVAL 的硬件连接
- 修改程序配置 - 只产生PWM波,不要CMP清除波形
- TIMER0时钟设置
- TIMER0的PWM设置参数设置
- main()中PWM波形的开启代码
- 示波器测量结果
- 如果要产生4KHZ的PWM需要设置怎样的参数?
- 尝试1 - 算一下时钟设置参数
- 尝试1 - 产生代码,编译,验证
- 错误分析原因
- 可能1
- 可能2
- 尝试2 - 算一下PWM设置参数
- 尝试2 - 产生代码,编译,验证
- 总结
- 疑问
- @todo
- 是否 “Clock division” 真的没用?
- END
GD - GD32350R_EVAL - PWM实验和验证1
概述
看到 EmbeddedBuilder_v1.4.1.23782\examples\GD32F3x0\examples 有PWM的例子工程,想迁移到工程里面用。
想通过实验,来确定设置确定频率和占空比的方波,开始PWM, 调整占空比,停止PWM 这些知识点 应该怎么编程。
笔记
实验设计
在例子工程指定的PWM输出管脚和GND之间,连接示波器探头。
设置好PWM后,用按钮来关联PWM开始/占空比的调整/PWM结束,用示波器实时的测量PWM的频率和占空比。
实验环境
GD32350R_EVAL
DS1202ZE
EmbeddedBuilder
例子工程 EmbeddedBuilder_v1.4.1.23782\examples\GD32F3x0\examples\CMP\CMP_pwm_signal_control
GD32350R_EVAL 的硬件连接
CMP_pwm_signal_control 例子工程中使用PA8作为PWM输出。
查了一下原理图,PA8只引出到了输出端子上,不和其他元件连接,正好可以连接示波器探头。
现在选一下GND和PA8的连接端子,就可以开始连接示波器探头。
GD32F3x0_Demo_Suites_V2.3.0\GD32350R_EVAL_Demo_Suites\Docs\Schematic 有原理图和板子丝印。
GND的端子用探头GND鳄鱼夹子夹住,离其他端子太近了,容易短路。
暂时用纸隔开。
问了厂家,是否探头GND端可以换成钩子配件。厂家说没有。
去x宝上找了一圈,厂家没骗人,其他家也没有卖的。
如果怕短路,又不想用纸隔开。只能先用杜邦线连上端子,再用探头GND端夹住。
最终,我用1 x 2.54 * 3P的插孔排,套在插针排上,这样用探头的GND夹子夹住就容易多了。
修改程序配置 - 只产生PWM波,不要CMP清除波形
官方例程自动停止PWM, 用的是光敏电阻,自己的实验用不到,去掉。
TIMER0时钟设置
时钟树配置后,给TIMER0的入口时钟CK_TIMER0 = 108MHZ
TIMER0的PWM设置参数设置
Prescaler Value(预分频值) = 107, 因为CK_TIMER0 = 108MHZ, 这里的值是108 MHZ / (107 + 1) = 1MHZ
也就是TIMER0分频后的实际时钟 CK_TIMER0_After_Prescaler = 1MHZ
Clock division = 1, 代表 CK_TIMER0_After_Prescaler 再分频 = CK_TIMER0_After_Prescaler_After_div = CK_TIMER0_After_Prescaler / Clock division = 1MHZ / 1 = 1MHZ
CK_TIMER0_After_Prescaler_After_div 就是最终被执行的TIMER0频率 = 1MHZ
Cunter auto reload value = 9999 代表时钟周期 = (9999 + 1) * (1 / 1MHZ)秒 = 10000 * 1 / 1000000 = 0.01秒 = 10ms
PWM的频率 = 1 / Cunter auto reload value = 1 / 0.01秒 = 100HZ
Compare value = 4999,意味着在一个PWM波周期内激活电平的占用时间 为 (4999 + 1)/ (Cunter auto reload value + 1) = 5000 / 10000 = 50%
对于一个PWM波,频率,占空比都有了,就确定了一个PWM波。
main()中PWM波形的开启代码
产生代码。
在主程序中,注释掉CMP开始的实现。
示波器测量结果
测量结果如下:
- 垂直幅度 = 3.3V
- 水平周期 = 10ms
- 水平频率 = 100HZ
- 占空比 = 50.20%
和上面代码设置的PWM周期相比,基本一致。
如果要产生4KHZ的PWM需要设置怎样的参数?
假设现在要驱动4KHZ的无源蜂鸣器,参考官方给的例子。尝试设置一下参数,再用示波器量一下,看看对不对?
就在官方的这个工程上将参数改一下,能产生4KHZ PWM波就行,然后在自己的工程上再重新配置。
尝试1 - 算一下时钟设置参数
为了验证"clock divsion", 将其改为2
手工先算一下,如下
Prescaler value = 107 = 108MHZ / (107 + 1) = 1MHZ
(时钟分频 clock division = 2, 试一下)div = 2 => TIMER0实际执行时钟 = 1MHZ / 2 = 500KHZ = 0.5MHZ
TIMER0实际执行时钟的周期 = 1 / (0.5MHZ * 1000000) = (1 / 500,000)s = 0.000002s = 2us 一个TIMER0时钟周期 = 2us
4KHZ的周期 = (1 / 4000)s = 0.00025s = 250 us
那么4KHZ的PWM波的时钟(TIMER0实际执行时钟的周期)个数 = 250us / 2us = 125个 => 自动重装值 = (125 - 1)= 124
驱动无源蜂鸣器的PWM波占空比要求是50%, 那么PWM波的比较值 = 125个 * 50% = 62.5个 = 63个。=> CMP比较值 = (63 - 1) = 62
按照手算的,来填写TIMER0的图形化配置参数
尝试1 - 产生代码,编译,验证
实际测量的频率和设想的大了一倍,实际周期比预想的小了一倍,占空比还可以。
看看参数哪里算错了。
错误分析原因
可能1
感觉是“Clock division”理解的不对。
从实际测量值来看,“Clock division”是对自动重装值的"细分", 有点像电机驱动芯片的细分功能一样。
虽然从TIMER0时钟看,只要数125个时钟,就能产生500KHZ的PWM波。
但是为了使自动重装值能数的数更多,可以"细分"
如果计算出的重装值为(125 - 1), “细分” = 2的话,那么自动重装值就应该在计算值的基础上x“细分值” = (125 * 2 - 1) = 250 - 1 = 249
同理,CMP值 = CMP值 x “细分值” = (63 * 2 - 1) = 126 - 1 = 125
可能2
可能是GD家的工具有bug, “Clock division”的值根本就没用到…
因为通过观察,不理会“Clock division”, 算出的PWM值就扩大一倍的,就是是对的。
尝试2 - 算一下PWM设置参数
在尝试一的基础上 + 错误分析原因, 手工算一下PWM参数
手工先算一下,如下
Prescaler value = 107 = 108MHZ / (107 + 1) = 1MHZ
不理会“Clock division” !!!
TIMER0实际执行时钟的周期 = (1 / 1MHZ)s = (1 / 1000,000)s = 0.000001s = 1us 一个TIMER0时钟周期 = 1us
4KHZ的周期 = (1 / 4000)s = 0.00025s = 250 us
那么4KHZ的PWM波的时钟(TIMER0实际执行时钟的周期)个数 = 250us / 1us = 250个计数 => 自动重装值 = (250 - 1)= 249
驱动无源蜂鸣器的PWM波占空比要求是50%, 那么PWM波的比较值 = 250个 * 50% = 125个计数 => CMP比较值 = (125 - 1) = 124
按照手算的,来填写TIMER0的图形化配置参数
尝试2 - 产生代码,编译,验证
这回对了。
频率,占空比都ok。
总结
和时序相关的操作,如果不用示波器实际看看,心里真没底,不知道弄得对不对。
其实就是官方根据特定开发板给出的例程,如果不拿对应的官方开发板跑起来 + 用示波器实际确认一下波形,也不能肯定官方例程就是对的(只能选择信任官方的例程)。
疑问
在Pinout配置TIMER0时,时钟源是禁止的。那禁止了时钟源,CK_TIMER0的时钟源是谁?
感觉GD家的软件现在还有不少疑似bug, 不过当前版本不影响用。
使用HAL库配置寄存器时,可以比使用固件库配置的更细致。
@todo
使用PWM时,可以不停止PWM波,直接可以改占空比。
官方这个例子是用软件来启动PWM, 用CMP从内部连接到TIMER0的PWM通道停止寄存器。
实际用PWM时,需要自己从逻辑上启停PWM/调整PWM占空比, 应该是在另外一个定时器中操作PWM。
将EmbeddedBuilder官方HAL库例子中,所有关于PWM的例子都看完,就知道PWM操作细节的玩法了。
是否 “Clock division” 真的没用?
将实验工程拷贝了一份,将 “Clock division” 改为4,重新编译,单步状态跑起来,用示波器看,还是4KHZ/50%占空比。
比较代码,确实有区别,可以看到“Clock division”为4,原始工程 “Clock division”为2,但是效果一样。。。
这如果是没有图形化配置,谁能知道寄存器配置还能有这区别?
从实验结果上看,“Clock division”是没用的,1/2/4效果都一样。不影响TIMERX时钟最终的执行频率。
只有CK_TIMEX和Prescaler Value(预分频值) 会影响TIMERX时钟最终的执行频率。