这里的代码是主文件的代码,其他的头文件之前已经提供,下面的代码仅提供思路,不提供原理,如有错误请及时留言提醒。
#include <stc15f2k60s2.h>
#include <intrins.h>
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
typedef unsigned int uint;
code uchar TAB[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf, 0xc6, 0x86, 0x8c};//显示1-9 灭 - C E P
uchar tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8;
uchar key, sec, min, hour, AD;
uint temp;
uint dat_t;
bit AD_state, time_state, temp_state;
uchar function;//显示功能变量
bit light;//亮,暗状态
bit set;//数据参数界面切换标志位
uchar hour_set = 17, temp_set = 25, led_set = 4;//小时参数为17 温度参数为25 LED指示灯参数为4
uchar led = 0xff;//存放led的状态
bit use = 1;//数据界面标志位,为0时处于参数界面,应题目要求所以参数均在退出参数界面时生效
uint time_3s;//持续时间计时
bit time3, time, light_tem;//达到3s时间标志位,开始计时标志位,临时存放上一个亮暗状态(方便比较)
void delay(uint z)//延时函数
{
uint x, y;
for(x=z; x>0; x--)
for(y=845; y>0; y--);
}
void timer_int()//定时器初始,一般是手写放在这里面
{
EA = 1;
TR0 = 1;//定时器0,16位,定时1ms,定时中断
ET0 = 1;
TMOD |= 0X01;
TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256;
}
void display()//显示函数,配合定时器0中断使用,达到循环扫描
{
static uchar i;//定义静态变量i
switch(i)
{
case 0: P2=0XC0; P0=0X01; P2=0XE0; P0=TAB[tab1]; i=1; break;
case 1: P2=0XC0; P0=0X02; P2=0XE0; P0=TAB[tab2]; i=2; break;
case 2: P2=0XC0; P0=0X04; P2=0XE0;
if(function==2) P0=TAB[tab3]&0x7f; else P0=TAB[tab3];//判断处于亮暗状态显示界面下,在第3位数码管上增加小数点
i=3; break;
case 3: P2=0XC0; P0=0X08; P2=0XE0; P0=TAB[tab4]; i=4; break;
case 4: P2=0XC0; P0=0X10; P2=0XE0; P0=TAB[tab5]; i=5; break;
case 5: P2=0XC0; P0=0X20; P2=0XE0; P0=TAB[tab6]; i=6; break;
case 6: P2=0XC0; P0=0X40; P2=0XE0;
if(function==1) P0=TAB[tab7]&0x7f; else P0=TAB[tab7];//判断处于温度显示界面下,在第7位数码管上增加小数点
i=7; break;
case 7: P2=0XC0; P0=0X80; P2=0XE0; P0=TAB[tab8]; i=0; break;
}
}
void key_scan()//四分之一 矩阵键盘扫描,常用需要理解记住
{
key = 0;//按键标志清零,每循环一次清除一次,在判断按键里面就不用再清零
P44 = 1; P42 = 1; P33 = 0; P32 = 0;
if((P44==0)|(P42==0))
{
P44 = 1; P42 = 1; P33 = 0; P32 = 0;//当控制的IO口不多时,可以直接位操作
delay(2);
if((P44==0)|(P42==0)) //判断纵列按键
{
if(P44==0) key = 4;
if(P42==0) key = 8;
}
P44 = 0; P42 = 0; P33 = 1; P32 = 1;
if((P33==0)|(P32==0))
{
P44 = 0; P42 = 0; P33 = 1; P32 = 1;
delay(2);
if((P33==0)|(P32==0)) //判断行列按键
{
if(P33==0) key += 0;
if(P32==0) key += 1;
}
}
while((P33==0)|(P32==0));//判断抬手
}
}
void time_read()//时间读取函数
{
EA = 0;//读取时间时,要关闭中断
Write_Ds1302_Byte(0x8e,0x00);
sec = Read_Ds1302_Byte(0x81);
min = Read_Ds1302_Byte(0x83);
hour = Read_Ds1302_Byte(0x85);
Write_Ds1302_Byte(0x8e,0x80);
EA = 1;//读取完成,必须打开中断
}
void initialize()//初始化函数
{
P2=0XA0; P0=0X00; P2=0X80; P0=0XFF;
Write_Ds1302_Byte(0x8e,0x00);//写入DS1302,时间 16-59-50
Write_Ds1302_Byte(0x80,50);
Write_Ds1302_Byte(0x82,59);
Write_Ds1302_Byte(0x84,16);
Write_Ds1302_Byte(0x8e,0x80);
timer_int();//定时器0初始化
}
void key_function()//按键功能函数
{
key_scan();//按键扫描
if(key==5)//切换按键
{
if(set==0)//切换数据界面
{
if(function==0) function = 1;
else if(function==1) function = 2;
else if(function==2) function = 0;
}
else //切换参数界面
{
if(function==3) function = 4;
else if(function==4) function = 5;
else if(function==5) function = 3;
}
}
else if(key==4)//界面按键
{
if(set==0) { set = 1; function = 3; use = 0; }//每次从数据界面进入参数界面,默认当前为时间参数
else { set = 0; function = 0; use = 1; }//每次从参数界面进入数据界面,默认当前为世界数据
}
else if(key==8)//减按键
{
if(function==3) { if(hour_set!=0) hour_set--; }//注意设置下限
else if(function==4) { if(temp_set!=0) temp_set--; }
else if(function==5) { if(led_set!=4) led_set--; }
}
else if(key==9)//加按键
{
if(function==3) { if(hour_set!=23) hour_set++; }//注意设置上限
else if(function==4) { if(temp_set!=99) temp_set++; }
else if(function==5) { if(led_set!=8) led_set++; }
}
}
void dat_read()//定时读取数据函数
{
if(time_state==1) //定时读取时间
{
time_state = 0; time_read();
if(use==1)
{
if((hour_set<=hour)|(hour<=8)) { P2 = 0X80; led &= 0xfe; P0 = led; }//判断当前时间处于小时参数整点至下一个8时之间
else { P2 = 0X80; led |= 0x01; P0 = led; }
}
}
else if(AD_state==1) //定时读取电压
{
AD_state = 0; AD = AD_read(0x01);
if(AD>=100) //判断是否未遮挡
{
light = 0; //亮状态
if(use==1)
{
switch(led_set)//指定的LED指示灯熄灭
{
case 4: P2 = 0X80; led |= 0x08; P0 = led; break;
case 5: P2 = 0X80; led |= 0x10; P0 = led; break;
case 6: P2 = 0X80; led |= 0x20; P0 = led; break;
case 7: P2 = 0X80; led |= 0x40; P0 = led; break;
case 8: P2 = 0X80; led |= 0x80; P0 = led; break;
}
}
}
else //判断是否遮挡
{
light = 1; //暗状态
if(use==1)
{
switch(led_set)//指定的LED指示灯点亮
{
case 4: P2 = 0X80; led &= 0xf7; P0 = led; break;
case 5: P2 = 0X80; led &= 0xef; P0 = led; break;
case 6: P2 = 0X80; led &= 0xdf; P0 = led; break;
case 7: P2 = 0X80; led &= 0xbf; P0 = led; break;
case 8: P2 = 0X80; led &= 0x7f; P0 = led; break;
}
}
}
if(time3==1)//判断是否持续时间超过3s
{
time3 = 0;
if(light==1) { P2 = 0X80; led &= 0xfb; P0 = led; }//点亮L3
else { P2 = 0X80; led |= 0x04; P0 = led; } //熄灭L3
}
if(light_tem!=light) time = 1;//判断状态改变,开始在定时器0中断中计时,第一次判断要是环境处于暗状态,才能看到现象
else { time_3s = 0; time = 0; }//其他情况清零,为下次判断做准备
}
else if(temp_state==1) //定时读取温度
{
temp_state = 0; temp = temp_read();
if(use==1)
{
if(temp<(temp_set*10)) { P2 = 0X80; led &= 0xfd; P0 = led; }//判断采集到的温度数据小于温度参数
else { P2 = 0X80; led |= 0x02; P0 = led; }
}
}
}
void dat_display()//数据显示函数
{
if(function==0)//时间显示界面
{
tab1=hour/10; tab2=hour%10; tab3=11; tab4=min/10; tab5=min%10; tab6=11; tab7=sec/10; tab8=sec%10;
}
else if(function==1)//温度数据 显示界面
{
tab1=12; tab2=10; tab3=10; tab4=10; tab5=10; tab6=temp/100; tab7=temp%100/10; tab8=temp%10;
}
else if(function==2)//亮,暗状态 显示界面
{
tab1=13; tab2=10; tab3=AD/100; tab4=AD%100/10; tab5=AD%10; tab6=10; tab7=10; tab8=light;
}
else if(function==3)//时间参数 设置界面
{
tab1=14; tab2=1; tab3=10; tab4=10; tab5=10; tab6=10; tab7=hour_set/10; tab8=hour_set%10;
}
else if(function==4)//温度参数 设置界面
{
tab1=14; tab2=2; tab3=10; tab4=10; tab5=10; tab6=10; tab7=temp_set/10; tab8=temp_set%10;
}
else if(function==5)//指示灯参数 设置界面
{
tab1=14; tab2=3; tab3=10; tab4=10; tab5=10; tab6=10; tab7=10; tab8=led_set;
}
}
void main()
{
initialize();//初始化
while(1)
{
key_function();//按键功能
dat_read();//数据读取
dat_display();//数据显示
}
}
void timer0_display()interrupt 1
{
TH0 = (65536-1000)/256;//定时器0装载
TL0 = (65536-1000)%256;
display(); //数码管扫描显示
dat_t++;
if(dat_t==50) AD_state = 1;
else if(dat_t==150) time_state = 1;
else if(dat_t==250) temp_state = 1;
else if(dat_t==300) dat_t = 0;
if(time==1)//开始计时持续时间
{
if(++time_3s==3000)//计时3000ms
{
time_3s = 0;
time3 = 1; //计时完成
light_tem = light; //重新赋值新的状态
}
}
}