数字电压电流表训练营
简介
【立创开发板&CW32】【新手区】:基于CW32F030C8T6(地文星)跟随立创与芯源半导体官方复刻数字电压电流表。供我们初学者学习使用。电压测量范围0~30V,电流测量范围0~3A
简介:【立创开发板&CW32】【新手区】:基于CW32F030C8T6(地文星)跟随立创与芯源半导体官方复刻数字电压电流表。供我们初学者学习使用。电压测量范围0~30V,电流测量范围0~3A开源协议
:GPL 3.0
描述
2024年9月5日【第一次补丁】
1、本来第一次补丁留待将官方的主体完全吸收后再放出,突然发现官方的数字电压电流表推荐合集突然少了3个,心中怕怕的,遂提前把第一次补丁打上,表示自己还是在认真完善的,虽然有点慢(bushi
2、本次补丁包括:
(1)“四、硬件原理与学习笔记”的“用于电压校准的TL431”新增6张解释说明图(部分手写,展示诚意)
(2)“六、软件例程学习笔记”新增有关“实验九 带有标定功能的数字电压电流表”代码的分析(弥补了官方代码在解释方面的空缺),这部分新增大约5000字及近20张配图(包括对标定计算的理解的手写笔记一张)
(3)“八、复刻过程中的问题解决”新增【问题6】以及相应【解决方法】
(4)“附件”新增我这个电压电流表在未标定前的“2到11.7V”和“0到2.49A”量程下测量值与误差表格
(5)将开源描述的排版和美观度略有优化
3、之后的补丁准备把新的3D外壳文件附上,把增加了换档功能(且符合我手头电源量程)和使用TL431标定的代码附上,并对硬件笔记进一步增加内容,以及录制新的演示视频
2024.8.24首次发布时的注释:
1、因为本次项目是8月9日才开始跟随官方学习的,加上还要实习,可能有些仓促,但我尽力学习新知识,结合官方资料进行再总结并用自己的话表达记录下来而不是仅仅照搬!希望能对大家有帮助~
2、因为快递方面的不可控因素,3D外壳实物并没有如期而至,我会将3D外壳注意事项放到“七、实物制作注意事项”而3D文件会放在“附件”放出;外壳的实物后面会想办法补上
3、部分细节待完善
一、前言:
感谢立创开发板和芯源半导体提供本次学习机会!
感谢提供教学文档和教程视频!
感谢嘉立创的20元3D券,50元器件券,50元彩色丝印券,30元面板券!
本开源工程描述含有:
【一、前言】
【二、功能介绍与使用说明】
【三、参考资料与复刻建议】
【四、硬件原理学习笔记】
【五、原理图与PCB绘制注意事项】
【六、软件例程学习笔记(官方的几个个例程,包括对代码的理解、例程变动了哪些代码)】
【七、实物制作注意事项(元件购买、彩色丝印、3D外壳、面板、焊接顺序、实物调试)】
【八、复刻过程中的问题解决】
【九、附件目录(即介绍目录中有哪些内容)】
【设计图(原理图总图和PCB总图)】
【附件】
注:
(1)“硬件原理学习笔记”里重点为电压电流采样原理,此外我还整理数码管显示的4个具体实例进行一个小拓展
(2)“软件例程学习笔记”还额外附加了CW32和STM32的GPIO和定时器的配置在软件方面的区别的对比
二、功能介绍与使用说明:
1、功能介绍
基于CW32F030C8T6(地文星)跟随立创与芯源半导体官方复刻数字电压电流表。供我们初学者学习使用。电压测量范围建议为0~30V(超过30V对初学者比较危险),电流测量范围0~3A
2、使用说明
(对于新的板子,正式使用前要进行调试,调试方法参见本开源描述的“七、实物制作注意事项”中的“实物调试”,这里只写调试后的使用)
当调试完成(按照官方例程代码实验九的标定方式可以完成),电压电流测试都没问题,则可以在XH2.54 3P的插口(TGND与T_V之间的插口)引入外界电压,正放时左针接GND,右针接VCC,中间的针可以为整个板子供电;
此外,调试完成后还可以在CH3.96 2P直插处引入外界电流,万用表具体接法可以参考本描述的“七、实物制作注意事项”中的“实物调试”(这里是不接R0的情况下),接R0的情况下测量电流万用表具体接法可以参考本描述的“四、硬件原理学习笔记”中的“电流采样”
三、参考资料与复刻建议:
1、详细资料(嘉立创官方)很重要
(1)详细开源文档:(后文说“开源文档”都指的这个)
https://wiki.lckfb.com/zh-hans/dwx-cw32f030c8t6/training/voltammeter-bootcamp/voltammeter.html
(2)B站免费录播课
搜索UP主:立创开发板,搜索关键词“电压电流表项目”即得,与开源文档教程相辅相成
2、建议
像我一样的小白将开源文档和B站录播课一起看,因为二者十分详细,各有测重
四、硬件原理学习笔记:
以下分各个模块,以官方文档和官方B站录播课为依托,结合我自己的部分思考再次分析每个模块:
【供电电路】
供电电路如图:
对于供电电路的分析,官方的文档从“降压芯片”“滤波电容”“防反接二极管”“串联小电阻”“PCB绘制GND单点接地”5个知识点进行介绍,此处我结合文档和录播课进行总结:
1、降压芯片:
(1)选择SE8550K2-HF,而不选择AMS1117-3.3(或AMS1117-5)以及LM7805。
(2)对于AMS1117-3.3V一般应用于5~7V变3.3V;AMS1117-5V一般应用于7~12V变5V;而本次数字电压电流表的工作范围最高需要达到30V,故不选择AMS1117;对于LM7805最大可将35V转为5V,但当电流达到1A时这种器件发热严重,故也不选择(当由7~9V转5V且电流几百mA,可使用7805)
(3)SE8550K2-HF选择封装在同类型器件中为大封装,因为大封装散热效果会更好
(4)SE8550K2-HF是一种“LDO低压差线性稳压器”,其原理可以近似理解成串联了一个大电阻进行分压,让功率在其上耗散,最后输出电压就小了,且因为是串联故电流不变,功率的下降与电压下降成正比
(5)项目理论上限40V,实际不要超过36V,考虑到人体安全电压,最大电压按照30V计算,考虑到很多学员较难提供大于12V的电压源,标注是按照5V~12V标注的;本项目工作时电流在15~20mA,电压不超过36V
2、滤波电容:
(1)这里总共5个电容,从种类上分为“电解电容”“陶瓷电容”两种,从位置上EC1单独做滤波,EC2和C1是一组滤波,EC3和C2是一组滤波总共3组;其中EC1之后经过小电组会引入噪声所以后面要再加电容;
(2)电解电容与陶瓷电容的搭配:电解电容目的是对波纹进行滤波,其为大容量,滤除低频波;并联小容量陶瓷电容,滤除高频波;
(3)电解电容在前,先将低频但可能大幅的纹波消除,陶瓷电容再将高频但小幅的波纹去掉;
(4)这里电容就像电荷缓冲池,电流需要增加时电容释放储存的电荷;
(5)用于滤波的电容不需要很精确,±20%是可以的,其耐压反而更重要,需要留有裕度;
3、防反接二极管:
(1)原理图里的D4是防反接二极管使用肖特基二极管EN5819,因其正向压降小,故串联时影响小(即正常接入时可以无视它),反向耐压高(即反向接入电源时不会立刻击穿);
(2)防反接还可用并联反接二极管;
4、串联小电阻:
(1)原理图上的R14是一个串联小电阻,次要功能是分担LDO上为了降压而耗散的功率(本质还是串联电阻分压)
(2)充当保险丝,最多烧他一个,应该使用1/8W的(我买成1/4W的了),不会烧短路而是烧断路,从而前后隔离
(3)它毕竟不是保险丝,没有高级保险丝的一些性质如自恢复,如很快断开
5、PCB绘制GND单点接地:
(1)由上图可以看出,我标注了3个单点接地,而且将地线的走法画得比较夸张,可以看出对于GND,应该是C1的GND直接连接到EC2的GND,C2的GND直接连接到EC3的GND,最后将EC2的GND直接连接到EC3的GND;
(2)对于“供电电路”来说这里是“串联单点接地”,但是从整个PCB板子的角度来看是“混合单点接地”
【MCU电路或者开发板电路】
在B站的硬件录播课中,讲了从芯片起步设计外围电路应该从哪儿找资料,而我们这次使用的是最小系统板和扩展板的形式(扩展板只焊接两排排母,核心板焊上排针后随时插取)
上面两个图中左图是官方原理图的核心板插座,右图是我的原理图的核心板插座。二者的区别在于官方画的原理图其实是2个2.54mm的20P排母,因为如上文所言扩展板上的元件并不是核心板,而是与其相连的2个20P排母
但这样做的不足是,在画PCB的时候无法确定两个排母的相对位置(因为要与核心板匹配),与其自己找相关尺寸数据,不如直接在原理图上使用地文星(主要是立创商城上有现成的图案和封装),而且地文星的封装上的焊盘可以直接插上20P排母,这样既方便又省事。
官方原理图中的是短接标识,我之所以没用是因为引脚按照官方这样标注会有报错,且因为网络标签PB5到PB9,PC14,PC15因为没有用到会有DRC报错,所以我自己在画原理图的时候就略去了。此外主控板的PB15引出的RES并没有在其他地方用到,于是我给删了
最后,官方对于MCU芯片选型和外围电路相关的B站录播课的笔记如下:
- 芯片选型【以CW32举例】
(1)宽工作温度
(2)宽工作电压(高上限有利于降压时减少功耗损耗,低下限有利于用电池供电时延长电池寿命)
(3)超强抗干扰
(4)12位高速ADC,±0的LSBINL,11.3的ENOB,拥有多种参考电压
(5)市场上很多电流电压表都用51单片机的增强型10位ADC,精度不如12位,有的芯片虽然ADC精度可达到16位,20位,24位,但速度很慢
(6)此外要考虑供应的稳定,芯片渠道,价格稳定性 - 拿到MCU芯片,怎样设计最小系统:
(1)找到芯片资料,如whxy.com
(2)滤波电容容值之类参见“电气特性”,其中VDD(VCC),VSS(GND),VDDA(analog),VSSA(AGND),一般VDD和VDDA相连
(3)“开发板资料”可以看见外围电路原理图
【电压采样电路】
1、电压采样原理:
为电阻分压,由图可知,重点分析电阻选型,然后分析二极管的作用(电容用于滤波,这里不细究)
2、电阻选型:
逻辑如下,首先明确,为了避免超过人体安全电压,最好预设测量的最大电压不超过30V;其次,为了测量准确性CW32使用参考电压为内部参考电压,有1.5V和2.5V可选,其中考虑到电流采样,这里选择1.5V为参考,即1.5V,即,那么先确定R7的阻值,因为不需要测电流,故选大电阻,以免发热影响阻值,故这里R7选择的是10kΩ,那么R8为什么不选择190kΩ?因为要以能测30V为目标要留有裕量,所以R8要选大一些,那为何不选200kΩ,其实190kΩ和200kΩ都不是那么常见的电阻,相比之下220kΩ更常见,也更符合要求
3、补充:
一般使用E24系列电阻,5色环电阻一般精度±1%,4色环电阻一般精度5%~10%;
录播课里说,BOM里电阻都是±1%,这是为了使用方便,本来可以因地制宜分±1%和±5%等的,但是为了避免新手把该用高精度电阻的位置焊接成低精度的(必将容易弄混),所以干脆都弄高精度的了(实际上低精度的位置用高精度是可以的,反之不行,另外1%精度足够,0.1%精度不划算)
4、二极管作用:
电压采集电路的开关二极管是为了防止测接高压,为正向钳位,当接入电压过高导致ADC输入大于5V时,可能会超过IO口输入极限损坏单片机,这时正向钳位二极管导通,将ADC输入口的电压钳制在5.7V(多出来的0.7来自二极管),此时这里的电压由二极管决定而不由分压电阻的比例决定,让此处电压不超过5.7V;1N4148是高速导通开关二极管(与前文所说的肖特基二极管不一样),有利于让高压的影响时间尽可能短;
5、电压采样电路那里的两种分压电阻比值不同的电路
是为了能让电压测量拥有多个档位。
这里分多个档位总体有两个方式:一种是通过更改ADC的参考电压,另一种是通过更改分压电阻的比值。下面通过控制变量法来解释两个方式:
对于第一种方式来说,当分压电阻比值不变的情况下,当ADC参考电压从1.5V切换到2.5V乃至3.3V时,可输入的电压范围也会变大(Vin≤Vref),但因为都是将电压分为4096份(12位精度,2的12次方为4096),所以精度会降低(但为了提高测量范围,精度降低是没办法的);对于CW32拥有4种参考电压,只是在本项目为了精准,建议选择1.5V或2.5V,其中又考虑到电流采样,建议选择1.5V,由此引出第二个方法。
对于第二种方式,当参考电压不变时(比如1.5V),将分压电阻阻值的比值改变也会改变测量范围,这点好理解。那么其怎样影响测量精度?假设实际要测量的电压在1.9V左右,若要根据10/10+220的分压值,则实际输入单片机的电压大约在0.0826V左右;而若是10kΩ和10kΩ的分压,则是输入的电压值为0.95V。虽然因为都用的是1.5V的参考电压,似乎测量精度应该一样,但实际上0.0826V的测量不如0.95V准,因为太低了。
【电流采样电路】
1、R0电阻的选型
(1)R0为1W,因为i^2*R=9*0.1=0.9W
(2)为什么是0.1Ω?如果阻值大了,同样3A的电流流过,功率增大,发热增大,发热会影响阻值,而且需要找最大功率更大的电阻;
(3)如果阻值小,则上面的电压降很小,直接传给ADC则分辨率很低,另外因为0.1Ω上最大电压为300mv,所以ADC参考电压使用1.5V要比2.5V更精准
(4)这个电阻小于0.1Ω也不是不可以,但需要加运算放大电路进行放大后再输入给ADC,这里为了避免硬件开销把运放优化掉了
2、串联1kΩ的R9的作用:
保护ADC引脚,减少瞬态电流对ADC性能的影响,且其与100pF的C6构成了RC低通滤波器
3、R0刚开始是不焊的
这里在下图先放两个R0焊上后的两种使用方式:
那么当R0不焊的时候,应该怎么做呢,这时就要说到原理图中的“模拟电流测量的标定与校准”
对于上面两个PCB的电流走向图,其原理图对应下图:
而当不接R0时,其原理图对应下图:
而不接R0时它的PCB上的电流流向是怎样的?如图:
如上图,白色箭头表示的就是此时的电流通路,浅蓝色箭头则表示从点位器分压点处获得电压,由图可知,获得此时此处的电流需要获得浅蓝色箭头处的电压,然后将电流计算出来,可知此时需要接电压表,红色笔头接TI+,黑色笔头接TGND
【按键电路】
文档里面提到了这一句:
由下图可以看出硬件结构对软件编写的影响,以下是从别的工程找来的两种按键的电路,一种如下图左,是含有上拉电阻和消抖电容,此时在软件上不需要将IO口配置成上拉,也不需要写消抖程序;相反,如下图右这种情况,既没有上拉电阻,也没有消抖电容,就需要软件给IO口配置上拉电阻,以及编写消抖程序。
下图是本次电压电流表项目里的按键,可以看出其属于没有外接上拉电阻和消抖电容的情况,因为其一端接IO口,一端接GND,当按下的时候IO口收到低电平,而配置为上拉还是下拉取决于未按下时应该的状态,由上文可知,未按下应该为高电平,故IO口应配置为上拉模式。
【数码管电路】
在本次训练营和上次盛思锐温湿度检测仪训练营中都使用到了数码管,温湿度那一次的基础区一等奖的大佬还专门对数码管电路做了改进,此外最近实习在用51单片机的时候也用到了数码管,这里总结一下它们(以下都以共阴极数码管为例):
第1种:本次训练营将两个3位数码管在程序眼光上看作6个“地位平等”的“位”进行操作,即6个“位”共用从A到G再到DP这八个IO口进行段码控制,且每个“位”分别用一个COM进行位的控制,共使用了14的IO口。优点是简单便捷框架清晰,缺点是使用了大量的IO口。但因为本项目IO口足够用,所以这样就可以了,可以理解为“软件资源换硬件资源”,如下图
第2种:上次盛思锐温湿度检测仪训练营的官方硬件布局是使用了3个74HC595对2个3位共阴极数码管进行控制,分别控制第一个数码管的段码,第二个数码管的段码,两个数码管的位码。优点是相比方法1,少用了5个IO口,缺点是多用了3个595芯片,可以理解为“硬件资源换软件资源”,如下图
第3种:我这几天实习时见到的一种方式,用4个74HC595级联的方式控制4个1位数码管,只需要1个IO口将数据串联输入到级联的4个74HC595中,每32位进行一次锁存输出,同时控制4位数码管。而4位数码管的共阴极则不进行控制,直接接地。优点是只需要3个IO口(串行数据,时钟,锁存信号),缺点是需要4个74HC595才能控制4位数码管,也是一种“硬件资源换软件资源”。但考虑到这种方式是用于IO资源稀缺的51单片机的项目上,可以说恰如其分。如下图
第4种:是上次盛思锐温湿度检测仪训练营基础区一等奖大佬古来夏Rhys对官方的接法进行的优化,可以理解为“第2种”用IO口操作COM(而不是COM直接接地),与“第3种”对74HC595进行级联来操作的结合。相比第2种方法,在同样控制6位数码管的情况下可以少用1个74HC595,且少用6个IO口(从9个到3个,前提是不用595的使能引脚和清零引脚);相比第3种方法,在都只用3个IO口的情况下,可以少用2个74HC595且多控制2位数码管。即这位大佬将软件资源和硬件资源做了一个很厉害的平衡!如下图:
【用于电压测量校准的TL431电路】
(1)这部分电路为什么说是“校准”或“基准”,因为它既可以输出一个大约2.5V的电压作为一个基准电压(适用于使用其他不像CW32这样有2.5V基准电压的MCU如STM32);其也可以用来校准类似于STM32这种芯片的3.3V基准电压准不准的手段
(2)稳压为什么不用稳压二极管?因为其精度必定不如TL431
(3)R13阻值选择来源于TL431的灌电流能力
(4)接下来几张图来描述TL431的工作原理、R13选型原理和带负载电流的计算和理解
五、原理图与PCB绘制注意事项:
在官方文档和视频录播课中,有关PCB绘制的的要点被分散到了几个部分。对于PCB绘制的基础方法,大家参考B站立创EDA的相关教程即可,现就此次项目之中的特殊要点做一个总结:
1、原理图:
- 对于原理图,主要注意尽量在画电源图标的时候朝上画,画GND图标的时候朝下画,保持工整
- 有些元件图标长相相似甚至相同,此时容易弄错(比如我直到焊接前才发现把两种不同的二极管弄错了),建议在器件周围把器件符号标出来或者检查器件的编号
2、焊盘:
- 官方建议对于插件,焊盘可以使用椭圆焊盘方便手动焊接时锡容易附着,此外在比较靠近的焊盘可以用丝印隔离(丝印本身有高度),不过我因为时间比较紧张,所以并没有做这方面的处理
- 电压电流采样部分(也就是标注TI+和TA的两个香蕉头母座以及与它们进行铜皮连接的焊盘们),焊盘与铜皮的连接方式应该由默认的发散改为直连,否则无法通过大电流,电机焊盘在右侧属性栏最下部把“热焊”的“通用”改为“自定义”后选择“直连”
3、GND:
官方建议本次项目的GND不使用铺铜,而是使用单点接地的铺铜方式,其中“供电电路”官方说是串联单点接地,而对于整个板子而言可以算是“混合单点接地”;
为什么不铺铜?请看下图:
可以看到图中,我把所有GND都高亮标注出来了,其中白色箭头所指的这次板子上测电流的2P座子CH1就有一个脚接的是GND,这里的GND在设计上是要过大电流的,属于“功率地”,上面会有很大的电流波动,所以其是通过R0的GND绕路连接上整个GND网络上的,而不是直接与左边元件的GND就近相连。同时从这张高亮图中也可看出左侧的元件遵从单点接地的原则,而不是就近连一起就行了。
4、极性元件:
官方建议所有极性元件在原理图和PCB上的方向要尽可能保持一致(当然若是实在无法一致也要尽量保持美观)比如本次所有电解电容负极朝右,所有二极管二极管负极朝左,这样不仅便于阅读,也便于手动焊接时不将元件焊接错。
5、走线:
之前的项目中一般信号线线宽10mil,电源线线宽15mil;在这里则是普通信号线(包括ADC采样的信号线)10mil,电源线则20~60mil
6、PCB情况(正面图、反面图)如下图:
六、软件例程学习笔记:
我将官方文档里每一步的例程代码统一下载,把原汁原味的部分放到了“文档教程-官方文档”,此外还有一个“文档例程-略有修改版”,与前者的区别在于我会改动一些功能,一些注释,以上两者均可以在开源文档末尾的附录里找到
“实验一 点亮LED灯”
那里我为了测试LED是否能够正常翻转而添加了一个简易的软件延时(分别用电脑通过DAP给板子供电,以及通过12V电池给板子供电,可以明显看出LED的亮度不同,后者亮度大于前者)
“实验二 按键检测”
的例程代码中,对于按键消抖没有使用延时,参见下面两个图:
这种做法的合理性在于,不加延时避免了delay对其他程序语句的干扰(程序执行delay的时候其他程序无法进行),但是有两个缺点:
第一个缺点是,对于没有外接消抖电容的结构,不加延时只进行一次判断容易因为按键的硬件方面的抖动而出现多次触发,增加误判概率;
第二个缺点是,此处判断按键是否按下是用的“轮询”而不是“中断”的方式,同样也会挤占其他程序的运行(但是当初我看江科大的网课上说普通按键用轮询就够了,因为用中断也是一种对定时器的浪费,编码器哪种一般才用外部中断)
不过话又说回来,我之前看到有程序虽然把判断按键按下放在了中断里,但是仍是用delay延时进行消抖,即意味着中断里出现了延时函数,不知道这样规范不规范,有没有隐患,但之前我自己用的时候应用于普通场景时问题不大。
此外,经过查阅资料,我发现还有一种思路是“可以引入一个计数器或状态机,通过一定次数的稳定状态来决定是否真正触发事件。”由CW32官方写的教程里有一句:在监测到IO电平发生变化后的一小段时间内快速采集IO的电平状态,如果这一小段时间内IO电平全都属于有效电平,则认为按键已按下(这种利用数学进行消抖的方式达到了对数字信号的筛选作用,所以他也是一种简易滤波器)以后我有空再尝试吧
“实验三 数码管驱动”
的例程代码中,其他的都好理解,理解的难点就在Seg_Dis函数中的以下语句:
这里的switch用于进行段选,这里截出来的case 0是对于数组中不同显示情况下,第0个段码“即段码A,即数字8的最上面那一个横”所应该显示的内容
其中(Dis_Value >> i) & 0x01又是关键,其作用是先将Dis_Value的值右移i位,然后通过按位与的方式只保留最低有效位(即LSB,Least Significant Bit);换句话这个语句的作用是提取二进制数的某一位;
具体的操作原理是先由Seg_Dis函数传递的参数Num知晓即将显示的数字(同时也是段码数组的下标,这点很巧妙),然后将对应的段码给变量Dis_Value,然后通过for循环对Dis_Value的8个位分别安排其对应的段的电平高低
“实验四 数码管动态显示”
主要介绍CW32的定时器配置,以及数码管相关的3个经典函数,我之前做数码管动态显示的时候没有要用到定时器,这次正好学习。这一个例程一个学习点是对三位数的三个位的提取,巧妙使用了“%”和“/”
“实验五ADC采样显示”
1、ADC通道通道配置的顺序可以看到是:
(1)结构体定义(注意ADC相关有2个结构体,还有一个“序列通道结构体”)
(2)打开时钟
(3)GPIO结构体初始化(注意这里是模拟输出,且还有专门一句函数用来“使能模拟引脚”)
(4)ADC配置结构体初始化(注意初始化之前还有一句ADC默认值初始化)
(5)ADC序列通道结构体初始化
(6)清除ADC所有中断状态、ADC使能、ADC转换软件启动命令
2、其中可以看出CW32的特色之一
就是ADC配置结构体初始化的时候可以选择内部参考电压,官方还在旁边写了注释提示【在检测电压较小时可以通过选择低参考电压从而提高精确度】
3、关于ADC的一个重要核心公式
即根据ADC分辨率和ADC获取的值来转换出实际电压如下:
这里的“实际电压”是指进入IO口的实际电压,外部输入的实际电压还要根据基础的串联电阻分压公式来计算
- 数码管部分因为要将显示分为10V以下与以上(小数点位置不同),相比“实验四数码管动态显示”的对应函数有了不同:不再只设置“百十个”3个位,而是设置“千百十个”4个位,对于10V以上的输入显示“千百十”,对于10V以下的输入显示“百十个”,如下图:
- 可以看出这里的“千百十个”是将数值扩大100倍后的数,因为要符合数码管的显示方式,比如34*100=1234,显示为12.3而3.21*100=321,就显示为3.21;
- 此处先得出“千位”以进行下一步的判断,接连使用“/”符号和“%”符号,前者是将所要位数之后的位数去掉,后者是将所要位数之前的位数去掉;
- 对于前者要在第2位加小数点,对于后者要在第1位加小数点,这里是因为储存代码的数组储存了“0”~“9”和“”~“9.”的段码,后者比对应的前者的下标多10;初次之外还可以通过对“X”的段码直接进行“与”或“或”操作来得出“X.”,比如“4”的段码是0x66,即0b 0110 0110,“4.”的段码是0xe6即0b 1110 0110,可以看出最高位表示小数点“.”(这里8位的顺序是DP/G/F/E/D/C/B/A),因此可以直接通过“0x66 | 0x80” 的方法得到0xe6
- 对于本例程的代码,我下载下来的工程与文档里的示例代码略有不同,如下图:
- 上面四个图,黑色背景为“官方文档里讲解的代码”,白色背景为“实际下载的例程的代码”,区别已在图中标注,白色图左图的Dynamic_Display应该放在if里而不是外面;
- 其中Show_TimeCount之所以说是为了避免数据刷新过快是因为过快则数码管变成一堆残影;
- 另外实际电压值的计算中使用了变量和宏定义的方式进行计算而不是直接使用常量,有利于复用;
- main函数中参考电压应该是5V,ADC_REF_VALUE则为1500,扩大了1000倍,此后在四舍五入的时候顺手除以了10,故最终是放大了100倍后交给数码管
“实验六 均值滤波”
- 这部分大家一定要看官方的参考文档,里面提出了几种典型的滤波方法并给出了适用场景与优缺点
- 我自己在学校内部电赛院内选拔的小车爬坡称重系统中用到的就是几种方法中很基础的“中位值滤波法”,取自定义的N个数据,排好大小后选中值,当时我排序使用的是“冒泡排序法”;电赛控制题常用PID,其中速度环PID对获取的速度值常常使用“一阶滞后滤波法”进行滤波,这里从经验上一般把上次数据权重设置为3,本次数据权重设置为0.7
- 从这10种滤波方法中可以看出一个普遍的点:良好的滤波效果往往会使用大量的代码和RAM,这是一组矛盾
- 官方给的例程选取了“中位值平均滤波法(又称防脉冲干扰平均滤波法)”,将连续N个数据中最大值和最小值去掉后取平均值
- “文档中的代码”相比实验五的一个变化是把Btim的中断服务函数中的固件库函数ADC_GetSqr0Result换成了能得到连续20次ADC读取值的自定义函数Get_ADC_Value;如下图:
- 均值滤波的主体函数没什么好说的,都是一眼能看懂的代码
- 主函数部分,相比“实验五”对于数码管刷新的计时从用Btim计时转换成了由系统滴答计时器systick来计数,如文档所说,需要在RCC_Configuration放一句InitTick(64000000);此外,而对ADC的值的处理要放在均值滤波之后
“实验七 六位数显的电流通道采集电压显示”
1、实验七在ADC初始化方面相比实验五,流程是差不多的
实验七的代码中有了GPIO_InitTypeDef GPIO_Init_Struct;但却没有以下几句:
GPIO_Init_Struct.IT = GPIO_IT_NONE;
GPIO_Init_Struct.Mode = GPIO_MODE_ANALOG;
GPIO_Init_Struct.Pins = GPIO_PIN_10;
GPIO_Init(CW_GPIOB, &GPIO_Init_Struct);
(1)原来是GPIO相关的初始化放在了main.c文件里的函数KEYGPIO_Init()里统一进行了
(2)此外相比实验五,实验七的ADC初始化函数用了4句“使能模拟引脚”,把本项目要用的4个ADC通道全部配置了(结合上下文推测这一段是从最终代码中节选出来的)
(3)最后,实验七的ADC初始化函数里有部分的注释没有改回来,比如ADC_ClkDiv这里是128分频,而不是实验五的4分频,但是后面注释还写的是4分频,但问题不大
(4)ADC初始化函数别的部分没有改动
2、此外文档里有些部分没有提到
比如main.c文件中的函数RCC_Configuration():
(1)RCC_Configuration()函数里的RCC_SystemCoreClockUpdate(64000000)变成了RCC_SystemCoreClockUpdate(48000000),同时多了一句RCC_PCLKPRS_Config(RCC_PCLK_DIV8);
(2)与“实验六”把InitTick(64000000);写到了RCC_Configuration()里不同,“实验七”专门设置了一个函数RCC1_Configuration()来处理相关代码
(3)BTIM1文件中对于Btim1的初始化,计数周期由8000改为6000但是仍然是1ms触发一次定时器中断
3、main函数中:
(1)将数码管Seg,定时器Btim和ADC的初始化函数的后缀从Configuration简化为Init
(2)while(1)相比实验六也发生了变化,如下图:
可以看出整个程序在标志位BrushFlag的控制下分为两个部分,每隔300ms进行一次电压采集,同时紧接着就是一次更新显示
(3)这里的计时变量timecount不是像实验六那样使用滴答定时器来计时,而是跟“实验四”“实验五”一样在Btim1的中断服务函数进行计时
4、再分析“实验七”的数码管相关文件:
(1)其中Close_Com()函数没有变化
(2)因为“实验七”将2个3位数码管都用上了,而不像前面的实验那样只用到1个3位数码管,所以要同时显示6位数据,故函数Display_Refresh()的num范围从0~2变成了0~5(这里官方案例代码写的是0~6,我觉得应该是0~5),其他没有变化
(3)数码管初始化函数把函数名从Seg_Configuration简化为Seg_Init,此外GPIO的配置代码也做了简化:初始化GPIOA后再初始化GPIOB,只需要更改GPIO_InitStruct里的Pins,而不需要改Mode、IT和Speed
(4)函数Seg_Dis()也几乎无变化,只是在switch(Pos)的每个case里仅把对应的COM打开,而省略了关闭其他COM的代码,因为Seg_Dis()是在Display_Refresh()里调用的,而每次调用Seg_Dis()前都会先调用Close_Com()来关闭所有数码管,所以可以删除上文所述代码
(5)“实验2~6”中的数码管显示函数Dynamic_Display在“实验七”里变成了DisplaySETV,内容不变,这一部分是为了显示电压,显示电压只用到1个3位数码管,所以仍然延续了原来需要将电压按照10V以上和以下进行XX.X显示或X.XX显示的思路
(6)“实验七”里还有一个Display函数,内容和DisplaySETV一模一样,应该是从整体代码进行节选的时候代码没删除干净
(7)此外“实验七”的数码管文件里还剩下两个函数:DisplayI和DisplayValue,分别如下图:
可以看出DisplayI函数用于显示电流,且相比电压在上面那个3位数码管显示,电流显示在下面那个数码管,这里也没有进行四舍五入等操作,且DisplayI函数对于自己的4个局部变量也都没用上;而对于DisplayValue函数,是同时将2个3位数码管都用上,因此位数除了个、十、百、千之外还有Wwei和SWwei(“万位”和“十万位”),可以看出在“万位”还加了小数点,但不知道为什么
- 对于Btim1的中断服务函数,“实验七”又把它从中断文件放到了main文件中,里面多了3个变量:keytime,timecount1,ledcount但函数却没有用到keytime,timecount1(而是用到了全局变量timecount)和原有的Cnt变量,Display_Refresh();从每3ms调用一次变成了1ms调用一次,此外ledcount变量用于让白色的LED1每1s翻转一次;综上可以看出这部分应该也是从最终代码里节选出来的
- “实验六”和“实验七”的函数Get_ADC_Value内容一样,只是变量名变了
- “实验七”把“实验五”和“实验六”中main函数while里对ADC数据的滤波和计算的内容专门放在了Volt_Cal函数里,如下图:
由图可以看出这部分计算相比“实验五”和“实验六”,没有进行分压电阻的计算和四舍五入的处理
“实验八 压流同时显示”
- 对于ADC初始化函数ADC_Init,“实验八”相比“实验七”在“序列通道结构体”的配置中,在通道12的基础上多配置了通道11,同时序列配置从序列0变到了序列1
- “实验八”相比“实验七”,数码管文件Seg_Dis中没有新增内容,反而删除了函数DisplayValue(即显示“个、十、百、千、万、十万”的函数)
- “实验八”相比“实验七”,用于获取ADC值的函数Get_ADC_Value在原来只获取序列0数据的代码ADC_GetSqr0Result(&Volt_Buffer[cnt]);基础上又添加了获取序列1数据的代码ADC_GetSqr1Result(&Curr_Buffer[cnt]);
- BTIM1文件无变动,计数周期还是6000
- c文件中RCC1_Configuration、RCC_Configuration、KEYGPIO_Init、BTIM1_IRQHandler和Mean_Value_Filter都没有变化
- c最主要的变化是函数Volt_Cal,如下图:
(1)函数Volt_Cal定义了局部变量t和KT1,但是却没有用到
(2)可以看出“实验八”像“实验七”那样专门在函数Volt_Cal计算,且重新加上了“实验六”中就已经有了四舍五入;此外在开始的均值滤波要对电压数据和电流数据分别滤波;
(3)对于代码V_Buffer = (V_Buffer * ADC_REF_VALUE >> 12) * (R2 + R1)/R1;
在前文已经说了,这里的宏定义ADC_REF_VALUE为1500,比参考电压1.5大了1000,然后再四舍五入的阶段再÷10,从而比真实值大100倍,后来通过在数码管倒数第3位添加小数点来显示真实值,这么做的本质原因是对于10V以上电压和10V以下电压需要用不同格式显示
(4)对于代码I_Buffer=I_Buffer * ADC_REF_VALUE >> 12;
可以看出相比电压的计算,这里只是将电流检测接口检测的电压的真实值进行计算
- main函数的唯一变化是在原来的只显示电压的基础上加了一句显示电流的代码
“实验九带有标定功能的数字电压电流表”
1、main文件
(1)main函数
实验九相比实验八,变化如下图
上图的三个函数都在main.c文件中,将于下文一一解释:
(2)校准前电压读取函数:
上图是官方给出的函数,我添加注释后如下图所示:
可以看出这个函数的主要目的是进行一次校准检查。如果未校准,则计算并保存理论值;如果已校准,则使用存储的值。这样的设计通常用于需要定期校准的设备,以确保其测量的准确性和可靠性。
对于这个函数需要关注3处:闪存读取函数flash_readme();对X15等4个变量的计算,以及保存结果函数save_calibration();有关“闪存flash”的部分这里放在后文讲flash文件时再说,这里先说明理论值的计算,对于函数read_vol_cur_calibration,分析如下:
可知该函数中的计算是当没有进行校准时对X05,X15,IX05和IX15分别进行运算,此时的计算因为没有实际测量外部的值,所以仍是理论计算,可以看作是为后续存放校正值的变量给一个初始化的值;此时根据如下ADC公式:
其中分辨率是4096(即2的12次方),参考电压是1.5(内部参考电压1.5V)
这里以X15的计算为例,其为15.0/23/1.5*4096,结合上文的ADC公式可知,15.0/23即为实际电压;这里的23是怎么来的?这里参考前文硬件笔记里“电压采样电路”的电路图可知,要测量的电压实际上是先经过分压,缩小为原来的1/23后才输入到ADC中,于是这里的X15计算出来的值指的是当以1/23分压的情况下(即1/23档位情况下),理论上ADC采样后获取的值;
X05的计算也是同理,只是把15.0替换为5.0而已,而IX05和IX15的计算本质上也是一样的(这里IX05是0.5A不是5A),注意这里IX05的计算式为0.5*0.1/1.5*4096,这里的0.1是怎么来的?为什么是“*”而不是“/”?这里参考前文硬件笔记里“电流采样电路”的电路图可知,要测量电流的本质是测量100mΩ上的电压分压,再用欧姆定律解出电流,所以这里0.5*0.1也是根据欧姆定律算出当检测到0.5A电流时,0.1Ω电阻上应该有的电压
(3)斜率计算函数:
可以看出斜率计算函数分别根据之前算出的5V、15V、0.5A、1.5A的标定值来计算斜率,其中电压部分只算了5V到15V的斜率,这里没有计算15V以上的情况,而0到5V因为默认0V是准的(即实际0V时测量也是0V),所以0到5V的斜率可以直接用Y05/X05来计算,这里不单独列出
电流部分也只计算了0.5A到1.5A的部分,其余部分原因同上。
(4)电压电流显示函数
电压与电流的显示部分,“实验八”在main函数中只有以下两句:
Display(V_Buffer);
DisplayI(I_Buffer);
而“实验九”的DisplayBuff函数里,应对5种不同的模式是5种不同的显示方式,由官方文档可知以下描述:
总结下来即“模式0”为正常显示,“模式1到4”是标定时显示,结合上图对五种模式的描述,即可看懂DisplayBuff函数,下面解释如下:
模式0:正常显示时,与“实验八”一样调用Display(V_Buffer);和DisplayI(I_Buffer);但是在显示电流之前,先对I_Buffer做了一个限幅,不让其超过400
模式1~4:可以看出这4种情况都是先对Seg_Reg[0][1][2]做一个处理,然后再显示,其中Display函数和DisplaySETV函数的功能都是“显示电压”,区别在于前者是在上面的数码管显示,后者是在下面的数码管显示;
因为模式0要同时显示电压和电流,所以电流在下面数码管显示时电压只能显示在上面的数码管处、而模式1~4标定时上面数码管需要显示当前是哪种模式,所以无论电压还是电流都需要在下面数码管显示,对于电流显示本来就在下面数码管所以一个函数足矣,这里电压显示有两个函数就是应对两个不同的显示位置(这里以后可以优化,因为不需要两个函数,只需要给电压显示函数多加一个参数即可)
对于模式1~模式4中都有的先对Seg_Reg[0][1][2]做一个处理,即对上面那个3位数码管做处理,让其显示当前处于哪种模式。段码的数组如下图:
之前“实验四 数码管动态显示”中有说明,段码数组下标0到9是与“0”到“9”段码对应的,而“0+10”到“9+10”是与“0.”到“9.”段码对应的,而这次专门在段码数组里新增了表示字符“A”的段码;
现在再来看,以模式1为例,此时是5V点位的电压标定,应该显示“5.05”,所以第一位是Seg_Reg[0] =5+10;即“5.”第二位是Seg_Reg[1] =0;即显示“0”即可,第三位Seg_Reg[2]=5+10;又是显示“5.”;模式2~4同理;这里有一个改进方向是,电压标定时显示“S”跟“5”是一样的,可能会被混淆;像电流那样显示“A”就很清楚,因此此处应该对电压以“V”来显示;
(5)校准储存函数
保存结果函数,就是将结果一方面保存在da数组中备用,一方面保存到flash中留待下次上电后直接读取,这里唯一值得分析的flash_erase和flash_write函数放在后文讲flash文件时再介绍
(6)电压(电流)计算函数
实验九的主要功能是引入了电压电流的标定,这里为了分析代码的方便,我先结合官方的文档对标定相关做出了以下理解,如下图:
理解完上图的步骤,电再进行代码的分析如下:
电压(电流计算函数)Volt_Cal()在“实验八”中就有,但是“实验九”的该函数有新增内容:
先看图中第一个框中的if-else,这里的V_Buffer是经过均值滤波后的当前电压实测值对应的AD值(也就是还没经过计算,范围在0~4096),对应到我上图手写笔记的右下角的那4步,此时是第3步,也就是这个if-else的目的是判断此时的X应该落在哪一段折线上,这里因为是按照0V,5V,15V这三个点来判断,也就是只有“0到5”和“5到15”这两段折线,所以这里只用一个if-else来判断,当V_Buffer大于X05,也就是对应“5到15”这段折线,给出代码:
t=V_Buffer-X05;
V_Buffer=(K*t+Y05)*1000;
关于上两句的代码参考上图手写笔记的中间那个图和下面那个图的右侧的文字解释,唯一需要解释的是V_Buffer最后还有一个“*1000”,理解这一点需要结合下文有关四舍五入的代码:
if(V_Buffer % 10 >= 5) V_Buffer = V_Buffer / 10 + 1; //10mV为单位
else V_Buffer = V_Buffer / 10;
比如前面的if-else那里应该测出来是6.157V,但是显示只能显示3位数,这时考虑到四舍五入,因为有个0.007,最终的显示应该是6.16而不是6.15,此时对6.157乘个1000倍为6157,后面的代码对6157 % 10得到7,然后V_Buffer = V_Buffer / 10 + 1后相当于616=615+1,不仅四舍五入了,此时616比真实的6.16大100倍(此处不需要再除以100因为小数点由数码管考虑),这时注释后面标注的是“10mV为单位”也就可以理解了
综上,在“实验九”中,四舍五入的处理比之前的写法更精妙了
理解了电压部分的处理,电流部分的处理也就同理可得了,这里不再赘述;
(7)中断服务函数(一方面有定时器中断,一方面有外部中断)
中断服务函数因为内容太长,这里先把按键外部中断的三个if折叠后先看整体结构,如下图
上图中的中断服务函数整体分为两个部分,橘色框内的部分和框外的部分;
框内的部分是“定时功能”,包括:
- 1ms进行一次ADC采集
- 1s进行一次LED翻转提示
- 1ms进行一次数码管扫描
这部分跟“实验八”的代码没有区别,此不赘述,框内唯一的区别是static变量中多了三个变量:keytime、keytime2、keytime3分别在KEY1、KEY2和KEY3的对应代码中使用
框外的3个if是“外部中断功能”,PB12、PB13和PB14分别对应KEY1,KEY2和KEY3,下面分别解释:
如上图对应按键KEY1,根据官方文档描述KEY1的作用为:切换显示模式
这里的keytime就是一个普通的计时变量,用法同前文的其他计时变量一样,此不赘述,这里它的目标是做一个消抖,也就是说,当按键KEY1被按下后(即PB12为低电平时),会每隔1ms进入一次这个语句,让keytime的值加1,直到连续100次(也就是持续100ms)PB12都为低电平(因为只要有一次不是,keytime就会置0并重新开始计算),则认为按键已经稳定,此时进行下一步操作。
KEY1按下判断成功后,令Mode的值加1,并且Mode的值会在0到4循环(对应“模式0”到“模式4”),之后会将BrushFlag置1,这里BrushFlag是一个标志位,用于main函数中,当BrushFlag为1时会调用函数DisplayBuff,显示当前模式的静态字符和此时待标定的值;调用结束后BrushFlag置0,等待下一次按动KEY1
如上图对应按键KEY2,根据官方文档描述KEY2的作用为:设置对应模式下的参数值,并保存到FLASH;
keytime2的作用与上文的keytime的作用同理,此不赘述;
之后有4个if(这里换成1个switch更好),分别就Mode为1到4这四种情况做出应对,对于X05、X15、IX05和IX15这4个变量,在前文read_vol_cur_calibration函数那里已经说明,如果是未校准过,则计算的是理论的AD值,否则就是校准后的值,而这里KEY2的作用就是按下后将校准后的值作为新的值储存在X05、X15、IX05和IX15这4个变量中;
此时还是以X05为例,先对Volt_Buffer的值调用一次均值滤波函数进行滤波(Volt_Buffer中的值是ADC实时读取的当前值,是随时变化的,此时一定要先在万用表显示未5V的情况下在按KEY2以保存此时的真实AD值)
调用结束后X05已经保存的不是理论值而是万用表辅助之下的实测值,此时在不下电的情况下后续的测量可以使用当前的X05作为基准来校准,但是如果下电,下次就要重新标定,所以引出了下一个要调用的函数……
紧接着调用校准储存函数save_calibration();将X05保存在flash中,这样掉电再上电后程序可以从flash读取上次标定后的值,这样只需要标定一次即可,如果后续发现标定不准确,也只需要再次按照原来的流程,再次按动KEY2即可;
之后连续调用了ComputeK();和Volt_Cal();因为新的5V标定后“0V到5V”和“5V到15V”两段的折线也会改变,而计算新的电压值则需要用到斜率,所以这里需要调用并先调用ComputeK();再调用Volt_Cal();
之后BrushFlag置1的作用在KEY1那里已经描述过,此不赘述
最后Mode置0相当于每次标定结束后立即返回为“压流同显”的模式,好处有2:
好处1:标定后返回“模式0”说明KEY2判定成功,否则从显示上不知道时候成功标定
好处2:节省一个按键,不需要KEY3进行“返回模式0”
如上图对应按键KEY3,根据官方文档描述KEY3的作用为:返回到“模式0”
这里keytime3和BrushFlag同上文,此不赘述
如上文,KEY2已经代劳了标定后会到“模式0”的作用,此时KEY3的作用在于没标定时可以用来返回“模式0”,作用已经比较鸡肋,可以在后续增加的功能中充当新的按动作用
(8)main.c文件中的其他函数
“实验九”相比“实验八”,main.c文件中的以下函数没有变化:
RCC1_Configuration函数没有变化,此不赘述
RCC_Configuration函数没有变化,此不赘述
KEYGPIO_Init函数没有变化,此不赘述
Mean_Value_Filter函数没有变化,此不赘述
2、ADC文件
ADC的初始化函数,相比“实验八”只有红色框处和蓝色框处不一样,本次数字电压电流表项目总共用到了4个ADC通道,根据原理图可知:
- ADC_IN11用于检测电压(先分压到原来的1/23);
- ADC_IN12用于检测电流(限流电阻为1Ω);
- ADC_IN9用于检测电压(先分压到原来的1/2,相当于小量程高精度档位);
- ADC_IN8联通TL431精密可编程电压基准,相当于外界的参考电压
之前的代码里只用到了ADC_IN11、ADC_IN12,用它们即可实现电压和电流的检测,这里增加了ADC_IN9和ADC_IN8是为了后续功能做拓展
蓝色框是因为“实验八”中给ADC_IN11分配的是Sqr0,给ADC_IN12分配的是Sqr1,而这里给ADC_IN11分配的还是Sqr0,给ADC_IN12分配的是Sqr3,本质上没有区别;
(2)ADC值获取函数
ADC值获取函数相比实验八唯一的不同是将ADC_GetSqr1Result(&Curr_Buffer[cnt]);换成了ADC_GetSqr3Result(&Curr_Buffer[cnt]);对应了上文的给ADC_IN12的分配由Sqr0改成Sqr3,此不赘述
3、其他文件
“实验九”的BTIM1文件和Seg_Dis文件相比“实验八”没有变化,需要注意的是“实验八”的Seg_Dis文件中储存段码的数组Seg_Table[21]已经包含了表示电流的“A”的段码;
CW32和STM32部分代码对比学习笔记:
【GPIO配置】
STM32对GPIO的配置代码(江科大版)
CW32对GPIO的配置代码(官方)
- 可以看出二者相差不大,都是使用结构体初始化
- 可以看出CW32版本的RCC初始化是用到了宏定义,而CW32结构体成员专门多出来了一个对中断的配置(此处是无中断)。
- CW32对引脚频率可以设为高频和低频,一般选高频;而STM32则一般也设为几种情况中最高频的模式,这里直接标注出来了,为50Hz
【定时器配置】
上图是STM32F103C8T6对于定时器定时中断的初始化代码(没有包括NVIC的其他配置)
下图是CW32F030C8T6对于定时器定时中断的初始化代码
下图中左图是STM32F103C8T6定时器的初始化结构体,右图是CW32F030C8T6的
1、可以看出CW32的Prescaler同时集成了STM32的ClockDivsion和Prescaler
2、我找的左图是STM32高级定时器的结构体,所以还有一个重复计数器
3、左图的“计数器模式”和右图的“工作模式”是不一样的
七、实物制作注意事项:
【元件购买】
1、开源文档描述最后有自动导出的BOM可以一键导入,但都是英文,不够直观,因此另整理出如下BOM清单提供给大家,在立创eda专业版顶端菜单点击放置,然后点击器件,输入表格中的供应商编号,就可以唯一对应这个元件。此外附件上还有官方推荐的BOM。
2、本次项目的轻触开关(按键)、2.54mm排针、发光二极管、1kΩ和10kΩ电阻使用现有的元件(从上上次简易数字示波器训练营那期剩下来的)(毕竟按键能按就行,LED能亮即可);0.1Ω、10Ω电阻和香蕉头母座购买自淘宝;
3、这里100nF电容用的是陶瓷电容,瓷片电容,上次示波器项目用的100nF的电容则是独石电容,我了解到独石电容耐压值不如陶瓷电容,所以我不敢贸然更换,所以其他元件都是在立创商城上购买的,品质放心有保证。
关于这些电容的种类可以参考:
https://blog.csdn.net/boyueqiu9000/article/details/100961835
4、LED本来准备替换为示波器那一期的,但发现那一期LED规格比较小,瓦数和通过电流都小,保险起见换了两个大的LED,并不是在立创商城上买的,故没有器件编号
5、关于“嘉立创的元件商城购买元器件”的优缺点,可参考上次温湿度检测仪我写的开源描述“五、复刻过程记录 【第3步】元件购买”
6、我给轻触开关配备了上上次简易数字示波器留下来的按键帽,既保护了按键,又提高了美观程度
【彩色丝印】
1、彩色丝印制作可以参考嘉立创B站教程视频(BV号:BV1Ab421J7dy)
2、彩色丝印里那些卡通图标等来自“阿里ICON”
3、部分图标可前往附件下载
【3D外壳】
1、3D外壳制作可以参考嘉立创B站教程视频(BV号:BV1F4421f7qp)
2、打印耗材推荐使用的嘉立创新推出的9600SLA光敏树脂,比之前的材料更白,关键是品质不下降的情况下更便宜!
3、我使用的3D外壳是“上下壳”(嘉立创还有“推盖”形式),一般都是从上到下按照“上壳,PCB,下壳”然后用螺丝将三者相连(一般都是M3,上壳下壳的螺丝柱和PCB的螺丝孔要对准),需要注意的是,如果是像我上上期“简易数字示波器”那样只有3D外壳而没有面板,则从美观上看,建议正面的螺丝柱不要开沉头孔,反面的螺丝柱可以开沉头孔,这样螺丝从反面安装,正面就是完整的;本次是因为我准备在正面安装一个透明亚克力面板,需要在正面固定,所以我正反两面都开了沉头孔
4、螺丝柱可以加加强筋,但前提是根据PCB预估后确保加强筋不能阻挡到元件,解决方法是螺丝柱的属性可以更改加强筋的高度,厚度,长度等尺寸信息
5、对于侧面实体和侧面挖槽,建议对于“上下壳”结构下,每个侧面(以矩形为例)的基准线可以贴着3D外壳但稍微有些距离地平行放置,然后每一侧的侧面实体与挖槽都以那一侧的那一条基准线为基准,好处是便于判断各个组件的几何关系
【面板】
1、面板制作可以参考嘉立创B站教程视频(BV号:BV1cZ421K76S)
2、嘉立创面板制作每次至少要开一个200mm和300mm的板子,无论要打造的面板薄厚,大小,都建议尽量利用整个大板子,因为对于亚克力材质的面板(嘉立创还有薄膜材质的面板),只要开工,哪怕只有一片20mm*20mm的板子,都要花费大概30元,而2块20mm*20mm的板子大概31元,3块32元……因此可以看出,板子制作时多打几片(哪怕都一样)更划算
【焊接顺序】
- 本次项目除了LDO芯片是贴片之外,其他元件都是插件,焊接需遵循从低到高的原则进行,我根据我最终实际用到的BOM表的元件,按照元件由低到高列出以下表格:
- 小白怎样焊接?参照嘉立创B站教程视频(BV号:BV1sJ4m1Y7Zp)
- 注意事项:
金属膜电阻之间,以及陶瓷电容之间长的很像,焊接前电阻可以用万用表测一下,电容看一下标号,免得焊错 - 电解电容,开关二极管,肖特基二极管都是有极性的,原理图和PCB上不要画反是基础,焊接时也要留意丝印上的极性,其中电解电容若是焊错会爆炸
- 建议电烙铁使用刀口,可变温,注意不要被烫伤
- 最后20P排母和地文星要合在一起后焊到板子上,避免焊歪无法安插核心板
焊接顺序(高度差不多的元件在顺序那里标的是并列数字所以会有数字相等的情况):
顺序 |
名称 |
位号 |
器件编号 |
1 |
电源IC |
U1 |
C115012 |
2 |
开关(普通)二极管 |
D1,D2,D3 |
C402212 |
3 |
香蕉头母座 |
无 |
无 |
4 |
300Ω电阻 |
R1,R2,R3,R4,R5,R6 |
C58609 |
4 |
10kΩ电阻 |
R7,R10,R12,R15,R16 |
C119347 C410695 |
4 |
1kΩ电阻 |
R9,R13 |
C713997 C57435 |
4 |
220kΩ电阻 |
R8 |
C119374 |
4 |
200kΩ电阻 |
R17 |
C119373 |
4 |
10Ω电阻 |
R14 |
C138214 |
10 |
肖特基二极管 |
D4 |
C402218 |
11 |
100pF陶瓷电容 |
C6 |
C254079 |
11 |
10nF陶瓷电容 |
C3,C4 |
C2761727 |
11 |
电压基准芯片 |
U2 |
C351448 |
14 |
100nF陶瓷电容 |
C1,C2,C5 |
C254085 |
14 |
数码管 |
LD1,LD2 |
C10701 |
16 |
XH2.54 3P直插无锁 |
CH1 |
C7429633 |
16 |
47uF电解电容 |
EC1,EC2 |
C45100 |
16 |
100uF电解电容 |
EC3 |
C43805 |
19 |
红色LED |
LD_PWR |
没用BOM上的 |
19 |
白色LED |
LED1 |
没用BOM上的 |
19 |
轻触开关 |
K1,K2,K3 |
C2837519 C2845257 |
19 |
2.54mm排针2P |
JP1,JP2 |
C124375 |
19 |
2.54mm排针4P |
H2.54 4P |
没用BOM上的 |
24 |
CH3.96 2P直插 |
CN1,CN2 |
C429947 |
24 |
DC电源连接器 |
DC |
C319099 |
26 |
10kΩ电位器 |
RP1,RP2 |
C330432 |
27 |
2.54mm排母20P,地文星 |
U3 |
C429947(排母) C22751548(地文星) |
【实物调试】
在结营前倒数2~3天,立创开发板在B站放出了“项目综合调试和应用”(BV号:BV1CfWUecEeN)主要步骤是对电压和电流测量误差的记录,这需要万用表以作辅助,这里文字总结为:
1、通断测试:
万用表通断档(我的万用表上标注的是“蜂鸣”)测3.3V以及其他网络与GND之间是否短路,没有问题则进行下一步
2、电压调试:
(1)用跳线帽(或杜邦线)短接JP1(即TGND母座和T_V母座之间的2.54mm排针);
(2)在DC接口接入电源(我用的是12V电池包,官方建议干电池包,因其稳定且自带DC接口,不推荐用电脑通过typeC供电免得损坏电脑,不推荐用220V转12V供电因有安全隐患)
(3)将万用表调到电压档,其中红色表笔接T_V母座,黑色表笔接TGND母座,因为我用的是12V的电池,我的电压表的电压档位有2V,20V,200V等,且我准备2V以下的电压测量使用10K与10K分压,所以我使用的是20V档位
(4)使用电位器RP1上的旋钮调节分压(分压范围取决于接入电源),烧录例程代码“实验八 压流同采显示”观察第一行3位数码管显示,此为测量电压值;观察万用表(默认这里使用的万用表是准的)显示值,此为实际电压值
(5)对电压的测量值和实际值列一个表格,计算误差
3、电流调试
(1)为了理解电流调试时万用表为什么这样接,可以参考本描述的“四、硬件原理学习笔记”中“电流采样”部分的图示,这里用文字做总结:
(2)因为电流测量本质测量的是电压,所以刚开始可以不焊接R0这个“电流采样电阻”,此时仍然能测量那里的电压,虽然此时实际上没有大电流流过,但因为有R0的时候也是由测出的电压和采样电阻的阻值来对电流进行计算,所以这里调试的时候没有实际电流也不影响我们进行计算。
(3)用跳线帽(或杜邦线)短接JP2(即T A母座附近的2.54mm排针);
(4)供电电源注意事项同“电压调试”部分
(5)将万用表调到电压档(注意不是电流档),其中红色表笔接TI+母座,黑色表笔接TGND母座,这里我使用2V的档位
(6)使用电位器RP2上的旋钮调节分压(分压范围在这个板子上是固定的,理论值约为0~238mV即max = 5V),官方推荐烧录例程代码“实验七 6位数显……”,因为能显示更多位数,我使用的仍然是“实验八 压流同采显示”,观察第二行3位数码管显示,此为通过测量出的电压值计算出来的电流值;观察万用表(默认这里使用的万用表是准的)显示值,此为实际电压值,想要算出理论上的实际电流值(如前文,此时不焊R0是没有实际电流的),需要将数值扩大10倍
(7)对电流的测量值和实际值列一个表格,计算误差
上图是一部分电压测量的情况,可以看出实际电压和测量电压的误差随着电压增加基本呈线性关系
本来这里的测试,为了发现一些共性问题,官方建议打样的5个板子最好全焊上,但我直到这个消息比较晚,所以元器件不够,就只能测这一个板子的情况了
八、复刻过程中的问题解决:
【问题1】官方BOM中所说的“2mm香蕉头母座”没有直接找到
【解决】找到官方给出的数字电压电流表训练资料,其中得知如下:
于是在淘宝找,图中母座外径是4mm,但是在淘宝找了半天都是4.7~4.8mm以下是淘宝链接:
【淘宝】https://m.tb.cn/h.gkAKF10MgIMorRA?tk=ECQB33lbTyJ CZ0000 「2mm香蕉插座纯铜镀金K2A33 插孔2mm测试孔电路实验教学仪器线路板」
点击链接直接打开 或者 淘宝搜索直接打开
【问题2】看到官方的PCB中,香蕉头母座大焊盘上有一圈小孔,但是没在立创商城找到相应的元件以及元件封装
【解决】解决方式是自己画,先画原理图,再自己画特制的焊盘然后将其互相关联起来
因为我买的母座的外径比推荐值大,所以我的理解是焊盘外径也要扩大到5.2mm左右
于是在立创EDA新建“元件”和“封装”,如下:
在封装上放8个小过孔
【问题3】电压基准芯片按照官方BOM中的C351448搜索出来与官方给的原理图中的元件的符号不一样官方的TL431如下:
我按照供应商编号C351448搜索出如下:
【解决】解决方法是查看手册
由上图和官方原理图,可知连接效果应该如下:
【问题4】发现画原理图的时候把三个开关二极管都画成了肖特基二极管,但是此时错误的板子已经下单制造并发货了
【解决】还好在准备焊接前发现了问题,元件购买也没有问题,肖特基二极管的封装可以兼容开关二极管,所以实际应用只不过是元件丝印有问题,并无大碍,不影响功能实现
【问题5】安装CW32的pack包时,遇到了官方文档里提到的问题
【解决】官方给了几种对策,我使用了修改文件名的方法解决,如图箭头所指处。
官方文档有教大家自己建立工程模板,因为我是小白,我直接从【3.2.4使用模板新建工程】的末端开始下载官方的工程模板,从而直接跳过3.2.3和3.2.4
【问题6】在电流标定时进行测量的时候,因为还没有焊接R0,所以此时万用表测量的是电压,而数字电压电流表显示的是电压除以0.1Ω限流电阻之后的电流(这部分参考本描述的“七、实物制作注意事项 【实物制作】”那部分);也就是说理论上万用表显示值应该比数码管显示值小10倍,但我在使用官方的“实验七 六位数显的电流通道采集电压显示”的代码进行调试的时候发现万用表显示值比数码管显示值大10倍;但当我换到“实验九 带有标定功能的数字电压电流表”的代码,却发现显示正常了,于是我怀疑是代码有问题
【解决】发现果然代码的小数点有问题:
上图是“实验七 六位数显的电流通道采集电压显示”中的函数,这个函数标框的这一句是根据测的电压算电流,因为数码管显示的原因,这里的参考电压ADC_REF_VALUE比1.5大了1000倍,也就是1500,此时对于实际位1.234A的电流就会变成1234,此时对于将两个3位数码管都用上的情况,小数点应该在上面那个数码管的第3位,那么我们接下来看下图:
上图是“实验七 六位数显的电流通道采集电压显示”中用于显示的函数,根据上文结论,小数点应该是在Thousands处进行处理,而代码却在Wwei处进行处理,于是真相大白,代码有误
九、附件目录:
1、代码包(分“官方原版”和“略有修改版”)
2、图片包(开源描述里出现的图片的原图)
3、视频
4、3D文件包(有stl格式,step格式,obj格式)
5、BOM包(官方推荐的BOM和我最后实际使用的BOM)
6、参考资料包(图标等)
评论