
【彩色丝印】过隧道拯救者-图一乐DIY游戏机-1.0
简介
“妈妈再也不用担心我坐火车过隧道时没得玩了!” ——成都西安往返用户如是说 基于GD32E230C8T6
简介:“妈妈再也不用担心我坐火车过隧道时没得玩了!” ——成都西安往返用户如是说 基于GD32E230C8T6开源协议
:GPL 3.0
描述
一、前言:
感谢嘉立创的彩色丝印活动!
感谢嘉立创的20元器件券,50元彩色丝印券!
本开源工程描述含有:
【一、前言】
【二、功能介绍】
【三、参考资料】(极简)
【四、硬件(原理图)】(详细)
【五、硬件(PCB)】
【六、软件】(非常详细)
【七、实物制作注意事项】
【八、过程中的问题解决】(极简)
本工程是本小白参加的第一个非训练营的征集令活动,其由以下四方面一拍即合:
(1)9月份无聊的时候写的一个简易棋类代码;(这部分功能和玩法在“六、软件”说明)
(2)9月到10月连续错过2~3次征集令活动的迫切心情;
(3)之前三次训练营已经学到的部分知识和可以复用的电路;
(4)本次一年一度的彩色丝印活动;
本次活动其实是为了一碟醋而包的饺子,电压电流表训练营结束后总觉得不能闲着,借用示波器那一期做的板子上的屏幕和按钮写了个简易棋类游戏,本来只需要最小系统板,屏幕和按钮,但是这样总觉得太过敷衍,于是:
三合一:
借用“简易数字示波器”的GD32,按键,LED,旋转编码器,TFT显示彩屏和相应代码
借用“简易电压电流表”的DC电源输入电路,数码管(硬件同型号)
借用“温湿度检测仪”的SHT40温湿度传感器模块,数码管(软件参考古来夏大佬)
此外还加了一些其他玩意儿,本次大量复用了之前剩余的硬件,所以我本身只额外多花了不到10元,如果元件全盘在立创商城从0开始买需要花费高达200元,本次暂时不考虑“他人视角下的”成本,纯粹图一乐!纯粹图一乐!求大佬轻喷
二、功能介绍:
(1)基于GD32E230C8T6的由屏幕和按钮组成的简易图一乐游戏机,供坐火车过隧道时没有网且手机平板没有别的单机游戏时使用;
目前代码方面只有一个基本完成功能的棋类游戏,玩法在“六、软件”说明
(2)温湿度模块这里主要目的不是为了获取温湿度,想怎么用都行;
(3) 三个按键1个软件消抖,1个硬件消抖,1个软硬皆可;在有屏幕的情况下还冗余了三个位置可放数码管,若问为何如此,纯属图一乐。
(4)未来期望在上面多实现几种简易游戏(游戏内容非原创,只不过想自己用代码在屏幕上实现,而且都是足够简单的游戏,难度应该不超过贪吃蛇)
三、参考资料:
参考资料很简单,就是前面3次训练营的所有包含内容
四、硬件(原理图):
硬件部分虽然大多照搬之前,但是这里为了完整性,还是说明一下(哪怕copy之前的解释)
1、【供电电路】
说明:
做好实物后才发现,从我之前预期的使用场景来看,直接用充电宝给GD32板子供电就可以了,似乎不需要下面的电路,以下文字来自对电流电压表项目文字的照搬;
唯一添加的0Ω电阻借鉴示波器那一期,因为本次其他电路GND都铺铜解决,而供电电路则不是,本小白不知道这样可不可以于是将两个GND用0Ω电阻连接
供电电路如图:

对于供电电路的分析,官方的文档从“降压芯片”“滤波电容”“防反接二极管”“串联小电阻”“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;对于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)由上图可以看出,我标注了单点接地,而且将地线的走法画得比较夸张,可以看出对于GND,应该是C1的GND直接连接到EC2的GND,C2的GND直接连接到EC3的GND,最后将EC2的GND直接连接到EC3的GND;
(2)对于“供电电路”来说这里是“串联单点接地”,但是从整个PCB板子的角度来看是“混合单点接地
2、【单片机电路】

单片机电路主要就是引脚分配,与示波器那一期训练营相比,只多了红框里的6个引脚,PB10和PB11是用于SHT40温湿度模块的,预计使用软件IIC;
PA1到PA4的引脚与数码管相关,本来使用2个74HC595串联形式可以只用3个引脚控制8位数码管,但是我预设了3个3位数码管,多的那一位和蜂鸣器共用PA1来控制,用跳线帽来确定控制谁
3、【人机交互电路】(不包含数码管部分)





(1)这部分电路里,“1.8寸TFT屏驱动电路”“五向开关接口(旋转编码器)”“LED指示电路”与示波器训练营那一期一致,没什么说的;
(2)“按键控制电路”,本来3个按键都是像KEY1那样一端接地一端接单片机IO口,但是KEY2和KEY3我都加了上拉电阻和滤波电容可以硬件消抖,区别在于KEY3还可以通过跳线帽的方式自主选择是硬件消抖还是软件消抖,我只是想借机消耗多余的电阻电容的情况下实验一下硬件消抖和软件消抖的不同
(3)“蜂鸣器&1位数码管”前文已经提到,2个74HC595最多控制8位数码管,多余的1位和蜂鸣器通过同一个IO口控制,由跳线帽的方式调节
4、【数码管显示电路】

对于数码管的驱动,我这次参考了盛思锐那一期的古来夏大佬的设计,将74HC595串联,其中一个管段码,一个管位码,数码管我准备了3个3位数码管(虽然封装上显示是1位但实际上是3位),想把红色绿色蓝色都试一下,两个595芯片接3V3的地方我各配了一个滤波电容,此外我这里的595使用的是芯片座配插件元件而不是贴片,因为上次我用了免费SMT券但这次没有,而这么小的贴片我不会焊也没有买热风枪。这里先摘抄上一次电流电压表项目的总结,如下:
第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位数码管。即这位大佬将软件资源和硬件资源做了一个很厉害的平衡!如下图:

数码管电路的限流电阻:
(1)每个位都要配一个限流电阻(注意这里并不是某些网上的原理图那样每个段一个电阻,是因为我们使用插件电阻,为了节省电阻于是只给位配一个电阻,否则的话6位数码管需要48个电阻,这样做的缺点是可能会影响显示效果)
(2)因为这里选择的是动态扫描的方式(每次显示1位),而不是静态扫描的方式(每次显示n位),所以每个位选定的时候其他5个位不需要点亮,所以每个位选定的时候承受且只承受对应位的8个二极管处的电流;
(3)查询CW32F030C8T6的手册可知其最大电流输入和最大电流输出为25mA;我们在此处用的是共阴极
(4)关于300Ω这个值具体是怎么选出来的,请看下图:

这里再对上图做出补充:
电阻大小除了要考虑MCU的拉电流/灌电流大小,还要考虑数码管本身能承受的电流,文档说查询手册得知是不超过35mA,所以按照MCU的不超过25mA来处理即可;此外电压驱动不低于2.9V,这里计算时用的3.3V是MCU的自带的输出,这里没有让MCU输出5V(文档说是因为功耗问题)
官方文档说过数码管的驱动方式为用DSP,MCU或移位寄存器,接下来的总结涉及只用MCU控制和MCU搭配移位寄存器控制;控制信号可以是PWM或者串行数据信号,下面总结的情况只用到了串行数据信号
数码管是一种特殊的LED使用方式,所以LED相关也放在一起讲;官方文档说LED设计为正极持续5V,负极由MCU的I/O控制是因为MCU一般灌电流(输入电流)能力大于拉电流(输出电流)能力,负极由MCU的I/O控制时电流是流入单片机的;这里LED最大电流是20mA,在5V下最小电阻为250Ω,官方文档综合考虑到亮度和器件参数数量,最终选择了10kΩ的电阻;
5、【其他电路】


(1)SHT40温湿度传感器模块这部分与盛思锐那一期的电路一致,但是两个上拉电阻我换成了插件,而且阻值不一样,其会影响数据传输速率,此外SHT40的插件模块已经停产了,我用的是之前买的,现在只能买到贴片形式的了
(2)4个M3铜柱为什么缺一个?这需要在后续PCB部分解答
五、硬件(PCB):

- 先展示一张隐藏了铺铜的正面的PCB以来看走线情况,可以看出对于GD32,按键,旋转编码器和TFT屏幕的布局摆放位置与示波器那一期训练营是一脉相承的
- TFT屏幕因为是通过模块插件的方式布置,下面有大量空间,示波器那一期在底下放了“模拟前端处理电路”而我这里主要放了2个74HC595和9个限流电阻
- GD32底下其实也有空间,我老早就想在底下放了,虽然感觉这么做不太正规。先放了SHT40模块和两个上拉电阻,然后是只需要听到不需要看到的蜂鸣器(之前怕蜂鸣器太高没法放下,好在最后买的无源蜂鸣器矮矮的)两个显示LED需要看到,不能被遮挡,所以放了出来
- DC电源输入的电路我之前放在整体左边,与电流电压表那一期一样,之后发现右下角空了一部分,于是硬塞进去,代价就是没法保持3个电解电容的极性方向在PCB的朝向的规整,导致有的向右有的向左有的向上;
- 现在看来,DC电源输入的部分和三个数码管应该放在整体结构的左边,这样DC电源那边的元件不会干扰到操作旋转编码器的右手的同时整体面积也不会变(不过当时放在左下角的另一个原因是这样5V的电源线直接就连到GD32上了,而不需要从底层走线)
- 整体来讲可以看出我尽可能不在底层走线以保持底层的铜皮完整性,哪怕代价是我的线弯弯绕绕(不过问题不大,因为不是高频信号线,大部分都是数码管控制的线)

从上图看出我确实尽可能避免在底层走线

上图是最终正面的情况,可以看出右下角DC电源那部分我确实GND用走线的方式而没有铺铜,用0Ω电阻将两种GND相连,分界线为在正面丝印层画的小点虚线

这是背面铺铜情况,同样是右下角没有铺铜,此外可以看出底层铜皮很完整,此外正面与反面铜皮的尖锐处我也通过“禁止区域”的方式处理了
六、软件:
游戏1:某种简易棋类(圆圈棋,姑且这么叫)
玩法:(类似于动物棋斗兽棋之类的但是是简化版)
(1)棋盘是5排6列30个格子,下棋双方是红方和绿方;
(2)每人15个棋子,分别是5个1级棋,4个2级棋,3个3级棋,2个4级棋,1个5级棋;
(3)吃棋规则:可以吃级别小的棋或者同级别的棋,比如3级棋可以吃2级和1级
(4)例外:最小的1级棋却可以吃5级棋,5级棋却不能吃1级棋,但1级棋仍然会被234级吃,即5>4>3>2>1>5>……
(5)游戏时红绿双方轮流出手,游戏开始的时候每个棋盘上棋都是未知状态,轮到每一方出手的时候可以选择揭晓1个未知状态的棋或者将自己1个棋进行挪动或者吃棋操作,其中揭晓未知状态的棋可能会发现是对方的棋
(6)判定游戏输赢有多种方式,目前只写了一种,就是谁先吃掉对方10个棋谁就获胜,此外以后肯能添加的玩法包括且不限于双方下棋下满50轮之后谁吃的棋多谁获胜
怎样操作:
(1)使用按键和旋转编码器操作,按键从左到右在下文称为KEY1,KEY2,KEY3,旋转编码器下文称为KEYD
(2)本游戏中,KEY1为确认键,KEY2为取消键,KEYD控制光标的移动,KEYD的控制方式有3种:顺时针旋转,逆时针旋转,垂直按压
(3)刚开始整个棋盘30个格子都是未知状态的棋子,开始时棕色方框光标会选中其中1个棋子,通过操作KEYD可以控制棕色光标移动到想选择的棋子位置,控制方式为,KEYD顺时针转动为光标右移或上移,KEYD逆时针转动为光标左移或下移,至于到底是左右操作还是上下操作,可以通过将KEYD垂直按压一次来切换,比如目前如果顺时针旋转KEYD光标是右移,那么将KEYD垂直按压一次后顺时针旋转KEYD光标是上移
(4)将棕色光标移动到想要操作的棋子上后,点击KEY1确认,方框光标会变成黄色选定当前棋子
(5)如果选中了未知状态的棋子,其会变成已知,本次操作结束,将由对方继续操作
(6)如果选中了本阵营棋子(对方阵营棋子无法被选中),此时棕色光标会选中黄色方框选中棋子的相邻4个棋子的其中1个,此时顺时针或逆时针旋转KEYD,棕色光标会顺时针或逆时针将相邻4个棋子轮流选中,如果黄色光标棋子位于边界,则相邻棋子只有3个,若选中棋子在4个角落,则相邻棋子只有2个
(7)对于“(6)”所说的情况,此时若再次点击KEY1确认,则会进行吃棋操作或者移动操作,相反若是点击KEY2取消,则将返回“(3)”所述的情况
以上的操作步骤如果觉得文字描述太过于抽象,可以结合演示视频来理解

上图是我写的代码,是展现我代码是怎么一步步写出来的,会放到附件,其中目前可以玩的是“08_GD32_Nixie_Score_and_Win”因为是从这一步才开始加入数码管显示和计分,而后面的091和092功能还没完全完成
软件流程图来不及画了,这里主要介绍代码里一些重要部分:
1、【main.h】文件
该文件里需要说明一些宏定义的作用和我设置的一个结构体:
先说宏定义

(1)最开始的X_SIZE和Y_SIZE是棋盘在x轴方向和y轴方向的格子数,分别为6和5(平面宽161个像素,高129个像素,1个格子大致25个像素)
(2)两个宏定义WAIT_SURE和WAIT_EAT是变量choose_state(选择的状态)可以有的两种值,choose_state是1个标志位,KEY1,KEY2和KEYD再操作时会根据choose_state的值是WAIT_SURE还是WAIT_EAT来进行不同操作;
(3)WAIT_SURE是“等待确认”对应前文“怎样操作”中的“(3)到(4)”此状态下,按KEY1会进行对棋的选中或对未知状态棋子的揭晓,按KEY2不会起作用,旋转KEYD光标会上下平移或者左右平移;
(4)WAIT_EAT是“等待吃棋”对应前文“怎样操作”中的“(6)到(7)”此状态下,按KEY1会将选中棋按照目前的位置进行移动吃棋或单纯只是移动,按KEY2会取消选中,回到“(3)到(4)”的状态下,旋转KEYD光标会在“步骤(4)”选中的棋的相邻位置打转;
(5)其他宏定义与上文同理,不再做详细解释,根据前文玩法大家应该都可以从注释和宏定义的名称上来“望文生义”,无非都是些标志位和它们可以的取值

- 上图中展现了我设置的重要的结构体:GuiGuai,叫这个是因为这个棋也叫“鬼怪棋”,不同级别的棋子就是不同级别的鬼怪
- 对于结构体GuiGuai,每个该结构体对应的变量都表示一个棋子,记录了4大属性:阵营级别,坐标,自身状态,交互状态;
- 其中“阵营级别”和“坐标”又是两个套娃级别的结构体,前者的两个变量分别对应“阵营”和“级别”,后者的两个变量分贝对应“x坐标”“y坐标”至于为什么要进行结构体的套娃?这需要再main函数那里揭晓
2、【main.c】文件
本文件是重头戏,需要向各位说明变量的设置,以及7个重要的函数

- 这是在7个重要函数之前的变量的初始化,分为“结构体变量”和“普通变量”,对于普通变量,结合前文说的游戏玩法,根据变量名称和注释就能大致猜出功能,此不赘述,这里主要说明一下“结构体变量”
- 可以看出先建立了1个存放30个GuiGuai类型变量棋子的结构体变量数组guiguaiArray,这个数组很重要,因为后文很多对于棋子位置的判断实际上就是对于这个数组的下标的判断,因为GuiGuai结构体有内嵌了两种结构体,所以底下又有两个结构体数组:coordArray[30]和campRankArray[30],其作用也是在后文中揭晓,最后还有一个GuiGuai类型的单独变量guiguai_temp,从变量名称中的“temp”就可以看出它存在的目的是用于两个结构体变量互换数据的时候暂存内容

(1)第1个重要函数就是主函数了,从中可以一窥代码整体结构
(2)在while(1)循环之前有两个初始化函数,Init_1();和Init_2();由注释可知Init_1()是跟外设有关的初始化,包括时钟,LED,屏幕,按键,数码管相关的初始化函数的调用,这个简单,这里不再额外说明,关于Init_2();也是7个重要函数之一,这个后文说,它的目的是将这个游戏初始化,所以两个初始化本质不一样,因此写了两个函数
(3)while(1)中的代码分为3部分介绍:LED6相关的6行,DisplayScan();开始的3行,以及用于“判断双方是否有人赢了”的那个if语句;其中第1部分和第3部分因为仓促还没来得及封装为函数
(4)LED6相关的6行代码是这样的,我原理图和PCB设置了3个3位数码管,最终只焊了1个3位红色数码管和1个3位绿色数码管,这里的LED6数组0,1,2位对应红色数码管,表示红方阵营的吃棋个数的百位数十位数个位数,LED6数组3,4,5位对应绿色数码管,表示绿方阵营的吃棋个数的百位数十位数个位数;与数码管有关的代码在nixie.c和nixie.h中,因为时间限制这里不作介绍,其就是参考的古来夏大佬在盛思锐那一期的数码管的代码
(5)用于“判断双方是否有人赢了”的那个if语句作用很简单,谁先吃到10个棋,就在屏幕上显示以赢方阵营颜色为底色的666三个字,并跳出整体的while(1),在这个while(1)外面还有一个空的死循环while(1),意味着这时候你就应该按动复位键重新玩游戏了
(6)DisplayScan();开始的3行:DisplayScan();和后面的delay_ms都与数码管有关,此不赘述,其中后者既是数码管扫描间隔,也是按键状态扫描间隔
(7)Key_Handle(&oscilloscope);函数是7个重要函数之一,这个后文说,至于为什么参数是oscilloscope结构体(前文没讲)(oscilloscope是示波器的意思)因为这个代码就是在之前GD32的示波器项目的代码的基础上改的,因为Key_Handle这个重要函数用到了oscilloscope结构体,所以与之相关的代码就没有删

- 上图是第2个重要的函数,这个函数有别于对外设的初始化,它是对游戏的初始化,由注释可以看出它总共分5步
- 第1步就是“30个“阵营种类”结构体赋值”它就是对30个CampRank结构体变量在阵营级别方面先设置好(坐标,自身状态,选中状态先不管)在这一步因为有两个阵营,所以代码方面用了两个for循环,级别设置的时候就按照5个1级棋,4个2级棋,3个3级棋,2个4级棋,1个5级棋设置的,此时各种阵营和级别的棋在数组campRankArray[30]中的顺序是有序的
- 第2步是“打乱30个阵营种类顺序”,这里用到了函数shuffle_campRank,其为洗牌函数,是8个重要函数之一,这个后文说,其作用是将campRankArray这个数组按照不同的random_value值进行打乱,每一个random_value都对应一种打乱后的情况,但是具体怎么对应,是在函数shuffle_campRank内部解决的,我们并不关心,我们认为其是某种随机打乱即可
- 第3步是“对30个鬼怪对象赋值”,这次赋值的才是那30个GuiGuai结构体变量,而且这次把阵营种类,坐标,自身状态,选中状态这4个属性都初始化了,可以看出阵营种类是打乱后才塞给GuiGuai结构体的,但坐标在数组guiguaiArray中是按照顺序放置的,且可以看出坐标与数组guiguaiArray的下标的对应关系,这样做是因为之后的操作中就是通过对guiguaiArray的下标进行判断和运算来进行棋子位置判断的,这一点很重要;此外可以看出刚开始30个棋子的自身状态都是“未知”,选中状态都是“为选中”,故统一赋值
- 第4步是“初始化其中1格待选中”,这里对数组guiguaiArray中下标为cur_cell的那1格进行选中,这里我cur_cell设为14,所以每次刚开始的光标位置都在那里
- 第5步是“显示更新函数”TFT_ShowUpdate();是7个重要函数之一,这个后文说


(1)上图是第3个重要函数:显示更新函数,目前方案很粗糙,每次显示更新都要全屏更新,先全部黑屏然后再更新,导致玩游戏的时候每次操作都会全屏闪一回,之后会改进为部分区域更新的模式
(2)这个函数特别的长,因为时间关系这里大致讲一下整体思路,就不详细讲了
(3)每次先将全屏清空,然后画上棋盘白线(相关代码就不解释了),定义了半径,颜色,坐标等4个变量用作准备
(4)接着是一个大大的for和两个switch,for循环是将30个位置的棋子情况轮流更新,第1个switch根据棋子“自身状态”来绘制,第2个switch根据棋子“选中状态”来绘制
(5)“自身状态”方面,位置状态用灰蓝色实心圆表示,普通状态则根据阵营和级别选择实心圆的颜色和大小,红方为红,绿方为绿,半径越大级别越高,这里画实心圆的函数是我拿示波器例程自带的画空心圆的代码改的,若是被吃状态则什么也不画
(6)“选中状态”方面,如果光标自由移动到这里则是用一格比棋盘格子略小的棕色方框框柱,如果是选中,则是金色方框,否则不绘制方框

(1)上图是第4个(或者说是第4类,因为其包含两个函数)重要函数:“伪随机数生成函数”和“洗牌函数”
(2)这两个函数是我求助AI后获得的,将数组内容进行伪随机打乱,效果不错,不过我没有深究背后的原理,此不赘述

(1)上图是第5个重要函数:按键处理函数,虽然这个函数并不在main.c文件里而是在key.c文件里,但是我必须在介绍剩下2个重要函数之前先介绍它,所以放在了这里
(2)这里再次说明一下:为什么参数是oscilloscope结构体(oscilloscope是示波器的意思)因为这个代码就是在之前GD32的示波器项目的代码的基础上改的,因为Key_Handle这个重要函数用到了oscilloscope结构体,所以与之相关的代码就没有删
(3)本函数主体是1个switch,它要判断的是oscilloscope结构体中的变量keyValue,这里从注释可以看出KEY3的作用被闲置,KEY1和KEY2是两个普通按键,作用是确定和取消,这里的KEYD,KEYA和KEYB代表旋转编码器垂直按下,逆时针旋转和顺时针旋转;至于keyValue的值的更新当然来自于按键对应的外部中断函数,但是因为时间原因,实在是来不及写了
(4)switch的KEY1,KEYA和KEYB涉及到剩下两类重要的函数,Judge_Sure();是一类,其用于进行按下确定键后的相关判断和操作,KeyA_DownLeft_Ni();和KeyB_UpRight_Shun();是同一类,其用于进行旋转旋转编码器后的相关判断和操作,而KEY2和KEYD因为对应的情况太过于简单,所以没有单独封装为函数,这里不解释了,大家看变量名称和注释就能看懂
(5)switch结束后更新图像并将keyValue置零,注意更新的前提是keyValue不为0,否则会一直更新,此外keyValue若不置零也会一直更新


(1)上图是第6个重要函数:确认键判断与执行函数,这个函数特别的长,因为时间关系这里大致讲一下整体思路,就不详细讲了
(2)整体而言,确认键可能在两种情况被按下,一种是在棕色光标自由移动在某处时进行目的是选中一个即将进行操作的棋子,另一种是已经有一个棋子被黄色光标锁定后来选择其相邻位置来进行吃棋或移动;
(3)对于前者,分为两种情况,如果选中未知状态棋子,则棋子揭晓同时本轮操作终止,轮到对方了,如果选中本阵营棋子(对方阵营的选不中),则将棕色光标换成黄色光标,并进行下一步操作
(4)对于后者,又分为两种情况,一种是选中的是空格子,则直接进行下文的坐标互换,否则若选中的是棋子,那么要判断是否能吃……这里的精髓有两个,1个是先按照大的吃小的判断,再排除5吃1和1被5吃两个错误情况,这使用了排除法;2个是“吃”在代码的实现上即被吃棋子自身状态转为“被吃”然后与吃他的棋子属性互换,但是坐标却不能互换,这里我不解释原因,大家猜猜为什么?


- 上图是第7个重要函数也是最后1个重要函数:编码器键旋转的判断与执行函数,这个函数特别的长,因为时间关系这里大致讲一下整体思路,就不详细讲了(这里只选择KeyB_UpRight_Shun而不说KeyA_DownLeft_Ni是因为二者在代码和功能上都是镜像的)
- 与Judge_Sure一样,编码器在顺时针旋转的时候同样有两个情况,且都是由同一个标志位确定的,在代码中的体现就是最外面那个if和else-if,对于前者还要额外判断现在是向上还是向右
- 重点是下面那个else-if,重要就重要在被选中的棋子可能是在边界甚至角落,这就导致其周围的棋子方格不一定是4个,可能是3个甚至2个,所以旋转的时候需要根据前面提到的数组下标来判断位置,这一部分在我debug的时候用时最久,也最为精髓(以后换个触摸屏就不用这么麻烦了),这里大家可以根据4种情况的代码的注释理解一下这里为什么这样判断,代码为什么这么写,我就不具体解释了(虽然我最想解释这里,但是时间确实不够了)
七、实物制作注意事项:
1、【元件购买】
因为我大量复用前3次训练营的多余元件,故这次我只新购买了无源蜂鸣器,插件74HC595芯片,16脚芯片座和两个绿色3位数码管;再加上有20元器件券,所以本次总共花费不超过10元,否则再立创商城全款从0购买要花费200多元
2、【彩色丝印】
本次活动为彩色丝印活动,但我没有将整个PCB都用1个大幅的彩图覆盖,因为我感觉那样选不好图的话反而不漂亮,我也没有像以前那样在正面放彩图,而是把很多图放到背面了,虽然我放了几个小小的彩图,但是其分辨力很高,嘉立创的彩色丝印就是厉害
3、【焊接顺序】
(1)本次除了LDO芯片是贴片之外,其他元件都是插件,焊接需遵循从低到高的原则进行,我根据我最终实际用到的BOM表的元件,按照元件由低到高列出以下表格:
(2)小白怎样焊接?参照嘉立创B站教程视频(BV号:BV1sJ4m1Y7Zp)
(3)注意金属膜电阻之间,以及陶瓷电容之间长的很像,焊接前电阻可以用万用表测一下,电容看一下标号,免得焊错
(4)注意电解电容,肖特基二极管都是有极性的,原理图和PCB上不要画反是基础,焊接时也要留意丝印上的极性,其中电解电容若是焊错会爆炸
(5)建议电烙铁使用刀口,可变温,注意不要被烫伤
(6)最后20P排母和GD32要合在一起后焊到板子上,避免焊歪无法安插核心板
焊接顺序:
|
顺序 |
名称 |
位号 |
器件编号 |
|
1 |
电源IC |
U4 |
C115012 |
|
2 |
1.27mm4P弯插排母 |
U5 |
C2881475(排母) C22437501(模块) |
|
3 |
10Ω电阻 |
R14 |
C138214 |
|
4 |
300Ω电阻 |
R1,R15,R16, R22,R23,R24, R25,R26,R27 |
C58609 |
|
5 |
10kΩ电阻 |
R4,R5,R20,R28,R29 |
C410695 |
|
6 |
0Ω电阻 |
R30 |
C410698 |
|
7 |
1kΩ电阻 |
R2,R3 |
C57435 |
|
8 |
肖特基二极管 |
D4 |
C402218 |
|
9 |
100nF直插独石电容 |
C5,C6,C7,C8,C9,C10 |
C168753 |
|
10 |
SN74HC595N(DIP16) |
U7,U8 |
C78711 |
|
11 |
100nF直插瓷片电容 |
C1,C2 |
C254085 |
|
12 |
无源蜂鸣器 |
BUZZER1 |
C96256 |
|
13 |
红色LED |
LED1 |
C2895470 |
|
14 |
绿色LED |
LED2,LED3 |
C2895477 |
|
15 |
数码管 |
LD1,LED5,LED4 |
C10701(红) C2938343(绿) C2938344(蓝) |
|
16 |
47uF电解电容 |
EC1,EC2 |
C45100 |
|
17 |
100uF电解电容 |
EC3 |
C43805 |
|
18 |
轻触开关 |
KEY1,KEY2,KEY3 |
C2845257 |
|
19 |
2.54mm排针2P |
JP2 |
C124375 |
|
20 |
2.54mm排针3P |
H1 |
C2937625 |
|
21 |
DC电源连接器 |
DC1 |
C319099 |
|
22 |
2.54mm排母8P 1.8寸TFT屏幕 |
U2 |
C41413862(排母) C9900080251(屏幕) |
|
23 |
旋转编码器 |
SW4 |
C2991196 |
|
24 |
2.54mm排母20P 立创GD32E230C8T6开发板 |
U1 |
C429947(排母) C20068939(GD32) |
八、过程中的问题解决:
【问题1】数码管本来是想1个红的1个绿的1个蓝的,但是下单PCB后才发现因为预计的红蓝数码管因为与上次电压电流表训练营同型号过于抢手已经没货
【解决】买了2个绿数码管,最后发现上次电压电流表训练营留下来1个红数码管,最后用了1红1绿两个数码管,而空了1个数码管的位置没有放东西
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。


评论