程序设计流程
综述
第六届初赛赛题除了基础的独立按键、数码管显示、继电器和蜂鸣器的控制、LED灯的控制以外,难度增加的部分体现在ds18b20和ds1302的调用,同时对于LED灯和数码管的闪烁需要加以控制。
本解析不代表标准答案或官方答案,仅做分享。若有不足或是更好的写法,望在评论区进行指正!
模板搭建
基础的功能:
1、独立按键
2、数码管显示
可以独立于赛题,提前写好,适用于各类赛题,仅做修改即可。
模板部分代码与解释在第三届赛题分享中
模板代码
程序设计
ds1302和ds18b20
ds1302的调用参考第四届赛题
链接
ds18b20的调用参考第五届赛题
链接
系统设计
在系统设计的时候,尽量避免对P2的重复操作。第三届系统设计示例
此题的难点在于,如何控制标识码1秒闪烁一次。处理这个问题的方法有很多,比如用定时器、判断0位变化等。笔者这里采用后者。用preSec
作为标志,每个循环判断一次时序芯片返回得到的当前时刻的秒位有没有发生变化,如果发生了变化则sec
自增,代表过了一秒。避免了使用定时器。
而如何判断是否到达了记录数据的时间点,也可以通过定时器来判断,而笔者这里用sec来记录了距离开始时刻过去了多少秒,所以可以通过sec来判断是否该进行记录。
该题不同于前面几届赛题,属于第一次出现了三种模式的切换,需要相应作出一些调整,还是要尽量避免对P2的修改。
主函数代码:
#include <stc15f2k60s2.h>
#include <intrins.h>
#include <ds18b20.h>
#include <ds1302.h>
#define uchar unsigned char
uchar keyPress[4] = {0, 0, 0, 0};
uchar keyPressFlag[4] = {0, 0, 0, 0};
uchar code shapeOfNum[11] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xbf};
uchar numGrp[8] = {11, 0, 5, 0, 0, 0, 0, 0};
uchar oriTime[7] = {50, 59, 23, 3, 2, 7, 19};
uchar nowTime[7] = {0, 0, 0, 0, 0, 0, 0};
int timeInte[4] = {1, 5, 30, 60};
uchar tempGet[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uchar preL1 = 0, L1 = 0;
int count = 0;
void Delay1ms(){
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void Delay5ms(){
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void openP2(uchar num){
P2 &= 0x1f;
P2 |= (num << 5);
}
void showNum(){
uchar i;
for(i = 0; i < 8; i ++){
if(numGrp[i] != 11){
openP2(6);P0 = (0x01 << i);
openP2(7);P0 = shapeOfNum[numGrp[i]];
Delay1ms();
}
}
openP2(6);P0 = 0x00;
}
void keyScan(){
uchar i;
for(i = 0; i < 4; i ++) keyPress[i] = 0;
if((P3 & 0x0f) != 0x0f){
Delay5ms();
if((P3 & 0x0f) != 0x0f){
switch(P3 & 0x0f){
case 0x0e:keyPressFlag[0] = 1;break;
case 0x0d:keyPressFlag[1] = 1;break;
case 0x0b:keyPressFlag[2] = 1;break;
case 0x07:keyPressFlag[3] = 1;break;
}
}
}
for(i = 0; i < 4; i ++){
if(keyPressFlag[i] != 0){
if((P3 & 0x0f) == 0x0f){
keyPress[i] = 1;
keyPressFlag[i] = 0;
}
}
}
}
void writeTime(){
uchar i, add, dat;
for(i = 0; i < 7; i ++){
add = 0x80 + i * 2;
dat = ((oriTime[i] / 10) << 4) + (oriTime[i] % 10);
Write_Ds1302(add,dat);
}
}
void readTime(){
uchar i, dat, add;
for(i = 0; i < 7; i ++){
add = 0x81 + i * 2;
dat = Read_Ds1302 (add);
nowTime[i] = (dat >> 4) * 10 + (dat & 0x0f);
}
}
uchar getTemp(){
uchar high, low;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(20);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
return ((high << 4) | (low >> 4));
}
void Timer0Init(void){
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void timer0() interrupt 1{
if(count == 1000){
count = 0;
L1 = !L1;
}
count ++;
}
void main(){
uchar mod = 0, preMod = 2;
uchar inte = 0;
uchar sym = 10, preSec = 0, tempNum = 0;
uchar index = 0;
int sec = 0;
P2 = 0xa0;P0 = 0x00;
P2 = 0x80;P0 = 0xff;
EA = 1;ET0 = 0;
getTemp();
//由于该函数第一次调用的时候采集的温度是异常数据,所以初始化的时候调用一次。
while(1){
keyScan();
if(mod == 0){//参数设置模式
if(preMod == 2){
inte = 0;
preMod = 0;
}
numGrp[0] = 11;
numGrp[1] = 11;
numGrp[2] = 11;
numGrp[3] = 11;
numGrp[4] = 11;
numGrp[5] = 10;
numGrp[6] = timeInte[inte] / 10;
numGrp[7] = timeInte[inte] % 10;
if(keyPress[3] == 1){
inte = (inte + 1) % 4;
}
if(keyPress[2] == 1){
mod = 1;
}
}
else if(mod == 1){//计时模式
if(preMod == 0){
writeTime();
preSec = oriTime[0] % 10;
sec = 0;
sym = 11;
tempNum = 0;
preMod = 1;
}
readTime();
if((nowTime[0] % 10) != preSec){//当发生了一秒跳转时
if(sym == 10) sym = 11;
else sym = 10;
sec ++;
if((sec % timeInte[inte]) == 0){
tempGet[tempNum ++] = getTemp();
if(tempNum == 10) mod = 2;
}
preSec = (nowTime[0] % 10);
}
numGrp[0] = nowTime[2] / 10;
numGrp[1] = nowTime[2] % 10;
numGrp[2] = sym;
numGrp[3] = nowTime[1] / 10;
numGrp[4] = nowTime[1] % 10;
numGrp[5] = sym;
numGrp[6] = nowTime[0] / 10;
numGrp[7] = nowTime[0] % 10;
}
else if(mod == 2){//温度查看模式
if(preMod == 1){
index = 0;
count = 0;
L1 = 0;
Timer0Init();
ET0 = 1;
preMod = 2;
}
if(L1 == 1){
if(preL1 == 0){
openP2(4);P0 = 0xfe;openP2(0);
preL1 = 1;
}
}
else{
if(preL1 == 1){
openP2(4);P0 = 0xff;openP2(0);
preL1 = 0;
}
}
if(keyPress[1] == 1){
ET0 = 0;
if(L1 == 1){
openP2(4);P0 = 0xff;openP2(0);
L1 = 0;
}
if(index < 9) index ++;
}
if(keyPress[0] == 1) mod = 0;
numGrp[0] = 10;
numGrp[1] = 0;
numGrp[2] = index;
numGrp[3] = 11;
numGrp[4] = 11;
numGrp[5] = 10;
numGrp[6] = tempGet[index] / 10;
numGrp[7] = tempGet[index] % 10;
}
showNum();
}
}