这里就不完全写思路过程代码什么的,这一篇文章就写我在训练真题中遇到的过程。
(呜呜呜,时间不够辣,能做多少算多少吧....)
十三届省赛题
问题1:数码管的数字消影不明显
(参考:蓝桥杯单片机开发板的数码管的消影_数码管消除鬼影-CSDN博客)
解决方法:
位选不选择任何数码管(消除影子)->再段选->再位选
或者是
先段选不选中数码管的任何段->再位选->再段选
原来:消影不明显
变成:
同时数码管Display前后显示都用关闭全部数码管,消影效果会更好。
问题2:按键切换模式时不够灵敏
问题3:IO模式下HC138译码器选通问题
经常用到的其实只有4567,其他为了操作方便可以不写,
前后关闭一下译码器会比较好,还可以将选通通道和赋值写在一起,这样比较简洁好看:
问题4 DS1302写入函数的写法:
最后最好还是要加上写操作关闭
问题5 当main函数中的执行的模块化函数过多时
可以将不在while循环里的函数,重新写一个函数放到初始化函数里面。
问题7:一个新的写LED闪烁的写法:
&=表示位与操作,|= 表示位或操作。
-
if((LED & 0x04) == 0x04)
:这里是检查LED的取出第3位是否为1,(为1说明L3熄灭)如果为1则执行LED &= ~0x04
,将LED的第3位清零,即L3点亮;如果为0则执行LED |= 0x04
,将LED的第3位设为1,即L3熄灭。 -
selecthc138(4, LED)
:这个函数应该是用来控制LED的显示,以此来控制LED灯的点亮和熄灭。
if(jdq == 0x10 ) //继电器吸合
{
count_100++
if(count100 == 2) //0.1s
{
count100 == 0
{
if((LED & 0x04 == 0x04))
{
LED &= ~0x04
}
else
{
LED |= 0x04
}
selecthc138(4,LED) //点亮LED灯
}
}
}
问题8:判断继电器吸合与否
这里就是问题3中选译码器时,可以把数据也传进去函数,然后让数据用一个名称来代替,那么判断继电器吸合与否我就判断这个名称的变量即可
比如:if(jdq == 0x10 ) //判断继电器是否是吸合状态
selectHC138(5,jdq) 这就是让继电器吸合
问题9 :计时的一个问题
这次试题有两个计时问题,一个是0.1s L3来回闪烁,一个是5秒,L1亮5s就熄灭停止。
一个是闪烁,一个是亮了一次就停止,等到下一个整点再亮5s又停止。
首先,Delay函数写不出那么长时间,所以必须用定时器,其次,定时器用两个的话太麻烦,
可以只用一个, 这里定时一个单位是50ms。
闪烁的0.1秒就用平时的,一到0.1s就清零,或者是取余。如图:
而5s的可以设置一个F_Time标志表示5s开始,
整点,5s要开始了,F_Time=1;
后面就要判断5s开始,那么就count_5s++,加到100就是0.5s,count_5s清零,同时标志F_Time=0(如果设置标志位直接清0,则即使执行了一次点亮后,没到整点又会继续执行。)
每到整点时,标志位置一,又开始启动5s。
其次,这里的5s内执行继电器等操作,不用<5 执行,>5停止,这里只判断一次,当5s到了就停止.
问题10:读题问题
有点读题的错误:
1. 题目是参数设置界面的温度值应该是初始为23,应该是自己设置的参数,而不是DS13B20测出来的,不然就算按键按下后修改了++ -- 温度,还是会跳回当前的温度,毕竟DS13B20测出来当前是多少就是多少,这是不可以改变的。
第十四届省题
问题1:数码管显示多个界面显示还有某界面还有子界面的情况
首先自己的想法是用两个flag,一个flag表示本来的四个界面,flag1用于转换为第二个界面的子界面,这样是不好显示的我发现,很容易显示子界面时就黑屏。 XXXX
看了小蜜蜂老师的,还是只用一个flag来显示比较好,子界面也成为flag里面的一种情况。然后跳转子界面可以用if ,else if语句。
if ,elseif语句原来是如果if满足就不会再执行下面语句了!所以上面图片flag=5后不会再执行else if。但是if,if语句的话如何第一个if满足,还是会判断下一个if是否满足。
问题2:光敏电阻由亮到暗如何判断
光敏电阻用的是AD转换,是将模拟电压转换为数字电压,所以判断亮暗就变成了判断前后数字大小。
由于涉及到前后,故需要两个变量来储存前后两个状态,然后比较这两个状态的大小。
我本来的思路是两个状态相减不等于0就是有一个转变过程,但烧进去发现就一直是触发状态,这里我感觉有两个错误,1是未审好题,题目是由亮到暗,而不等于0是可能亮到暗也可能暗到亮两种;2是由于每次测量有误差,即使是不挡光,可能测得的每次本来就不太可能一样,所以这个条件总是满足,就总是触发状态。 XXXXX
看了小蜜蜂老师的思路,他是自定义一个阈值为50,>50为亮,<=50为暗
但是其实我是有疑问的,光敏电阻不是光强和阻值成反比吗?光越亮,阻值越小,分压不是越小吗?(但老师的烧进去又是正确的呜呜呜,不管啦!!!明天就比赛啦!!!)
问题3:PC8591的另一种传入函数的写法
之前写PC8591的时候,说过由ADC 和 DA输出函数,(怎么说,还是有点没太理解透...)
就这样写!之前说ADC函数是写在一起的分为写——等待——读——电压转换,现在就分开来,把等待去掉(因为这次试题又说触发小于0.05s,但是我发现触发响应的时间好长,然后就察觉到了是这个Delay函数的原因,拖长了时间,要把它去掉)
ADC函数:
注意:转换电压那里千万别忘了写5.0,.0不能去掉!!!还有公式就记成是转换成 n V的电压来计算。
//将写的这部分独立出来一个函数(然后就去掉Delay)
void Set_PCF(unsigned char AIN)
{
I2CStart();
I2CSendAck(0x90);
I2CWaitAck();
I2CSendAck(AIN); //将AIN作为函数传进来,转换通道比较容易,不用重复写,比如光敏电阻,电位计...
I2CWaitAck();
I2CStop();
}
void Read_PCF()
{
I2CStart();
I2CSendAck(0x91);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
adc_volt = dat * (5.0 / 255);
smg_volt = adc_volt * 100;
}
DA函数:
观察其实就是比ADC中的set(写函数)多了:DA_dat是要输出的电压
I2CSendAck(DA_dat);
I2CWaitAck();
void DA(unsigned DA_dat)
{
I2CStart();
I2CSendAck(0x90);
I2CWaitAck();
I2CSendAck(0x40);
I2CWaitAck();
I2CSendAck(DA_dat);
I2CWaitAck();
I2CStop();
}
问题4 :取最大温度时读取到最大值为初始温度85
这是因为没有去掉初始温度,要写个温度初始化函数,已经在之前的DS13B20中更新了,可以回去看看
就写到这啦!!!明天就比赛了!!!祝我好运叭!!!!!!!!