目录
前言
虽然第十一届省赛题目跟十四届相比,也很简单,但是里面确实也需要许多特殊的处理,这里也跟大家分享一下,我对里面的一些特殊处理的方式。
老规矩,先放资源链接
单片机资源数据包_2023(点击下载)
一、第十一届比赛原题
1.比赛题目
2.赛题解读
平平常常的四个菜单,简简单单按键功能,只是对参数的加减,这次题目难就难在计数和LED显示部分。所以如果能把按键和数码管写好,按键功能实现,感觉冲个省二都没问题了。这里只针对上边两个部分进行介绍:
1)计数功能
计数界面:
计数规则
从图上可以看出,它想表达的计数时机,其实就是当VAIN3电压值从高于Vp,也就是电压参数或者说电压预支,到低于电压阈值之后,计数就+1,当然从低于阈值到高于阈值这个过程计数不会增加,这个VAIN3就是PCF8591的第三个通道。对应到板子上的话,就是读取到的电位计的电压。其实这个跟第十四届从亮到暗或者从暗到亮有异曲同工之妙,相当于第十四届是这个的升级版。我把第十四届的链接放在下边,感兴趣的可以去瞅瞅。至于这个计数怎么实现,下边会介绍。
蓝桥杯第十四届电子类单片机组程序设计_蓝桥杯单片机哪一届最难-CSDN博客
2)连续按下无效按键
题目上的要求如下
指示灯 L3: 连续 3 次以上(含 3 次) 的无效按键操作触发 L3 点亮,直到出现有效的按键操作, L3 熄灭。
之前的题目要求,只说某某按键的功能只在某某菜单才可以生效之类的,当然这个题目也有这样要求,如果在当前菜单按下某个按键后,不会响应,或者说当前按下的按键,没有在它指定的菜单时,那就应该记为一次“无效按键操作”。
除此之外呢,我个人感觉比如一些本身就没有功能,题目没有用到的按键按下之后,也应该被标记为“无效的按键操作”,因为题目上也没写使用哪些按键完成操作。
同样的,具体的实现下边会提到。
二、部分功能实现
1.计数功能的实现
要想精确计数,我们肯定得实时读取电压值V,这个肯定是不可避免的了。我们知道PCF8591读取到的都是数字量(取值0到255),我们需要先把它转化为模拟量,加上题目要求的Vp以及需要显示的电压值要精确到小数点后两位,这里在转换时就直接把V的值扩大100倍方便计算和处理。
unsigned char ad=0;//读取到的AD值
unsigned int V=0;//当前读取到的电压值,由AD值转化而来。为便于显示小数点后两位,电压的数值扩大了100倍
ad=get_pcf(3);//读取ad
V=(unsigned int)(ad*100/255*5);//获得当前读取到的电压,为方便保留小数点后两位,这里已经扩大100倍
读取的处理,我放在了定时器里。大致思路如下:
1)定义一个标志位is_up,当读取到的电压值V高于Vp,并且is_up=0时,则将is_up置为1,也就是记录第一个状态:当前电压值高于Vp
2)当当前电压值V低于阈值Vp,并且is_up=1,则将is_up置为0,并且计数+1.
这样就是实现了,只有当电压从高于阈值跳到低于阈值时,计数才会+1了。具体代码如下:
if(is_up==0&&V/10>Vp)//如果当前电压V小于Vp,则is_up置为1(记录此时前一次电压大于Vp的状态)
{
is_up=1;
}
else if(is_up==1&&V/10<Vp)//如果上一次电压V大于Vp,且下一次电压V小于Vp,则计数+1
{
is_up=0;//记录此时电压小于Vp
count++;//计数+1
}
2.连续按下无效按键的处理
如果是按照我之前写代码的习惯的话,我都是在按键处理函数中,先读取按键,再根据读取到的按键的键值,对其进行处理,最后将按键的键值清零。
这里对无效的按键处理也用了类似的方法。如果按下了按键,并且这个按键被某个if else if语句处理了,则将按键的键值清零。如果所有的按键处理都进行完了,并且此时按键的键值还不为0,则说明按下了一个没有被处理的按键,或者说是“无效的按键”,因为它没产生任何效果嘛,此时记录错误按键次数的标志位count_wrong就+1.同时将按键键值清零。如果count_wrong大于三,也就是连续三次都按下了无效的按键,则将点亮L3的标志位置1(题目要求的,连续三次无效按键就点亮L3)。
至于对于按下有效按键的处理那就好办了,只要在按键处理时的每一次处理之后,加上count_wrong清零,以及将点亮L3的标志位置为0即可。这里就把题目中用到的按键操作也都写出来,方便演示对于按下有效按键的处理了。
代码如下:
void get_key(void)
{
unsigned char key_P3=P3;
unsigned char key_P4=P4;
static unsigned char count_wrong=0;//记录连续多少次按错了按键(也就是按下了不被处理的按键)
P3=0xFF;
P4=0xFF;
P44=0;
if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=7;}
else if(P31