#训练营#基于GD32的简易数字示波器项目 - 嘉立创EDA开源硬件平台

编辑器版本 ×
标准版 Standard

1、简单易用,可快速上手

2、流畅支持300个器件或1000个焊盘以下的设计规模

3、支持简单的电路仿真

4、面向学生、老师、创客

专业版 professional

1、全新的交互和界面

2、流畅支持超过3w器件或10w焊盘的设计规模,支持面板和外壳设计

3、更严谨的设计约束,更规范的流程

4、面向企业、更专业的用户

专业版 #训练营#基于GD32的简易数字示波器项目

简介:基于GD32的简易数字示波器项目

开源协议: Public Domain

(未经作者授权,禁止转载)

已参加:简易数字示波器训练营

创建时间: 2024-03-05 08:40:59
更新时间: 2024-04-11 21:41:13
描述

基于GD32的简易数字示波器项目。参加的是新手区,硬件部分不做过多说明了。

具体说明请看附件中Doc文件夹下readme文件。

本人习惯在keil里使用UTF-8编码格式,为兼容各种需求,因此基本不在工程中写中文注释。英文注释类似工地英语,本人认为有必要单独写一个说明文档来解释工程中的一些事项。
本工程基于嘉立创陈工的开源代码基础上进行了一定修改,开源网址:https://gitee.com/chen11232/GD32E230-Oscilloscope

首先从main.c看起,时钟配置,LED相关引脚初始化,KEY相关引脚初始化等。

初始化函数之后,增加一个嘉立创图片作为待机界面,拨动KEY1跳过该界面,进入正常程序。带Simplified后缀文件删除了包含该图片的头文件,下载程序时间可能会缩短。

待机界面程序实现如下:


然后是死循环里的两个函数,第一个函数实现按键控制PWM波,第二个函数实现有信号输入时的电压,频率显示。

LED相关引脚初始化和KEY相关引脚初始化比较基础,不做过多介绍。
值得关注的是,Key.c中的Key_GetState()函数和Key_GetNum()函数。
Key_GetState()函数为只要拨动一个按键,就会返回该按键对应的按键值。比如拨动检测到按键1被按下,即GPIO PB13引脚为低电平,将该按键状态作为返回值返回。
在Key_GetNum()函数中,读取上一个按键状态和当前按键状态。如果按键一直处于按下状态,则当前按键状态永远不会为零,函数返回keynum的上一个值。
只有当按键处于松开状态,函数开始判断,根据按键上一个状态判断哪个键刚才处于按下状态,比如当前按键状态是0,上一个按键状态为1,可以认为KEY1被按下,返回KEY1键值。


之所以处理得这么麻烦,是因为想要使用中断函数来处理按键,而不是在main函数while循环中,用一直扫描键值的方式来判断哪个按键被按下。
扫描方式严重占用CPU资源,还只是完成十分简单的操作。因此,使用中断函数处理。而按键有一个著名的问题就是需要消除抖动,一般都是在程序中通过延时10ms左右来消除抖动。
而中断函数是需要快进快出的函数,在中断函数中添加延时函数有一定的风险,借鉴B站up主江协科技的方法,在定时器中断函数中调用Key_GetNum()函数,中断时间设置为10ms。
Key_GetNum()函数只包含简单且不耗时的操作,每隔10ms调用一下Key_GetNum()函数,通过Key_GetNum()函数的逻辑判断实现键值判断,读取上一个按键状态和当前按键状态来读取键值,实现方法如前述。
TIM.c里有相关定时器15的配置,将其配置为10ms中断一次,定时器中断函数void TIMER15_IRQHandler(void)位于main.c靠后位置。

串口初始化和外部中断初始化也比较基础,不做过多介绍。
值得关注的是,在main.c中的外部中断4-15函数(void EXTI4_15_IRQHandler(void)),该函数实现的功能是:
根据当前按键键值,以及旋转编码器的旋转状态,实现GD32芯片PWM波输出频率、输出占空比以及ADC采样时间的调整。函数中,cnt1和cnt2变量存储旋转编码器顺(逆)时针的旋转量,主要作用的是防止误判。


该值本人设置较小,可以通过修改宏定义KeyThresholdValue更改编码器旋转的格数减小误判率,该部分仅是象征性进行判断,
参考了B站up主立创EDA,示波器训练营,软件部分,外部中断实验末尾陈工对于旋转编码器误判的处理思路。
该函数实现功能详细如下:
按下KEY1,顺时针转动旋转编码器打开GD32芯片PWM输出,逆时针关闭。
按下KEY2,顺时针转动旋转编码器增大PWM输出占空比,逆时针减小。具体变化数值是本人随意设置的,可根据需求自行更改,改变变量Pulse的变化步长即可,变化步长可以通过修改宏定义deltaDutyRatio,


触发一次编码器旋转,占空比变化该值的大小,比如本人将初始值设置为0.042,即触发一次编码器旋转,占空比改变4.2%,如果占空比原来为50%,顺时针旋转后占空比为54.2%;逆时针旋转后占空比为45.8%。
占空比增加了一些限制,小于0.6%会强制将占空比设为75%,大于100%会强制将占空比设为25%。可以设置宏定义RatioThresholdValue改变强制设置占空比。
占空比功能实现存在一定bug,可能是因为数据类型精度问题,改变幅度可能只能保证小数点后两位。(毁灭吧,不想改了)
按下KEY3,顺时针转动旋转编码器增大PWM输出频率,逆时针减小。具体变化数值是本人随意设置的,可根据需求自行更改,改变变量AutoloadValue的变化步长即可,变化步长可以通过修改宏定义deltaFreRatio,触发一次编码器旋转,频率变化与该值的关系为,顺时针旋转旋转编码器,频率变为原来的(1+deltaFreRatio)倍,逆时针旋转旋转编码器,频率变为原来的(1-deltaFreRatio)。


由一下例子具体说明:本人将初始值设置为0.8,如果输出频率原来为1KHz,顺时针旋转后,频率变为1.8KHz;逆时针旋转后,频率变为200Hz。
按下旋转编码器,顺时针转动旋转编码器增大采样时间,逆时针减小。采样时间只有几个档,本人仅设置了239.5、71.5、55.5和41.5,可根据需求自行增加switch的case数量。

可选值可通过在工程中按下ctrl+f,Find what输入ADC_SAMPLETIME_239POINT5,Look in下拉Current Project,点击窗口下方Find Next,在gd32e23x_adc.c文件中,可以找到可选值。

ADC、FREQ相关函数和屏幕初始化本人没做改动,不做过多介绍,详细可以参考B站up主立创EDA,示波器训练营,软件部分相关视频。

PWM初始化比较基础,不做过多介绍。
值得注意的是,本人定义了PWM_PulseAdjustment()和PWM_FrequencyAdjustment()函数,这两个函数用来计算输出PWM波的占空比和频率。
在Key_ControlPWM()函数中,通过判断Timer14flag是否为0使能或失能定时器14,达到控制PWM输出开启、关闭的目的。该标志位由外部中断4-15函数控制。ONflag,OFFflag作用为不频繁刷新显示状态,仅第一次Timer14flag变化后,刷新一次显示屏,之后不刷新显示屏显示,保留上一个显示状态。
通过定义Pulse_temp、AutoloadValue_temp和SampleTime_temp分别存储上一个状态的Pulse、AutoloadValue和SampleTime,只有Pulse、AutoloadValue和SampleTime变化才刷新屏幕显示。
值得注意的是,设置了输出频率的最大值和最小值,最小值约为16Hz,最大值约为40KHz。达到最小值后,在KEY3键值状态下再逆时针旋转旋转编码器,屏幕会出现一次提示,并增加了3s延时,此时输入频率和幅值会等到提示消失后才会刷新,提示只会出现一次,而且在屏幕提示状态下,旋转旋转编码器无效,需要等3s延时过后才可以正常调整输出频率。

乱码是因为刚开始变成使用GB32的编码,后来改回UTF-8导致,所以大家编程一定要养成好习惯,统一编码格式啊。
采样时间同理,改变采样时间会出现提示,只有提示结束才能继续改变采样时间。
Key_ControlPWM()函数增加了采样时间变化时,在屏幕上显示的功能,最后两行为刷新屏幕采样时间屏幕显示提示而设置的空格。

本工程未使用陈工的结构体变量Oscilloscope,因此大部分参数直接在main.c里使用全局变量来进行参数传递,习惯不好。

注意事项,本人编程许多地方未考虑,肯定存在巨量bug,如果有人看到这个贴子,并烧录了本人编写的程序,遇到一些bug可以留言,本人在有精力的情况下会着手尝试修改,并上传修改程序。这也是上传附件程序带有V1,V2的意义。谢谢大家!

遇到的主要问题是刚开始使用了仅有10x衰减的示波器探头作为输入探针,频率和电压怎么都测不对。使用可选择1x和10x探头后恢复正常使用。

设计图
原理图
1 /
PCB
1 /
未生成预览图,请在编辑器重新保存一次
工程视频/附件
工程成员
侵权投诉
相关工程
换一批
加载中...
添加到专辑 ×

加载中...

温馨提示 ×

是否需要添加此工程到专辑?

温馨提示
动态内容涉嫌违规
内容:
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 技术支持

support
  • 开源平台公众号

MP