当前位置: 首页 > article >正文

GD - GD32350R_EVAL - PWM实验和验证1

文章目录

    • 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时钟最终的执行频率。

END


http://www.kler.cn/a/284883.html

相关文章:

  • 华为大咖说 | 浅谈智能运维技术
  • 35.3K+ Star!PhotoPrism:一款基于AI的开源照片管理工具
  • 16008.行为树(五)-自定义数据指针在黑板中的传递
  • OLED 显示画面的变换操作——上下、左右翻转
  • Android CarrierConfig 参数项和正则匹配逻辑
  • 协程3 --- golang的协程调度
  • React原理之Diff算法
  • ESP32-S3 IDF框架 控制 WS2812 灯条:实现多种灯效
  • 【通过h5作为中转页跳转到微信小程序】
  • 【Linux】06.Linux 下的编译器——gcc/g++
  • 【C++ 第十八章】C++11 新增语法(2)
  • vue3+el-tale封装(编辑、删除、查看详情按钮一起封装)
  • 【HarmonyOS 4.0】@ohos.router 页面路由
  • ★ 算法OJ题 ★ 力扣11 - 盛水最多的容器
  • sqlite3 数据插入效率
  • YOLOv8改进 | 模块缝合 | C2f融合卷积重参数化OREPA【CVPR2022】
  • Having trouble using OpenAI API
  • 回归预测|基于鹅GOOSE优化LightGBM的数据回归预测Matlab程序 多特征输入单输出 2024年优化算法
  • vue3本地运行错误集
  • 5.3 MySql实战
  • Xilinx FPGA在线升级——升级思路
  • 鸿蒙开发5.0【基于Swiper的页面布局】
  • LeetCode 热题100-9 找到字符串中所有字母异位词
  • vscode 未定义标识符 “uint16_t“C/C++(20) 但是可以顺利编译
  • Java算法—插入排序(Insertion Sort)
  • 一种导出PPT到MP4的方法