一. 题目概述
-
目的
设备按照用户通过按键设定的时间间隔自动采集并存储温度数据;
具有采集完成提醒、数码管显示等功能; -
元器件
按键电路、电源供电电路、 RTC 时钟、传感器电路和显示电路组成。 -
具体操作
二. 对问题的解读
-
定义存储空间存储采集的10个温度数据
-
有两个驱动DS18B20(温度传感器)和驱动DS1302(时钟)
-
用一个小技巧便可轻松实现两个提示符的闪烁
-
单列按键,其实就只有S4按键和S5按键实现起来复杂一些
-
需要注意的在实现其中之一的功能时,其他按键的按动不会对其有影响
-
其他部分有模板写成即可
三. 问题的难点
a) 最难的还是单列按键,屡不清思路,就没有办法写好程序。你如何用S4按键调换4种不同的计数时间,这是一个难点;之后S5按键按下了,怎么调换界面,怎么让提示符闪烁;
b) 再者就是采集温度这一块,一共要采集10个数据,要用什么存。
c) 中断怎么写才是最恰当的。
四. 问题的解决
i. 单列按键根据模板即可写出,先分析一下,主要的任务是采集数据,要分为3种状态:采集之前,采集之中,采集之后。定义一个标志位:Cai_start,不过是uchar型的,bit型的只能表示两种状态。之后是第一个按键S4,需要切换4个时间间隔。定义一个标志位:timerc。借助Cai_start标志位,S5按下后就进入到采集的状态。if(P33==0) { delayms(5); if(P33==0) { if(Cai_start==0) { //字节型的输入,一个标志位即可实现 if(timerc==1)timerc=5; else if(timerc==5) timerc=30; else if(timerc==30) timerc=60; else if(timerc==60) timerc=1; } } while(!P33); } else if(P32==0) { delayms(5); if(P32==0) { if(Cai_start==0) { //S5按键按下了,进入参数设定界面 tt=0;//结束时间的累积并打开灯 Cai_start=1; } } while(!P32); }
ii. 提示符的闪烁其实用一个技巧便可,对时间进行取余,奇数亮,偶数灭。
else if(Cai_start==1)//S5按键被按下了
{
DS_get();
yi=shijian[2]/10;er=shijian[2]%10;
si=shijian[1]/10;wu=shijian[1]%10;
qi=shijian[0]/10;ba=shijian[0]%10;
//闪烁 小技巧偶数秒亮
if(shijian[0]%2==0){san=10;liu=10;}
else {san=11;liu=11;}
}
iii. 采集10个温度的值,其实也不难,用一个数组和一个变量即可。写在了定时器里。
if((Cai_start==1)&&(tt==timerc*200))//S5按键按下了,并且进入相应的时间间隔进行采集
{
tt=0;
Save[Save_n]=wendu;//把温度传进来
Save_n++;
if(Save_n==10)//判断有没有记满
{
Cai_start=2;LED_shan=1;Save_n=0;//存满数据则退出,并闪烁
yi=10;er=0;san=0;si=11;wu=11;liu=10;qi=Save[0]/10;ba=Save[0]%10;
}
}
if((Cai_start==2)&&(tt==200))//这是第二种状态已经采集完毕,让灯闪烁
{
tt=0;
if(LED_shan==1)//这一部分是判断闪烁的
{
if(fla==0)
{
fla=1;
P2=0x80;P0=0xfe;
}
else if(fla==1)
{
fla=0;
P2=0x80;P0=0xff;
}
else if(LED_shan==0)
{
yi=10;si=11;wu=11;liu=10;//进入温度采集显示界面
er=Save_n;san=Save_n;
qi=Save[0]/10;ba=Save[0]%10;
Save_n++;//逐一显示
if(Save_n==10)//显示完毕 归0并退出
{
Save_n=0;
Cai_start=3;//这也是是个标志位,表示显示完成
}
}
}
}
iv. 最后就注意一下,在采集的时候,不能被干扰。用if语句判断即可;
void keyscan()
{
if(P33==0)
{
delayms(5);
if(P33==0)
{
if(Cai_start==0)
{
//字节型的输入,一个标志位即可实现
if(timerc==1)timerc=5;
else if(timerc==5) timerc=30;
else if(timerc==30) timerc=60;
else if(timerc==60) timerc=1;
}
}
while(!P33);
}
else if(P32==0)
{
delayms(5);
if(P32==0)
{
if(Cai_start==0)
{
//S5按键按下了,进入参数设定界面
tt=0;//结束时间的累积并打开灯
Cai_start=1;
}
}
while(!P32);
}
else if(P31==0)
{
delayms(5);
if(P31==0)
{
if(Cai_start==2)
{
//显示完毕,让灯灭
LED_shan=0;
P2=0x80;P0=0xff;
}
}
while(!P31);
}
else if(P30==0)
{
delayms(5);
if(P30==0)
{
if(Cai_start==3) Cai_start=0;//任务完毕,返回设置界面
}
while(!P30);
}
}
五.经验总结
面对按键就是设立标志位最为容易简便,但需要对问题的反复研读才能设立好标志位,理清其中的逻辑关系最为重要。在基本的框架搭好后,就需要往里面填一些东西。此时六要读设计要求,进行相应的操作。以前做标志位时,觉得就只有一种类型BIT型,但是就只能显示两种状态,有很大的局限性。当时,只能在这种思维下写题,导致无论用什么办法都没用。后来,我才醒悟过来,标志位也是可以用uchar型的。这时就没有那么多的束缚了,可以表示很多种情形了。思维上有了一定的突破,就开始理逻辑关系,其实每按一次按键就是一次状态的改变,这时就用上了标志位:Cai_start,0表示S4按键按下(采集之前);1表示S5被按下了(采集时);2表示S5按键被按下了(采集好并输出显示);3表示采集完毕进行显示。四种时间的转换,也还是用一个标志位:timerc,直接赋值即可。最后在主函数中进行转化。S5按下后,采集数据,采集好后,让灯1 闪烁。还是用到标志位:fla,实现的。
之后难点在于采集数据的存储,那就定义一个数组:Save[10]存放数据,并搭配一个标志位Save_n,检验是否存满。其中还有一些细节的问题:怎么精确定时,直接调用timerc,并乘以200,就能实现了。存满后,进行判断,并进入下一种状态。
提示符的闪烁用了一个小技巧,直接就用驱动时间中的秒进行判断,对秒进行取余,奇书亮,偶数灭。
此题中还有一个要求:在采集的任意阶段,任意的按键按下,确保不会影响相应的功能。其实这个容易,刚才就用Cai_start标志位,加上if语句进行判定即可。
自己的几点要求:驱动这三大部分已经基本定型,平时需反复进行理解并辅以记忆,便可容易将底层驱动写好。每日除了将模板反复练习外,更为重要的是:将历届做过的真题,亲自打一遍,同样需要反复练习。