一. 题目概述
- 目的
单片机采集 DS18B20温度传感器的输出信号, 并送到数码管进行显示;
通过传感器得到的温度数据将与用户设定温度上限、下限值做比较, 再由单片机启动控制或报警电路 - 元器件
系统硬件部分主要由单片机最小系统、数码管显示、 DS18B20 温度传感器、矩阵键盘等模块组成。 - 具体操作
二. 对问题的解读
-
最小系统就是由各个功能部分组成
-
只有一个驱动DS18B20(温度传感器)
-
报警电路由继电器和灯2的亮灭情况组成,由中断精准定时
-
3*4的矩阵按键,其实就只有两个特殊的按键,就是设置和删除键
-
其他部分有模板写成即可
三. 问题的难点
a) 最难的还是矩阵按键,这在历届赛题中只出现过一次。实际上并不是特别难,难在了设置和删除这两个键的操作上,如何根据要求进行设置。
b) DS18B20(温度传感器)也是首次做题遇到,但它与前两个驱动的改法差不多。
c) 如何逐一赋值给数码管值。
四. 问题的解决 -
3*4的矩阵按键根据模板即可写出,但中间还有一些细节内容要加以变动。那便是设置和清除的按键
i. 设置按键需要定义一个标志位:shezhi,目的在于:方便以后区分按键的按下,进入相应的模式。一下只列子函数和主函数的部分:case 0xb7: if(shezhi==0)//进入更改界面 { shezhi=1; ET0=0;EA=0; P2=0x80;P0=0xff;P2=0xa0;P0=0xff; yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11; } else if(shezhi==1) { shezhi=0; ET0=1;EA=1; P2=0x80;P0=0xff; //存进上下线的值 max=er*10+san; min=qi*10+ba; } break; ii. if(shezhi==0)//设置按键没有被按下 { //读取温度穿感器的值 wendu=temget(); // qi=wendu%100/10; // ba=wendu%10; //判定不同的状态 这一部分已经完成 if(wendu<min) { qujian=0; P2=0xa0;P0=0x00; } else if((wendu>=min)&&(wendu<=max)) { qujian=1; P2=0xa0;P0=0x00; } else if(wendu>max) { qujian=2; P2=0xa0;P0=0x10;//打开继电器 } yi=10;er=qujian;san=10;si=11;wu=11;liu=11;qi=wendu/10;ba=wendu%10; } else if(shezhi==1)//设置按键被按下了 { if(qinchu==1) { qinchu=0; yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11; } if((er==11)&&(flag==1))//上电的时候还没有按下按键所以FLAG=0 { flag=0; er=num; } else if((san==11)&&(flag==1))//flag表示再次按下 { flag=0; san=num; } else if((qi==11)&&(flag==1)) { flag=0; qi=num; } else if((ba==1)&&(flag==1)) { flag=0; ba=num; //在写完最后一位时,检验是否有问题 if((qi*10+ba)>(er*10+san)) { yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11; P2=0x80;P0=0xfd; } } }
iii. 其实清除没有什么变化,下面只说明主函数的内容。如何在数码管上逐一写入值?因为只有一个num可供写入,所以还是要设置一个标志位:flag.
以第二个按键为例:先是判断二键是否恒等于1,再是以标志位判定是否被按下了。
if((er==11)&&(flag==1))//上电的时候还没有按下按键所以FLAG=0
{
flag=0;
er=num;
}
同样的我在写定时期时,也同样是一个道理:先是到了某一个区间,再是达到了设定的时间:
if(qujian==0)
{
if(tt==160)
{
tt=0;
//以下这两行还是用的标识位的方法,灯才进行闪烁
if(fla==0) {fla=1;P2=0x80;P0=0xfe;}
else if(fla==1){fla=0;P2=0x80;P0=0xff;}
}
}
iv. DS18B20驱动的更改
需要注意的是,里面的延时有问题,原因也在于51比52的快了8-12倍,解决的办法是:每一个延时*10倍即可。下面的就是一些常规的增加内容:
//1 写读的函数
unsigned char Tempget(void)
{
unsigned char low,high,temp;//这是转化温度的中间变量
init_ds18b20();//初始化
Write_DS18b20(0xcc);//在对寄存器进行配置
Write_DS18B20(0x44);//关闭一些功能,开一些功能
Delay_OneWire(200);
//以上基本完成读的功能
//下面需要对温度进行转换 ,将转化完成的温度读取出来
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
//总是16位的,前四位因为是小数点所以不用
low=Read_DS18B20();
high= Read_DS18B20();
temp=high<<4;//向左移4位的原因在于,高四位是用不了的,那是小数点,低四位是正负
temp|=(low>>4);//向右移4位是将其舍去
return temp;
}
五.经验总结
现在写真题时,有了一些感觉。按照以往的思路,可以把大部分的功能实现。但总会在键盘这里卡住,需要多读几遍设计要求,缕清其中的逻辑关系,方可码代码。这次写赛题,我已将一部分的按键加以实现了。也与后面的答案不谋而合,但没有将其实现。原因在于:我并没有将其看作是一个整体,而是将其分散的实现功能。没有将这些通过按键将其串成一个系统,从而没有完整的实现其功能。
还是矩阵按键的问题:倒不是写不出矩阵按键,而是用矩阵按键实现一系列的操作有点难度。我遇到的第一个问题便是:可以切换两个界面了,但是如何赋值,而且是一一赋值。第二个问题是:如何区别每一个区间,而不是单一的赋值。第三个问题是:如何将那两个按键加以区分。这些问题都可以用一个老的套路来实现,设立一个标志位。但是如何实现还是一大关?需要仔细揣摩设计要求,理清其中的逻辑结构:先是最外边一层结构:就是设置按键的按下(shezhi),检验是否按下;之后是,在未被按下之前,检验处于哪一模式(qujian,wendu);接着就是被按下了,进入设置界面,按键和标志位(flag)联合作用,逐一输入值。最后,则是检验是否出错和清除。
驱动这三大部分已经基本定型,平时需反复进行理解并辅以记忆,便可容易将底层驱动写好。
每日除了将模板反复练习外,更为重要的是:将历届做过的真题,亲自打一遍,同样需要反复练习。