目录
前言
目前能分享的处理方式前边都已经分享过了,这里还是只分享本届赛题中一些独特的处理方式。做过十四届赛题之后,感觉前边的题目都很简单,所以在省赛之前,可能会刷一些国赛题来代替省赛。关于选择题的部分,还是不再分享了,感兴趣的可以自己看看。
如果今年省赛之前,公布了新的资源数据包,或者有了新的要求,作者也会第一时间如何使用新的资源数据包完成我之前写的代码的相关修改。
这里还是以第十四届资源数据包为基础:
单片机资源数据包_2023
一、第十三届比赛省赛
1.比赛题目
2.赛题解读
本届比赛只有三个菜单,比起十四届的六个菜单,真是简单了许多。
本届比赛使用到了继电器,虽然最开始学的时候也已经介绍了继电器,但是说实话用的次数不多,而且原理与LED和数码管想通,所以后续就很少介绍了,甚至上一篇的省三模板代码也没提到继电器。本篇文章会再次重温一下继电器的使用。
其他的要就就是中规中矩了,有一个长按S17显示分秒,正常情况显示时分的功能,实现起来也比判断短按按键和判断长按按键简单的多。而且好像去年比赛也用到了这个功能。
二、部分功能实现
1.继电器的开启与关闭
开启/关闭继电器其实和点亮/熄灭一个LED灯的道理是一样的,只是操纵的锁存器不一样而已,而且中间多了一个芯片用于大电流驱动,但是这个芯片几乎不影响处理。
左边的锁存器就是我们用来控制及继电器和电机的。右边的ULN2003是一个常用的达林顿晶体管阵列,它主要用于放大输入信号,以驱动继电器或其他大电流负载。需要注意到是,ULN2003芯片输入高电平时,输出的是低电平,输入低电平时,输出的是高电平。比如现在ULN的IN5是高电平,那么对应的OUT5输出的就是低电平。
下图是蜂鸣器的原理图:
其中N RELAY就是信号输入引脚,不难看出,当N RELAYT引脚为低电平时,有电流流过继电器,继电器闭合,结合上边关于锁存器和ULN的原理图,N RELAY连接的是ULN的OUT5(N RELAY有用红色框框标注欧),OUT5对应ULN的IN5,而IN5连接的是锁存器的Q5,锁存器Q5对应的输入是D5,D5连接的是P04,也就是说,我们只需要把P04置为高电平,然后开关一下锁存器让数据保存进去,就可以完成继电器的开启,同理,将P04置为低电平,然后开关一下锁存器,就可以将锁存器熄灭。是不是跟点亮一个LED灯一样呢,只是说点亮一个LED灯需要给一个低电平,熄灭给高电平,而继电器和蜂鸣器则是高电平闭合/响,低电平不闭合/不响。
至于锁存器的开启与关闭相比大家应该都已熟知,控制用来存储ULN数据的锁存器的使能端连接的是Y5C接口(上边图片也有标注),高电平有效,我们要想开启ULN连接的锁存器,只需要将ULN连接的锁存器的使能端置为高电平,在置为低电平,即完成了一次开关。
而Y5C接口连接的是三八译码器(右边的或非门可以选择性忽视)。三八译码器的输出是P25 P26和P27,当P27 P26 P25为101时(也就是十进制的5),就可以使得Y5C为高电平,同理,如果当P27 P26 P25不为101时,Y5C输出的就是低电平,这样我们就完成了一次开关连接ULN的锁存器。
当然,开关锁存器之前我们要先给P0置为。我们可以向控制LED灯一样控制继电器,定义一个变量用来记录ULN的状态。然后通过宏函数开改变ULN中对应的值,并且开关一次锁存器。代码如下:
unsigned char ULN=0x00;//ULN芯片状态(控制继电器和蜂鸣器)
#define RELAY_ON() ULN|=0x01<<4; P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;
#define RELAY_OFF() ULN&=~(0x01<<4); P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;
2.长按切换显示状态功能的实现
先看题目要求
简单点说就是按下S17之后,显示分秒,其他状态下显示时分。
不需要判断长短按,反正就是按下去之后切换一下显示,我们直接在按下按键的while循环中加上我们需要显示的数据即可(由于就这一个长按,所以长按时显示的数据就没写在菜单显示函数里了),同时不再调用菜单显示函数即可(避免发生冲突)。注意这个长按功能仅在时间显示菜单有效。
P34=0;
if(P32==0)
{
Delay5ms();
while(P32==0)//如果长按了17,由于只在长按时有效果,所以就把菜单直接显示在这里了
{//一旦跳出这个循环,show_menu函数就会开始运行,这个临时菜单就会被清除
if(mod==1)
{
Nixie_num[0]=21;//U
Nixie_num[1]=2;//2
&