
基于GD32E230C8T6的数字示波器
简介
数字示波器是一种用于显示电信号波形的仪器,主要由模拟前端处理电路、单片机电路、电源电路、控制电路、触发电路、校准电路等电路组成。由于该项目为示波器入门项目,在电路设计上选择了一些核心电路。
简介:数字示波器是一种用于显示电信号波形的仪器,主要由模拟前端处理电路、单片机电路、电源电路、控制电路、触发电路、校准电路等电路组成。由于该项目为示波器入门项目,在电路设计上选择了一些核心电路。开源协议
:GPL 3.0
(未经作者授权,禁止转载)描述
基于GD32E230C8T6的数字示波器
实物演示
B站视频(视频太大已经分开压缩,如需要下载解压请同时解压视频资源1,2,3,4,5)
【基于GD32E230C8T6的数字示波器】 https://www.bilibili.com/video/BV1qJ4m177jP/?share_source=copy_web&vd_source=b56038c6fc5a32b35a0c1a44d8c245fc
电路原理
模拟前端处理电路
在整个示波器电路设计过程中,模拟前端处理电路是最为重要的,其中大量应用了模拟电路的知识,其中包括输入交直流耦合切换电路、输入信号衰减电路、以及信号调理电路所组成。
交直流耦合电路
信号类型可以分为直流信号和交流信号,现实中的信号往往都是都不是理想波形。比如直流电源信号应该是一条水平的直流信号,但都会存在电源纹波(交流信号);在采集交流信号时也可能混入直流信号对波形的峰峰值造成影响。
为了保障对输入交流信号的准确测量,利用电容通交隔直的特性,将电容串联到电路中就可以过滤到信号中的直流分量,这就是交流AC耦合的概念。而直流DC耦合就是不对输入信号做任何处理
电路中通过一个拨动开关SW2对输入交直流耦合信号进行切换,当开关2与1接到一起时为直流耦合,当开关2接到3时为交流耦合。
这里的电容如何选择大小呢?
要解决这个问题,那就需要了解电容的频率特性,理想状态下隔直电容的选择应该越大越好,但是由于不同容值的自谐振频率不同,低于自谐振频率时电容呈现容性状态,高于该频率时存在感性状态。电容越大,其自谐振频率越低,简单来说就是大电容通低频,小电容通高频。
如下图可知当瓷片电容为0,1uF(100nF)时,其自谐振频率为4Mhz,一般要求电容的截止频率fc=1/5*fo,其中fo为电路中工作频率。由此可知在该项目中100nF是足够应用的,但如果输入信号频率更高,就应该选择更小的电容。
信号经过交直流耦合选择电路后由开关SW3选择两个通道,开关2和3接到一起时,输入信号直接流入后级的电压跟随器电路;当开关2和1接到一起时,输入信号经过R7、R11、R14三个电阻构成的电阻分压网络后将信号衰减到了1/50倍,即
由此可知,当输入信号幅值较小时,可优先选择低压档位,如果测量时不确定输入信号幅值可先用高压档位测量后如满足低压范围内,可用低压档位测量以得到更为精准的测量结果,同时保护电路。
输入信号衰减电路
该项目中使用的探头为BNc转鳄鱼夹探头,非专业示波器探头,仅对电路进行简单分析,此处不进行展开说明更多关于探头选择与阻抗说明。如使用专业示波器的无源探头进行测量,由于探头上有一个×1和×10的档亻立选择,当档位为×10时可以通过调整探头上的衤卜偿电容或者是电路中的c10进行匹配已得到准确的测量效果,其中C10一般为可调电容,实际大小与各板间电容特性有关。
信号调理电路
在信号调理电路中包含了一个电压跟随器以及由运放构成的信号放大电路,在分析该这部分电路时需要掌握运放的虚断与虚短原理。
虚断:
理想运放的输入阻抗是无穷大,然而真实的运放输入阻抗却是有限的。如果给运放的输入端加一个电压,然后测量该输入端的电流会发现电流读数接近为0,感觉运放内部断开,没有电流流入一样,但实际又是连接的,这种现象称为虚断。
也可以用欧姆定律U=I*R来理解,当电压一定时,电流与电阻成反比,电阻无限大那电流也就无限小接近为0。
虚短:
在运放处于深度负反馈时会出现虚短现象,使两个输入端的电位相等,就象两个输入端短接到了一起,可以近似为v+=v-。
在负反馈中,运放的输出信号的一部分被取出并反馈到输入端。这种反馈作用使得运放的两个输入端(正输入和负输入)的电压差趋近于零,、两个输入端的电压几乎相等。因为尽管运放的两个输入端在电气上并没有被直接短路、,但由于负反馈的作用,两个输入端的电压却几乎相等,就象它们被短路了一样,故称为虚短。
电压跟随器
电压跟随器的特点是输出的电压幅度和极性都与输入电压相同,且具有输入阻抗高,输出阻抗低的特点,常用于做缓冲级和隔离级。
由于运算放大器的虚短特性,V+=v-,由于Vin=V+,Vout=V-,所以Vin=Vout,即TP6测试点电压与TP7电压一致。
反相比例放大器
输入信号从运算放大器的反相输入端输入,具有输出极性相反且放大输入信号的功能。
当运放正向输入端接地,IJ+=OO此时构成反相比例放大电路,由运放的虚断特性可知反向输入引脚流入运放的电流为0,可以R13和R15可以看做串联,所以流经电流相同。由虚短特性可知v+=v-=0,i+=i-=0,由此可得.
推出反相比例放大器计算公式为
将Vi=1V,R13=20K,R15=10K带入得Vo=-0.5V
串联电路中电流相等,输出电压为-0.5伏。
同相比例放大器
输入信号从运算放大器的同相输入端输入,具有输出极性相同且放大输入信号的功能。
当运放反向输入端接地,U-=0。此时构成正相比例放大电路。由运放的虚断特性可知运算放大器两个输入引脚流过的电流为0,即流过R4的电流为0,Vin=V+。可以看做R13和R15串联,所以流过的电流也相同。由虚短特性可知两个输入引脚的电压相同,即V+=v-,所以有Vin=V+=V-。Vo与R13和R15构成回路,则流过的电流为·
单独对R13来看,流过的电流也等于它两端的电压除以它的电阻值,代入Vin=V+=V一得到以下公式:
由此可以推导出
将Vin=5/3V,人3=20K,RI5=10K带入得Vo=2.5V。
同向比例放大电路验证正确,输出电压为2.5伏。
综合电路:
将正相比例放大电路与反相比例放大电路结合起来共同分析:
当运放正相入端接地,U+=0时,
代入R15=10K,R13=20K,V1=-0.5Vi。
当运放反相输入端接地,U-=0时,
代入R15=10K,R13=20K,Vin=5/3V,V2=2.5V。
当两电路共同作用时vout=V2+V1=2.5+0.5Vin,整理可得·
Vo信号将直接接到单片机的ADC引脚,由于单片机采集到ADC的电压范围值为0、3,3V,由此可以计算出该示波器输入电压范围。
当输入信号Vin不衰减时,将Vo=0、vo=3.3V分别代入公式得,
当输入信号Vin衰减1/50时,将Vo=0、Vo=3。3V分别代入公式得.
得到以下结论·
.当开关5和3接到一起时,可以测量的输入信号幅值为-1.6-5v
.当SW5开关2和1接到一起时,可以测量的输入信号幅值为·80V一250V
比较器测频电路
为了实现频率检测的功能,将ADc输入信号通过一个滞回比较器对输入信号进行比较,实现频率的测量功能。滞回比较器是属于电压比较器中的一种,常规的电压比较器是一个单限比较器,电路中只有一个阈值电压,但在输入电压在阈值附近有微小变化时都会引起输出电压的越变。
为了增强电路的抗干扰能力,在单限比较器的基础上引入了正反馈,保障了在一定范围内信号的稳定性。通过滞回比较器电路后输出一个方波信号,使用单片机的定时器捕获功能计算出输入波形的周期大小。
滞回比较器电路的阈值电压需单独对运放输出结果进行分析,原始电路如下图所示:
当输出为高电平时,输出端上拉到高电平,这时等效电路如下中图,算得Uth=U+=2.214V。
当运放输出为低电平时,输出端接地,等效电路如下右图,算得Utl=U-=2.172V。
下图绿色线代表信号输入电压变化肩况,从0电位上升,初始输出状态为高电平,输入电压达到2,214V时,
输出信号变成低电平,直到输入信号低于下限阈值2,172V时输出变为高电平。可以根据比较器当前的输出状
态来确定下一个变化电平的阈值,当输出为高电平时使用的是高阈值Uth,输出为低电平时使用低阈值Tt|。
之所以将阈值设置接近是为了避免信号干扰造成的误识另刂。
下图绿色线代表信号输入电压变化肩况,从0电位上升,初始输出状态为高电平,输入电压达到2,214V时,AAAAAAAAAAAA输出信号变成低电平,直到输入信号低于下限阈值2.172V时输出变为高电平。可以根据比较器当前的输出状态来确定下一个变化电平的阈值,当输出为高电平时使用的是高阈值Uth,输出为低电平时使用低阈值Ttl。之所以将阈值设置接近是为了避免信号干扰造成的误识别。
注意事顶:
此处阈值比较器运放正向输入信号为固定电平,若使用带有DAC输出的单片机,可自由配置该点电位大小,从而改变直电压,实现对触发模式的设置。
电源电路
USB电源输入
该项目使用GD32最小系统板为核心,板载亍5V转33V降压电路,所以在设计扩展板时只需要设计一个5V电源输入电路即可,这里选用了主流的type-c为输入接口,且该接口只有两根线,插件封装,方便新手焊接学习,但需要注意的是这个pe·c接口仅用于供电,不能传输数据,如果需要使用传输数据,可以使用核心板上的Type--接口。sw1为电源总开关、C1为输入滤波电容,RI是LED1的限流电阻。
负电压产生电路
除了电源输入电路为,为保障运算放大器对于负电压的测量性能,使用了XD7660负压产生电路得到一个负电压,该芯片夕卜围电路简单,只需要两个电容和一个二极管即可工作,理论上输入电压为+5V,也可以输出一个5V的电压,由于芯片内部存在一定压降及转换效率,实际测量负电压为还3V左右,也能满足运算放大器的要求。
单片机电路
该项目使用了由立创开发板团队推出的GD32最小系统板为主控,这款开发板是由立创开发板团队联合兆易创新推出的一款全国产的开发板,板载CH340下载芯片,只需要一根数据线就可以对板子进行烧录与串口调试,同时兼容STM32最小系统板的尺寸与引脚配置,可以直接进行替换。
人机交互电路
液晶屏显示电路
1.8TFT是一款彩色显示屏,具有128×160个彩色像素,使用四线spI通信方式与单片机进行连接,一共有八根引脚,模块引脚说明及与单片机连接情况如下所示:
屏幕购买链接:
https://item.taobao.com/item.htm?_u=n34jmok8fa2c&id=709270273013&spm=a1z09.2.0.0.67002e8dxYMtHQ
高清SPI TFT显示彩屏0.96寸1.3寸1.44寸1.8寸 OLED液晶屏 st7735-淘宝网 (taobao.com)
旋转编码器电路
旋转编码器属于一种特殊的按键,该项目使用的ECII旋转编码器有五个引脚,其中DE两个引脚类似于普通按键引脚,按下导通,松手断开,其余ABC三个引脚用于检测旋钮的转动方向,c脚为公共端,直接接地就行。
在旋转编码器时,A和B两个信号引脚存在相位差,也就是有一个引脚信号变化后另一个引脚信号再跟着变化,即两个引脚不同时变化,通过检测哪个引脚先变就能判断是正转还是反转功能。
LED灯指示电路
LED指示电路设计比较简答,采用低电平驱动的方式,当单片机引脚输出为低电平时,LED两端存在电势x差,LED点亮;当单片机引脚输出为高电平时,LED灯熄灭。
按键控制电路
除了旋转编码器外,该项目还使用了三个独立按键对系统进行控制,三个按键一侧直接接地,另一侧连接到单片机引脚,当单片机引脚检测到按键按下时,单片机引脚直接接到GND接地,单片机收到该引脚接地信号的反馈后再去实现对应的功能,为节约硬件成本,可以在软件设计时引入消抖功能,避免机械按键抖动时的误触发。
波形输出接口
除了示波器检测功能夕卜,单独引出了一个pwM信号用于模拟一个简易的函数发生器功能,可以通过改变输出PWM的频率和占空比输出一个简易方波信号输出。
PCB设计
走线长度尽量短,走线沿焊盘方向引出
PCB设计尽量避免产生锐角和直角,产生不必要的辐射干扰
走线过程中不允许出现一端浮空走线,避免天线效应
电源滤波去耦电容走线时保证电流先流过电容滤波再给器件供电
在设计走线时,保证信号其回路面积尽可能小,即最小回路原则PCB走线时尽量加宽电源与地线宽度,地线>电源线>信号线宽度
走线以直线为主,如需拐弯时拐角以135。钝角或圆角优先,减少直角的使用,
走线线宽电源线宽大于信号线,该项目中信号线走线宽度为15mil,电源走线为20mil,GND和AGND网络使用铺铜的方式连接;
建议优先使用顶层走线,走不通的地方使用过孔建立顶层和底层的连接后转到底层继续走,底层走不通同样可以放置过孔换到顶层连线,
对AGND和GND需要以0欧姆电阻处为分界单独覆铜铜,这里需结合PCB布局情况来调整覆铜范围,
覆铜完成后如果还存在飞线,可通过在存在飞线的位置放置对应网络的过孔或者是调整走线位置网络能够连接,也可以采用手动接线的方式消除飞线。
走线完成后可在"工具"菜单栏选择泪滴添加,加强焊盘与走线的连接,最后再进行覆铜操作,如果对走线有移动调整也应使用快捷键shift+B进行重建覆铜。
软件
LED
LED灯发光原理
LED灯内部是一个半导体晶片,一半是P
型半导体,另一半是N型半导体。这两种半导体连接起来时,就形成了P一N结,当电流通过导线作用于这个晶片时,电子就会被推向P区,在P区里电子跟空穴复合,然后就会以光的形式发出能量,这就是LED灯发光的原理。
LED灯驱动原理
驱动LED灯,也就是使LED灯点亮,首先查看原理图,查看LED灯引脚的连接关系,可通过对应单片机引脚输出高低电平,从而改变LED灯两侧电势差形成电流回路,点亮LED
示波器板led原理图
- Init_LED_GPIO 函数:
-
- 这个函数用于初始化LED灯所连接的GPIO引脚。
- 首先,它使能了GPIOC的时钟。
- 然后,它设置了GPIOC的两个引脚(PIN_14和PIN_15)为输出模式,并且没有启用上拉或下拉电阻。
- 接着,它设置了这两个引脚的输出类型为推挽输出,并且输出速度为50MHz。
- 最后,它调用CLose_LED函数来关闭LED灯(即初始化时LED灯是关闭的)。
- Open_LED 函数:
-
- 这个函数用于打开LED灯。
- 它接收一个参数value,这个参数的值决定了哪个LED灯被打开。
- 如果value是1,则GPIOC的PIN_14引脚被拉低,这通常意味着LED灯(如果连接到该引脚)会亮起。
- 如果value是2,则GPIOC的PIN_15引脚被拉低,这通常意味着另一个LED灯(如果连接到该引脚)会亮起。
- 如果value不是1或2,则不进行任何操作。
- CLose_LED 函数:
-
- 这个函数用于关闭LED灯。
- 它也接收一个参数value,这个参数的值决定了哪个LED灯被关闭。
- 如果value是1,则GPIOC的PIN_14引脚被置高,这通常意味着LED灯(如果连接到该引脚)会熄灭。
- 如果value是2,则GPIOC的PIN_15引脚被置高,这通常意味着另一个LED灯(如果连接到该引脚)会熄灭。
- 如果value不是1或2,则不进行任何操作。
按键
独立按键结构组成
独立按键实际上是一个非自锁的轻触开关,有左右四个触点,当按下时左右四个触点闭合,当松开时左右四个触点断开,12触点与34触点在内部是连接在一起的。
独立按键驱动原理
单片机通过检测按键按下前后的高低电平变化,来判断按键是否按下。通过程序的控制,就可以实现不同的功能与设置。机械式按键在按下或者释放时,由于机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才稳定下来。抖动时间长短与开关的机械特性有关,一般为5一10ms。在触点抖动期间检测按键的按下与否,可能会导致判断错误,为了克服机械抖动所产生的影响,必须采取消抖措施,可分为硬件消抖和软件消抖。
消抖
硬件消抖:
硬件消抖一般会在按键检测引脚处加入电容与电阻,通过RC延迟电路将按键按下时的高频振荡吸收滤除掉。
软件消抖:
软件消抖一般是通过延时。当检测到按键按下时,不会立即去检测电平,而是经过短暂的延时之后,再去检测当前引脚的电平,这样就可以去掉抖动过程中的干扰,一般抖动时间在10ms以内。
驱动原理·
驱动独立按键,首先需要判断按键两端的引脚,根据按键两侧引脚接法的不同,可分为两种情况。
按键一侧接电源
GPIO需要设置为下拉,也就是默认为低电平,通过判断对应GPIO引脚为高电平,从而判断按键是否按下。
按键一侧接GND·
GPIO需要设置为上拉,也就是默认为高电平,通过判断对应GPIO引脚为低电平,从而判断按键是否按下。
GPIO 初始化
Init_Key_GPIO 和 Init_EC11_GPIO 函数负责初始化连接到按键的GPIO引脚。它们通过配置GPIO的模式(输入模式、上拉电阻)、使能中断线以及初始化中断线来实现这一目的。
- rcu_periph_clock_enable:使能特定外设的时钟,以便它可以工作。
- gpio_mode_set:设置GPIO引脚的模式,这里是输入模式,并使用上拉电阻。
- nvic_irq_enable:使能中断,以便当GPIO引脚的状态改变时,可以触发中断。
- syscfg_exti_line_config:配置外部中断线,将GPIO引脚与中断线连接起来。
- exti_init:初始化外部中断线,设置触发方式(这里是下降沿或上升沿触发)。
- exti_interrupt_flag_clear:清除中断标志位,确保没有未处理的中断。
按键处理函数
Key_Handle 函数根据按键的值调整Oscilloscope_Value结构体中的pwmOut成员。
- switch 语句根据按键值执行不同的操作。
- KEY1 和 KEY2 分别增加和减少pwmOut的值,并检查其是否超出范围。
- KEY3 和 KEY4 似乎执行一个延时操作,但实际上它们并没有改变pwmOut的值。这可能是代码的一个错误或未完成的部分。
中断服务函数
EXTI4_15_IRQHandler 函数是一个中断处理程序,当外部中断线4到15中的任一条线触发中断时,该函数会被自动调用。
- 函数首先通过exti_interrupt_flag_get函数检查是哪一个中断线触发了中断。这通过检查EXTI_9、EXTI_13、EXTI_14、EXTI_15和EXTI_4的中断标志位来实现。
- 如果检测到中断,它会清除相应的中断标志位,以避免重复处理同一个中断。
- 根据触发中断的引脚,函数将keyValue设置为对应的按键值(如KEY1、KEY2、KEY3、KEY4或EC11_KEY)。
- 如果keyValue不为0,说明确实有一个按键被按下,于是将Oscilloscope_Value结构体的keyValue成员设置为这个按键值,并调用Key_Handle函数来处理这个按键事件。
按键处理逻辑
Key_Handle 函数根据按键的值调整Oscilloscope_Value结构体中的pwmOut成员,这通常用于控制PWM(脉宽调制)信号的占空比。
- 对于KEY1,它增加pwmOut的值,但不超过timerPeriod。这可能是用于增加PWM信号的占空比,从而增加输出信号的强度或持续时间。
- 对于KEY2,它减少pwmOut的值,但不小于0。这是用于减少PWM信号的占空比。
- KEY3和KEY4的处理逻辑看起来有些奇怪,因为它们执行了一个延时操作,但并没有改变pwmOut的值。这可能是代码的一个错误,或者这些按键原本计划用于其他功能,但这部分功能尚未实现。
串口
Init_USART 函数
这个函数用于初始化USART(通用同步异步收发器)串口,使其能够发送和接收数据。
- 函数参数:bound 是波特率,即每秒传输的符号数,它决定了通信的速率。
- 函数功能:
-
- 使能GPIOA端口和USART0的时钟。
- 配置GPIOA端口的引脚9和10为复用功能,通常用于USART的TX和RX。
- 设置引脚9和10的模式为复用功能(AF),并启用上拉电阻。
- 配置USART0的参数,包括数据位宽度(8位)、停止位(1位)、校验位(无)和波特率。
- 启用USART0的接收和发送功能。
- 最后使能USART0。
fputc 函数
这个函数是标准库函数fputc的重定向实现,用于将字符发送到串口。
- 函数参数:ch 是要发送的字符,f 是文件指针(在这个上下文中可能并未使用)。
- 函数功能:
-
- 使用usart_data_transmit函数将字符ch发送到USART0。
- 使用while循环等待直到USART0的发送缓冲区为空(USART_FLAG_TBE标志被设置),以确保字符被成功发送。
- 返回发送的字符ch。
中断
中断介绍
中断即打断,当单片机在顺序执行当前程序时,由于系统出现了某种需要紧急处理的情况,单片机暂停正在执行的程序,转而执行紧急事务,当处理结束后单片机自动返回到原先暂停的程序中继续执行,这种执行过程由于夕卜界的原因被打断的情况叫做中断。
中断应用
正常程序是顶序执行的,但是在嵌入式系统中,往往会出现短暂的需要紧急处理的事件,比如按键按下,虽然死循环检测也同样可以,但会消耗大量的CPIJ资源去做无用检测,通过中断的方式,只有当按键按下事件来临时,才去处理,可以节省资源。
外部中断:
GD32E230外部中断卜部中断EXTI包括21个互相独立的边沿检测电路并且能够向处理器内核产生中断请求或唤醒事件。EXTI有三种触发类型:上升沿
触发、下降沿触发和任意沿触发。EXTI中的每一个边沿检测电路都可以独立配置和屏蔽。
中断触发·
GD32E230夕卜部中断EXTI触发源包括来自I/O管脚的16根线以及来自内部模块的5根线。通过配置SYSCFGEXTISS×寄存器,所有的GP℃管脚都可以被选作EXTI的触发
中断优先级:
GD32E230是M23内核,没有中断优先级分组的概念,支持4个优先级设置(3),数字越小,等级越高。高优先级可抢占低优先级中断。
旋转编码器
原理说明
旋转编码器可以当做是一种位移传感器,旋转它,可以判断是正转还是反转,以及旋转的角度。从符号上可以看出,DE引脚是普通的开关,按下旋转编码器,开关导通,不按下时开关断开。旋转判断主要是通过ABC三个引脚来进行判断。
C端口接GND,A与B引脚连接GPIO,软件上拉,当正向旋转时,内部触点会先接触A,再接触B,反转则相反。
所以,想要判断正转还是反转,可以通过规定一个引脚,在它的下降沿处判断另外一个引脚的电平。比如检测A端口,在A端口的下降沿触发时,如果B端口是高电平,则是正转,如果是低电平,则是反转。
ADC采集信号
ADC介绍
ADc是一种用于将模拟信号转换为数字信号的模拟数字转换器。我们知道,模拟信号是连续的,其取值可以在一定范围内任意变化。而数字信号则是离散的,仅能取有限的值。ADC的工作原理是将模拟信号通过采样转换为离散的数字信号,然后再通过量化、编码等处理,最终得到对应的数字表示。ADC采样的频率越高,得到的数字信号就越接近原来的模拟信号,也就是保真度越高,但是需要更多的资源和计算功耗。
GD32E230片上集成了12位逐次逼近式ADC,可以采样来自10个外部通道、2个内部通道的模拟信号,最快采样速率2MSPS。
GD32E230ADC支持三种模式,扫描模式、注入通道自动转换模式、连续模式。
扫描模式下,ADC按照预设的顺序扫描多个通道,并对每一个通道进行一次采样和转换,扫描模式下需要开DMA,这是因为不开启DMA,可能会导致通道数据被下一个通道数据给覆盖
注入通道自动转换模式下,类似于中断,当有注入通道触发后,会优先采样转换注入通道。
在连续模式下,一旦ADC被启动,它会不断对选定的通道进行采样和转换,直到函数命令其停止,连续转换模式下转换无需重新启动。
注意这里的模式并不是多选一结构,而是多选多,自由搭配,例如:连续扫描转换模式,可连续不间断扫描。
如果当以上三种模式都关闭,即打开单次转换模式。
GD32E230ADC支持各种数据对齐方式以适应不同的应用场景,常见的数据对齐方式包括左对齐和右对齐。在右对齐模式下,ADC的数据在转换结束后会右对齐到最低位,不足的位数在高位填充0,
左对齐则是对齐到最高位,在低位填充0。
一般情况下选择右对齐,可直接将转换完成的数据进行计算。
ADC转换的步骤.采样、保持、量化、编码;转换时间设置越快,采样精度越低。并且随着转换时间设置越快,夕卜部阻抗也需要更小,以降低干扰。
GD32E230ADC分辨率可配置为6、8、10、12为,如果对精度要求不高,可以通过降低分辨率来获得更快的转换时间。
使用ADC功能,需要开启ADC时钟,这里ADC时钟不同于其他夕卜设时钟,它有一个最大时钟频率,在28Mhz。
ADC时钟来源是AHB(72Mhz-max)、APB2(72Mhz-max)、lRC28(28Mhz)总线,需要选择一个时钟源,并将其分频到28Mhz以下。假设使用AHB总线、3分频,这样输入时钟是72/3=24Mhz,接近最大速度。
get_ADC_Value 函数
这个函数的目的是获取存储在 adc_value 数组中的ADC值。它接受一个下标 value 作为参数,并返回对应下标的ADC值。如果下标超出了数组范围(即大于 ADC_VALUE_NUM),则函数会将下标重置为0。在返回ADC值之后,它还会将数组对应位置的值清零。
Init_ADC 函数
这个函数用于初始化ADC模块。它首先使能了相关的GPIO引脚和ADC模块的时钟。接着,它配置了ADC的时钟、引脚模式、特殊功能(如连续模式、扫描模式、注入组自动转换模式)、数据校准、通道长度、常规通道配置以及触发源。然后,它使能了ADC并启动了校准。最后,它使能了DMA模式,并通过软件触发启动了ADC。
ADC_DMA_Init 函数
- DMA时钟使能:rcu_periph_clock_enable(RCU_DMA); 确保DMA控制器的时钟被使能,以便DMA可以正常工作。
- DMA参数结构体:定义一个dma_parameter_struct类型的变量dma_data_parameter,用于存储DMA的配置参数。
- 使能DMA中断:nvic_irq_enable(DMA_Channel0_IRQn, 0U); 使能DMA通道0的中断,以便在DMA传输完成时能够响应中断。
- 通道0复位:dma_deinit(DMA_CH0); 将DMA通道0复位到初始状态。
- DMA参数配置:
-
- periph_addr:外设(ADC)的基地址,设置为ADC_RDATA的地址。
- periph_inc:外设地址不自增,因为ADC数据是连续从同一地址读取的。
- memory_addr:内存地址,设置为adc_value数组的地址。
- memory_inc:内存地址自增,因为数据会被连续写入adc_value数组的不同位置。
- periph_width 和 memory_width:都设置为16位,因为ADC数据和数组元素都是16位宽。
- direction:数据从外设(ADC)传输到内存。
- number:传输的数据量,设置为ADC_VALUE_NUM,即数组的大小。
- priority:设置DMA传输的高优先级。
- DMA通道0初始化:dma_init(DMA_CH0, &dma_data_parameter); 使用配置的参数初始化DMA通道0。
- DMA循环模式使能:dma_circulation_enable(DMA_CH0); 使能DMA的循环模式,这意味着当DMA完成一次传输后,它会自动重新开始,持续不断地从ADC读取数据到内存。
- DMA通道0使能:dma_channel_enable(DMA_CH0); 启动DMA通道0的传输。
- 使能DMA传输完成中断:dma_interrupt_enable(DMA_CH0, DMA_CHXCTL_FTFIE); 当DMA完成一次数据传输时,将产生一个中断。
DMA_Channel0_IRQHandler 中断处理程序
- 中断标志检查:if(dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_FTF)) 检查DMA通道0是否完成了数据传输。
- 中断处理:
-
- oscilloscope.showbit=1; 设置oscilloscope结构体的showbit字段为1,可能用于通知其他程序部分DMA传输已完成,并且数据可用于显示或处理。
- dma_channel_disable(DMA_CH0); 禁用DMA通道0,停止进一步的DMA传输。这通常是为了在处理完当前批次的数据后,防止新的数据被写入adc_value数组,直到程序准备好再次启动DMA。
- 清除中断标志位:dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G); 清除DMA的中断标志,确保中断不会再次被误触发。
定时器
定时器是单片机内部集成,可以通过编程控制。单片机的定时功能是通过计数来实现的,单片机每一个时钟周期产生一个脉冲,计数器就加1,当计数达到设置的值后,就代表时间到了。
定时器作为单片机的基础夕卜设,几乎每一个程序都会使用到,像ms、us延时,都是通过系统滴答定时器计数从而实现延时的。除此之夕卜,定时器还可以用于PWM输出、输入捕获、以及编码器模式等等。
GD32E230定时器支持3种计数模式:
向上计数模式:计数器从0计数到自动加载值(周期值),然后重新从0开始计数并产生一个计数器溢出事件。
向下计数模式:计数器从自动加载值(周期值)开始向下计数到0,然后重新从自动加载值开始,并产生一个溢出事件。
中央对齐模式:计数器从0开始计数到自动加载值一1,产生一个计数器溢出事件,向下计数到1并产生一个计数器溢出事件。再从0开始重新计数。
PWM输出
PWM介绍
PWM(Pulse-widthmodu丨ation)是脉冲宽度调制的缩写。脉宽调制是利用微处理器的数字输出,来对模拟电路进行控制的一种非常有效的技术,通过对一系列脉冫中的宽度进行调制,来等效获得所需要的波形(含形状和幅值),即通过改变一个周期内高电平所占时间,也就是占空比,达到调整电压的目的。
PWM在各种领域中有广泛的应用
在照明控制中:通过调节PWM信号的占空比来控制LED灯的亮
度,在电机控制中:通过调节PWM信号的占空比来控制电机的转速和扭矩,
GD32PWM介绍:
每一个PWM通道都对应单片机的一个管脚,这个引脚不是唯一固定的,可能
有一个管脚或多个管脚对应同一个通道。比如刊MER14CHO对应PA2和PB14,
就是PA2和PB14管脚都可以配置为定时器的通道0,我们在使用的时候可以任
选其一进行配置。
PWM基本参数:
频率·
是指单位时间(s)内信号从高电平到低电平再回到高电平的次数(周期)·
单位:Hz、Khz、Mhz
频率=1/周期;
假设频率为50Hz,也就是意味着一个周期是20ms(1/20ms)*1000=50Hz
占空比:
是指一个脉冲周期内,高电平的时间占整个周期时间的比例
单位:%
- Init_PWM_Output函数用于初始化PWM输出。它接受两个参数:period(周期)和pulse(脉冲)。在函数内部,首先配置GPIOA的第2个引脚为复用功能,并设置为推挽输出模式。然后使能时钟,初始化定时器参数结构体,配置定时器通道输出参数结构体,设置输出比较值,配置输出模式等。最后,禁用定时器。
- Set_Output_PWMComparex函数用于设置PWM占空比。它接受一个参数value,表示占空比的值。在函数内部,调用timer_channel_output_pulse_value_config函数设置定时器通道0的脉冲值。
- Set_Output_Freq函数用于设置PWM输出的频率。它接受一个参数value,表示频率的值。在函数内部,调用timer_autoreload_value_config函数设置定时器的自动重载值。
输入捕获测频率
通道输入极'陸:指捕获的跳变沿是上升沿还是下降沿。
通道输入模式:分为直接输入、间接输入、ITS输入。(不同定时器的捕获通道可能稍有不同——L2)
捕获频率方法:
下图是一个方波信号,信号从上升沿/下降沿开始,到另一个上升沿/下降沿结束,此时将输入捕获设置为下降沿捕获,当下降沿沿到来时,触发中断,记录当前时间,直到下一个下降沿到来时再次触发,记录两次时间的差值,即是整个信号的时间,最后通过定时器自身频率/时间=信号频率。
- Init_FreqTimer()函数用于初始化频率计时器,包括以下步骤:
-
- 使能时钟:使用rcu_periph_clock_enable()函数使能GPIOA和TIMER2的时钟。
- 设置引脚模式:使用gpio_mode_set()函数将GPIOA的PIN6设置为复用功能(AF)。
- 设置输出状态:使用gpio_output_options_set()函数设置GPIOA的PIN6为推挽输出(PP)和50MHz的速度。
- 定时器中断使能:使用nvic_irq_enable()函数使能TIMER2的中断。
- 复位定时器:使用timer_deinit()函数复位TIMER2。
- 定时器参数初始化:使用timer_struct_para_init()函数初始化定时器参数结构体timer_initpara。
- 配置定时器参数:设置预分频器、计数方向、周期等参数。
- 初始化定时器通道输入参数:使用timer_channel_input_struct_para_init()函数初始化定时器通道输入参数结构体timer_icinitpara。
- 配置定时器通道输入捕获:使用timer_input_capture_config()函数配置TIMER2的通道0的输入捕获参数。
- 使能自动重装载值:使用timer_auto_reload_shadow_enable()函数使能TIMER2的自动重装载值。
- 清除中断标志位:使用timer_interrupt_flag_clear()函数清除TIMER2的通道0的中断标志位。
- 使能定时器通道中断:使用timer_interrupt_enable()函数使能TIMER2的通道0的中断。
- 使能定时器:使用timer_enable()函数使能TIMER2。
- TIMER2_IRQHandler()函数是TIMER2的中断处理函数,当定时器通道0发生中断时执行以下操作:
-
- 读取第一次通道0捕获值:如果ccnumber等于0,则读取通道0的捕获值并存储到readvalue1中,并将ccnumber设置为1。
- 读取第二次通道0捕获值:如果ccnumber等于1,则读取通道0的捕获值并存储到readvalue2中。
- 计算频率:根据两次捕获值的差异计算频率,并将结果存储到freq变量中。
- 更新示波器频率:如果计算出的频率大于等于100Hz,则将该频率赋值给oscilloscope.gatherFreq。
- 重置变量:将readvalue1、count、freq、readvalue2和ccnumber重置为初始值。
- 清除中断标志位:使用timer_interrupt_flag_clear()函数清除TIMER2的通道0的中断标志位。
屏幕
常见屏幕类型
屏幕作为显示设备,在生活中随处可见,在嵌入式系统中,显示屏幕主要有LCD、OLED两种,根据大小、制作材料的不同,又有许多细分,如LCD1602、0,96寸OLED、1·8寸LCD屏等。
屏幕应用
嵌入式系统中屏幕常用于:
设备参数显示;
环境参数显示;
人机交互显示等。
LCD屏幕驱动方式介绍:
通常LCD屏幕厂商为了降低开发难度,一般会在屏幕中内置驱动芯片,同时引出引脚与夕卜界进行通信,常见的驱动芯片有ST7735S、ILI9163、ST7789等等。
同时,LCD屏幕在引出引脚方面,也分为SPI串口通信(四线)、以及8080并口通信(8线)等方式。SPI总线包括四条逻辑线,定义如下:
MISO:Masterlnputslaveoutput-主机输入,从机输出。(数据来自从机),
MOSI:Masteroutputslaveinput-主机输出,从机输入。(数据来自主机),
SCLK:SerialClock一串行时钟信号,由主机发生给从机;
NSS:SalveSelect片选信号,由主机发送,以控制与哪个从机通
信,通常是低电平有效信号。
屏幕厂商一般会根据自己所用的驱动芯片,写好驱动案例,大家在购买屏幕时可以找到屏幕厂商对应的资料,根据板子引脚与时序进行修改即可。
GD32一SPI通信介绍:
SPI:SeriaIPeripheralinterface的缩写,意思是串行外围设备接口。前面我们介绍的一种方式是串口通信,只不过是异步串行通信,SPI是具有时钟线,是一种高速、全双工的同步串行通信总线。
GD32E230支持SPI0与SPI1两个通信接口,在使用时,需要将对应的外设SPI引脚连接到GD32一SPI引脚上。才可使用硬件SPI。否则只能使引脚高低电平变化模拟SPI通信时序。
SPI通信介绍:
1.SPI数据交换过程
SPI是一个环形总线结构,由四根线组成,SSPSR是SPI设备内部的移位寄存器,根据SPI时钟信号状态,往SSPBUF中移入或移出数据,注意这个环形的说法,这里当MOSI向从机发送一位数据后,从机的MOSO也会移位数据给主机,只不过主机可以根据需要是否将其放置接收缓冲区中,比如,如果是主机发送0×80,从机可能会移位过来一位无意义的数据,这时主机不会管这些数据,会选择丢弃。
如果主机需要接收数据,那就是发送无意义的数据给从机,以此来交换有效数据存储到接收缓冲区中去。
2·SPI总线极性与相位
极性:会直接影响SPI总线空闲时的时钟信号是高电平还是低电平;
相位:会直接决定SPI总线从哪个跳变沿开始采样数据,
其中,CPOL配置SPI总线的极性,CPHA配置SPI总线的相位,
CPOL=1:表示空闲时是高电平,
CPOL=0:表示空闲时是低电平。
由于数据传输是从跳变沿开始的,如果空闲时是高电平,那么数据传输时是下降沿,反之则是上升沿。
从原理图中可以看出,该屏幕使用的是ST7735驱动芯片,引脚接口为四线SPI通信。
SCL(PA5)-->SCLK,
SDA(PA7)-->MOSl;
CS(PB7)-->NSS,
DC(PB6)一>芯片命令/数据控制弓|脚,
RES(PB5)一>芯片复位引脚,
BLK(PB8)一>背光控制引脚,
这里引脚中没有MISO,这是因为内部芯片无需向外部主控发送数据,所以MISO数据线就没有引出。
1.8寸屏幕是128160的大小,也就是说有128160=20480个像素点,如果是整个屏幕刷新一次,那就需
要定义20480*2的字节,因为颜色显示是uint16_t的;单片机仅有8KRAM,显然不现实。
这里供两个思路(显示波形就是显示折线)
第一个,以时间为×轴,电压为Y轴建立平面直角坐标系,将电压值转换为平面直角坐标系上的点,画
一个点,然后使其与前面的点连接成线,随后时间轴往后推一格,再画一个点,然后连线,循环往复。最后
形成波形,并且考虑到第一次波形显示会对第二次显示造成干扰,画点连线之后,先把后一行的屏幕清空,
这样波形可以顺畅显示。
第二个,类似于手机小窗显示,对整体波形显示区域缩小,然后定义一个大数组,同样是平面直角坐标
系,对电压和时间数据进行转换,将对应的点填充成波形颜色,其余没有用到的点填充为背景色,最后显示
效果同样是波形。
tft_init.c
- 初始化SPI0引脚:这部分代码主要是配置GPIOA和GPIOB的时钟,设置复用功能,设置输出模式和速度,以及初始化SPI0。其中,Init_SPI0_GPIO()函数用于初始化SPI0的8位数据宽度,Init_SPI0_GPIO16()函数用于初始化SPI0的16位数据宽度。
- SPI0发送数据:这部分代码主要是定义了两个发送数据的函数,分别是SPI0_Write()和SPI0_Write16()。这两个函数都是通过判断SPI发送缓冲区是否为空,然后发送数据。其中,SPI0_Write()函数用于发送8位数据,SPI0_Write16()函数用于发送16位数据。
- 初始化TFT屏幕引脚:这部分代码主要是配置GPIOB的时钟,设置输出模式和速度,以及初始化TFT屏幕的GPIO。其中,TFT_GPIO_Init()函数用于初始化TFT屏幕的GPIO。
- TFT屏幕发送数据:这部分代码主要是定义了四个发送数据的函数,分别是TFT_WR_DATA8()、TFT_WR_DATA()、TFT_WR_DATA16()和TFT_WR_REG()。这四个函数都是通过拉低片选信号,然后发送数据,最后再拉高片选信号。其中,TFT_WR_DATA8()函数用于发送单个字节的数据,TFT_WR_DATA()函数用于发送2个字节的数据,TFT_WR_DATA16()函数用于发送16位的数据,TFT_WR_REG()函数用于发送命令数据。
- 设置显示地址:这部分代码主要是定义了两个设置显示地址的函数,分别是TFT_Address_Set()和TFT_Address_Set16()。这两个函数都是通过发送列地址和行地址来设置显示地址。其中,TFT_Address_Set()函数用于发送8位的数据,TFT_Address_Set16()函数用于发送16位的数据。
- 初始化TFT屏幕的函数。首先,它调用了TFT_GPIO_Init()和Init_SPI0_GPIO()函数来初始化TFT屏幕的GPIO和SPI接口。接着,它通过设置GPIOB的第5位为低电平来复位TFT屏幕,然后延时100毫秒。之后,它通过设置GPIOB的第8位为高电平来打开TFT屏幕的背光,再延时100毫秒。接下来,它通过发送一系列的命令和数据来设置TFT屏幕的参数,包括设置帧率、电源序列、VCOM电压、RGB模式、伽马序列等。最后,它通过发送0x29命令来开启TFT屏幕的显示。在完成这些操作后,它调用了Init_SPI0_GPIO16()函数来初始化SPI0的16位数据宽度。
- TFT_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color):这个函数用于在指定区域填充颜色。它接收起始坐标(xsta, ysta)和终止坐标(xend, yend),以及要填充的颜色color作为参数。函数内部通过设置显示范围,然后使用循环遍历区域内的每个点,并调用TFT_WR_DATA16函数将颜色值写入到对应的点上。
- TFT_DrawPoint(uint16_t x, uint16_t y, uint16_t color):这个函数用于在指定坐标画一个点。它接收点的坐标(x, y)和要填充的颜色color作为参数。函数内部通过设置显示范围,然后调用TFT_WR_DATA16函数将颜色值写入到指定的点上。
- TFT_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color):这个函数用于画一条线。它接收起始坐标(x1, y1)和终止坐标(x2, y2),以及要填充的颜色color作为参数。函数内部通过计算坐标增量,然后使用循环遍历线上的每个点,并调用TFT_DrawPoint函数将点画出来。
- TFT_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color):这个函数用于画一个矩形。它接收起始坐标(x1, y1)和终止坐标(x2, y2),以及要填充的颜色color作为参数。函数内部通过调用TFT_DrawLine函数分别画出矩形的四条边。
- Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color):这个函数用于画一个圆。它接收圆心坐标(x0, y0)、半径r和要填充的颜色color作为参数。函数内部通过计算圆上的每个点的坐标,并调用TFT_DrawPoint函数将点画出来。
- drawCurve(uint8_t yOffset, short int rawValue):这个函数用于画折线。它接收Y轴参数值yOffset和原始值rawValue作为参数。函数内部根据原始值的范围进行处理,然后计算出折线的Y轴坐标,并调用TFT_DrawPoint函数将点画出来。
- TFT_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode):这个函数用于显示一个字符。它接收起始坐标(x, y)、要显示的字符num、字的颜色fc、背景色bc、字号sizey和模式mode作为参数。函数内部根据字号选择对应的字体数据,然后根据字符的点阵信息,调用TFT_DrawPoint或TFT_DrawLine函数将字符画出来。
- TFT_ShowString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode):这个函数用于显示一个字符串。它接收起始坐标(x, y)、要显示的字符串指针p、字的颜色fc、背景色bc、字号sizey和模式mode作为参数。函数内部通过循环遍历字符串中的每个字符,并调用TFT_ShowChar函数将字符显示出来。
- TFT_ShowChinese(uint16_t x, uint16_t y, uint8_t *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode):这个函数用于显示一个汉字串。它接收起始坐标(x, y)、要显示的汉字串指针s、字的颜色fc、背景色bc、字号sizey和模式mode作为参数。函数内部通过循环遍历汉字串中的每个汉字,并调用相应的汉字显示函数(如TFT_ShowChinese12x12、TFT_ShowChinese16x16、TFT_ShowChinese24x24)将汉字显示出来。
- TFT_ShowChinese,入口参数包括x、y坐标、要显示的汉字、字的颜色、字的背景色、字号以及模式(非叠加模式或叠加模式)。函数内部通过查找点阵字库来显示对应的汉字。函数首先定义了一些变量,如i、j、m、k等,用于循环和计数。然后根据字号计算一个字符所占字节大小,即TypefaceNum。接着统计汉字数目,即HZnum。接下来,函数使用for循环遍历点阵字库,查找与输入的汉字相匹配的字库。如果找到匹配的字库,函数会设置显示区域的范围,即调用TFT_Address_Set16函数。然后使用嵌套的for循环遍历每个字符的点阵信息,根据模式选择非叠加方式或叠加方式进行显示。在非叠加方式下,函数会根据点阵信息绘制每个像素点;在叠加方式下,函数会在已有的像素点上绘制新的像素点。
- TFT_ShowUI。函数接收一个指向Oscilloscope结构体的指针作为参数,该结构体包含了峰峰值、频率、直流偏执信号等信息。函数首先定义了一个字符数组showData,用于存储要显示的数据。然后使用sprintf函数将峰峰值信息格式化为字符串,并调用TFT_ShowString函数在屏幕上显示。接着根据频率是否大于等于1000来选择显示单位是千赫兹还是赫兹,并调用TFT_ShowString函数显示相应的数据。接下来,根据输出状态(ouptputbit)的值,选择显示"打开"或"关闭",并调用TFT_ShowChinese函数显示。同样地,根据输出频率是否大于等于1000来选择显示单位,并调用TFT_ShowString函数显示相应的数据。最后,计算占空比,并将结果格式化为字符串,调用TFT_ShowString函数显示。整个函数的作用是根据输入的示波器参数,在屏幕上显示相应的信息,包括峰峰值、频率、直流偏执信号、输出状态、输出频率和占空比等。
tft.c
- TFT_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color):在指定区域填充颜色。参数xsta、ysta表示起始坐标,xend、yend表示结束坐标,color表示要填充的颜色。
- TFT_DrawPoint(uint16_t x,uint16_t y, uint16_t color):在指定坐标画点。参数x、y表示画点的坐标,color表示要填充的颜色。
- TFT_DrawLine(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t color):画一条线。参数x1、y1表示起始坐标,x2、y2表示结束坐标,color表示线的颜色。
- TFT_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color):画一个矩形。参数x1、y1表示左上角坐标,x2、y2表示右下角坐标,color表示矩形的颜色。
- Draw_Circle(uint16_t x0,uint16_t y0,uint8_t r,uint16_t color):画一个圆。参数x0、y0表示圆心坐标,r表示半径,color表示圆的颜色。
- drawCurve(uint8_t yOffset,short int rawValue):画折线图。参数yOffset表示Y轴偏移量,rawValue表示Y轴参数值。
- TFT_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode):显示一个字符。参数x、y表示起始坐标,num表示要显示的字符,fc表示字的颜色,bc表示字的背景色,sizey表示字号,mode表示显示模式(0非叠加模式,1叠加模式)。
- TFT_ShowString(uint16_t x,uint16_t y,const uint8_t *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode):显示一个字符串。参数x、y表示起始坐标,*p表示要显示的字符串,fc表示字的颜色,bc表示字的背景色,sizey表示字号,mode表示显示模式(0非叠加模式,1叠加模式)。
- TFT_ShowChinese(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode):显示一个汉字串。参数x、y表示显示坐标,*s表示要显示的汉字串,fc表示字的颜色,bc表示字的背景色,sizey表示字号,mode表示显示模式(0非叠加模式,1叠加模式)。显示不同大小汉字的函数库,包括12x12、16x16和24x24像素的汉字。函数接收参数包括显示坐标(x,y)、要显示的汉字(s)、字的颜色(fc)和字的背景色(bc)、字号(sizey)以及模式(mode)。其中,mode为0表示非叠加模式,mode为1表示叠加模式。函数首先定义了一些变量,如i、j、m、k、HZnum、TypefaceNum和x0。然后根据字号计算一个字符所占字节大小(TypefaceNum),并统计汉字数目(HZnum)。接下来,通过循环遍历所有汉字,找到与输入的汉字相匹配的汉字,然后设置显示区域,接着通过嵌套循环遍历每个字符的点阵信息,根据mode的值选择非叠加方式或叠加方式进行显示。最后,在静态UI界面中调用这些函数来显示各种信息。
- 显示示波器界面的函数。它接收一个指向Oscilloscope结构体的指针作为参数,该结构体包含了示波器的相关信息。函数通过调用其他函数来在屏幕上显示峰峰值、频率、直流偏置信号等参数。首先,定义一个字符数组showData,用于存储要显示的数据。使用sprintf函数将峰峰值(vpp)格式化为字符串,并调用TFT_ShowString函数将其显示在屏幕上。根据频率(gatherFreq)的大小,将其转换为千赫兹或赫兹,并调用TFT_ShowString函数将其显示在屏幕上。根据输出位(ouptputbit)的值,显示"打开"或"关闭"。根据输出频率(outputFreq)的大小,将其转换为千赫兹或赫兹,并调用TFT_ShowString函数将其显示在屏幕上。计算PWM输出的占空比,并将其显示在屏幕上。
main函数
首先定义了一个字符数组showData,用于存储要显示的数据。然后使用sprintf函数将峰峰值信息格式化为字符串,并调用TFT_ShowString函数在屏幕上显示。接着根据频率是否大于等于1000来选择显示单位是千赫兹还是赫兹,并调用TFT_ShowString函数显示相应的数据。
接下来,根据输出状态(ouptputbit)的值,选择显示"打开"或"关闭",并调用TFT_ShowChinese函数显示。同样地,根据输出频率是否大于等于1000来选择显示单位,并调用TFT_ShowString函数显示相应的数据。
最后,计算占空比,并将结果格式化为字符串,调用TFT_ShowString函数显示。
整个函数的作用是根据输入的示波器参数,在屏幕上显示相应的信息,包括峰峰值、频率、直流偏执信号、输出状态、输出频率和占空比等。
设计图

BOM


评论