代码参考:<我的GitHub>第十届蓝桥杯省赛
emmm,本来我想详细写一下代码的。然后,我写完之后发现要写的好像就只有之前那两篇博客的东西,这届省赛试题跟第八届、第九届相比真的要简单太多,逻辑不是很复杂,底层,也只是一个i2c加一个pcf8591,为什么失败了呢?下面是我的总结:
- 比赛经验不足,客观题部分不能坚持自己的想法,比赛很坑的一点是,客观题部分题目上说的都是多选题,然而,假的,很多题实际上是单选题,只有一个答案,比赛的时候我也感觉到了这一点,但是,可能当时我的心态崩了吧,程序部分写的不太顺利,然后自己有点儿沮丧,然后,就都给改成多选了,所以大概我的客观题没几分。
- 第二个就是关于数据类型的问题,这个我最近的博客里已经写过了,这个问题很重要,大家可以去看看。说到这里,我还是想说,真的感觉心态很重要啊,一定要稳住,,不能急,一急起来啥都忘了,还会犯一堆小错误,赛后想想真的觉得很懊悔,其实自己当时也意识到了这个问题,可是思维好像被圈住了一样,打不开,往错误的方向想了
- 关于LED的控制(也就是LED指示灯的部分):每一种状态下的573都要随开随关,比赛的时候,我为了简化程序,573只开关了一次,然后,灯的状态就出现了问题,会出现本该关闭的小灯仍有微弱亮度的情况,其实这种情况比赛前也遇到过,但是我慌了,现在想想还是觉得心痛,(有哪位大佬有别的方法解决这个问题吗,有的话可以在评论区告诉我一下嘛,o(╥﹏╥)o)
void FrTest()//频率提示
{
if(flagLED == 0)
{
if(cnt < 1000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFD;
P2 |= 0x1F;
}
else if(cnt < 5000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xF5;
P2 |= 0x1F;
}
else if(cnt < 5000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFD;
P2 |= 0x1F;
}
else
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xF5;
P2 |= 0x1F;
}
}
else
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFF;
P2 &= 0x1F;
}
}
- 这次省赛试题还有一个点我觉得要特别注意,比赛时自己也理解错了这一点,赛后重写代码时才被宝宝发现了这个问题,额,还是对题目理解不太透彻,AD和DA的功能概念了解的也不是很清楚,看一下题目要求: 就是要明确一件事,DAC输出电压跟将RB2输出的电压显示到数码管上是两个完全不同的功能! DAC输出电压是用SetDACValue() 这个函数实现的,将RB2输出的电压显示到数码管上是用 GetADCValue() 这个函数加上 RefreshVal() 这个函数实现的!
电压显示界面只显示一个内容:RB2 的输出电压! 比赛的时候自己并没有理解这个点,也是读题不认真的原因,电压显示界面设置了两个,一个是2v电压显示的界面,另一个是RB2输出电压显示界面,其实2v的电压是不需要显示出来的,只是用来初始化DAC输出的!
看一下DAC输出部分的代码:
u8 flagDAC = 0;//0-初始状态,1-RB2
u16 val = 0;//定义一个全局变量,储存读到的ADC通道3的电压值,也就是RB2的输出电压
void SetDAC()
{
u16 InitDAC = 200;//初始化DAC输出电压2v
if(flagDAC == 0)//DAC输出是初始状态
{
SetDACValue(InitDAC);
}
else//DAC输出随RB2改变
{
SetDACValue(val);
}
}
说明一点,通道3的电压值是在刷新显示电压时读的,因为val是一个全局变量,所以只在显示电压处读就可以了
void RefreshVal()
{
u8 i;
val = GetADCValue(3);
for(i = 6; i>2; i--)
{
LedBuff[i] = 0xFF;
}
LedBuff[7] &= 0xC1;
LedBuff[0] = LedChar[val % 10];
LedBuff[1] = LedChar[(val / 10) % 10];
LedBuff[2] = LedChar[(val / 100) % 10];
LedBuff[2] &= 0x7F;
}
这次省赛学到的知识:
1、用好缓冲区!真的贼好使!一定要理解这种思想!这种思想在哪里体现的呢?看题:
就是在实现根据频率改变L4的状态这一功能时体现到的,先看一下我写的显示频率的代码,我是利用到了定时/计数器0的计数功能,P34口是定时器0的脉冲输入端口,只要P34口输入一个高电平的脉冲,计数器模式下就会自动加一,这也是频率显示的原理:
u32 cnt = 0;//记录脉冲个数
void ConfigTimer0()
{
TH0 = 0xFF;
TL0 = 0xFF;
TMOD &= 0xF0;
TMOD |= 0x04;
ET0 = 1;
TR0 = 1;
}
void InterruptTimer0()interrupt 1
{
cnt++;
}
利用cnt来记录脉冲个数,然后再一秒清0,得到的就是频率了。
if(flag1s)
{
flag1s = 0;
cntBuf = cnt;//定义一个缓冲变量存储某一秒的频率
ShowNumber(cntBuf);
LedBuff[7] &= LedChar[15];
cnt = 0;
}
这里为什么要定义一个缓冲变量呢?我们知道cnt的值是不断变化的,我们可以用一个不断变化的量去和一个固定值比较吗?显然不可以!如果用cnt直接去比较呢?那么L4 的状态就会是不稳定的,我的现象就是L4会是一闪一灭的状态
void FrTest()//频率提示
{
if(flagLED == 0)
{
if(cntBuf < 1000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFD;
P2 &= 0x1F;
}
else if(cntBuf < 5000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xF5;
P2 &= 0x1F;
}
else if(cntBuf < 10000)
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFD;
P2 &= 0x1F;
}
else
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xF5;
P2 &= 0x1F;
}
}
else
{
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFF;
P2 &= 0x1F;
}
}
2、只要是不需要实时刷新,实时显示的部分,也就是说让人视觉上可以看出即可的部分,例如电压的刷新显示,LED指示灯的部分,都要放在200ms里面,每200ms刷新显示一次就可以了,一直刷新会出问题!