📄 main.c
字号:
#include "include.h"
#include "ds12887.h"
#include "p8255.h"
#define open 0x00//打开所有显示位
#define close 0xff//关闭所有显示位
#define first_open 0xdf//显示秒个位
#define secon_open 0xef//显示秒十位
#define three_open 0xf7//显示分个位
#define four_open 0xfb//显示分十位
#define five_open 0xfd//显示时个位
#define six_open 0xfe//显示时十位才
uchar code d2q[]={0x7b,0X30,0Xea,0Xf8,0Xb1,0Xd9,0XDB,0X70,0Xfb,0Xf9};//十进制转换为七段码
uchar data time[7];//时间缓冲
uint data tem;//温度缓冲
uchar data thl1;//定时器1初值
uchar data timch_bitchoose=0;//调时位选
uchar data t1_intrup_time=0;//T1中断次数,用于闪动1分自动退出调时状态
uchar data flash_T=0;//记录一个闪动周期动态显示的次数,用于闪动周期的占空比
/////////////////数码管的闪动亮灭的开关控制变量//////////////////
uchar data six_flash=open;//控制第六位数码管的闪动灭
uchar data five_flash=open;//控制第五位数码管的闪动灭
uchar data four_flash=open;//
uchar data three_flash=open;
uchar data secon_flash=open;//控制第二位数码管的闪动灭
uchar data first_flash=open;//控制第一位数码管的闪动灭
uchar data flash_time=0;//在调时状态下无操作时由调时状态自动退出前闪动的时间
uchar data showtime=0;//控制是显示时间(0)还是显示日期(4)
bit bdata leapyear=0;//记录是否闰年 闰年=1
uchar data showpoint=0x00;//控制在显示日期时显示数点
//中断函数
void Int0_timeset_bit(void);//调时位选
void T1_sec_end(void);//定时50ms,中断响应从12887读取时间送入缓冲区
void T0_time_set(void);//调时值设置,加1
void display(); //显示
void delay(uchar data x);//延迟 x ms
uchar BCD2BIN(uchar data BCD);
uchar BIN2BCD(uchar data BIN);
void keyscan();//扫描8255 C口 键盘,进而判断是显示时间(showtime=0)还是显示日期(showtime=4)
void if_leapyear();//判断是否闰年
//void Init();
main()
{
P8255Con=0x88;//A口方式0输出,B口方式0输出,C口高四位输入,低四位输出
P8255Con=0x88;
TMOD=0X16;//0001 0110,定时器0采用外部计数方式2,定时器1采用定时方式1
TH0=0xfe;
TL0=0XFE;//定时初值,定时器0计1满
thl1=15536;//定时器1定时50ms
IT0=1;//INT0中断采用下降沿
IT1=1;//INT1中断采用下降沿
EX0=1;//外部中断0允许
EX1=1;//外部中断1允许
ET0=1;//定时中断0允许
ET1=1;//定时中断1允许
EA=1;//总中断允许
PT0=0;
PT1=1;//读取时间函数为最高优先级
PX0=0;
PX1=0;
TR0=1;//开启定时器0
TR1=1;
P8255Con=0x88;//A口方式0输出,B口方式0输出,C口高四位输入,低四位输出
P8255Con=0x88;
//P1=0X00;
//SetTime(BIN2BCD(00),BIN2BCD(38),BIN2BCD(17));
//SetDate(0x26,0x06,0x07);
while(1)
{
keyscan();//确定显示时间还是日期
display();//显示
}
}
//////////////////调时位选////////////////////////
void Int0_timeset_bit(void) interrupt 0 using 1//调时位选
{
timch_bitchoose++;//调时位的移位
if(timch_bitchoose==4)//退出调时状态
timch_bitchoose=0;
//根据要调时的位确定各个闪动开关变量的开与闭
switch(timch_bitchoose)
{
case 0:six_flash=0x00;five_flash=0x00;three_flash=0x00;four_flash=0x00;secon_flash=0x00;first_flash=0x00;break;//不是调时状态
case 1:six_flash=0x00;five_flash=0x00;three_flash=0x00;four_flash=0x00;secon_flash=0xff;first_flash=0xff;break;//调秒,闪
case 2:six_flash=0x00;five_flash=0x00;three_flash=0xff;four_flash=0xff;secon_flash=0x00;first_flash=0x00;break;//调分,闪
case 3:six_flash=0xff;five_flash=0xff;three_flash=0x00;four_flash=0x00;secon_flash=0x00;first_flash=0x00;break;//调时,闪
}
}
/////////////////////每50ms从128887读取时间,从ds1820读取温度写入缓冲区//////////////////
void T1_sec_end(void) interrupt 3 using 3//
{ uchar data i;
thl1=15536;//重新赋初值
t1_intrup_time++;
if(t1_intrup_time==20)//满1秒钟
{
t1_intrup_time=0;
flash_time++;
if(flash_time==30)//在调时状态时,如果不操作,则30秒后自动退出调时状态
{
flash_time=0;
timch_bitchoose=0;
}
}
//从12887读取时间送缓冲区
time[0]=GetSeconds();
time[1]=GetMinutes();
time[2]=GetHours();
time[3]=GetDay();
time[4]=GetDate();
time[5]=GetMonth();
time[6]=GetYear();
//从ds1820读取温度
tem=ReadTemperature();
//将BCD码转换为二进制
for(i=0;i<7;i++)
time[i]=BCD2BIN(time[i]);
}
/****************调时状态时,时间修改**************************/
void T0_time_set(void) interrupt 1 using 2//调时值设置
{
flash_time=0;//保证从调时状态自动返回的前提是无调时操作
switch(timch_bitchoose)
{
case 0:break;
case 1:if(showtime==4)
time[0+showtime]++;//调日,
else
time[0+showtime]=0;//调秒清零
break;
case 2:time[1+showtime]++;break;//调分或月
case 3:if(showtime!=4||time[6]!=99)//
time[2+showtime]++;
else
time[2+showtime]=0;
break;//调时或年
}
if(time[0]>=60)//调秒防溢出
time[0]=0;
if(time[1]>=60)//调分防溢出
time[1]=0;
if(time[2]>=24)//调时防止溢出
time[2]=0;
if(time[3]>=8)//调星期防止溢出
time[3]=1;
if(time[5]>=13)//调月防止溢出
time[5]=1;
//调日期防止溢出
if(time[5]==1||time[5]==3||time[5]==5||time[5]==7||time[5]==8||time[5]==10||time[5]==12)//含31天的月份
{
if(time[4]>=32)
time[4]=0;
}
else
{
if(time[5]==4||time[5]==6||time[5]==9||time[5]==11)//30天的月份
{
if(time[4]>=31)
time[4]=0;
}
else //二月是28天还是29天
{
if_leapyear();//判断是否闰年,闰年时leapyear=1
if(leapyear==1)//是闰年
{
if(time[4]>=30)
time[4]=0;
}
else//不是闰年
{
if(time[4]>=29)
time[4]=0;
}
}
}
//将调时后的时间日期写入12887
if(showtime==0)//当前状态是显示时间状态
SetTime(BIN2BCD(time[0])/*秒*/,BIN2BCD(time[1])/*分*/,BIN2BCD(time[2]))/*时*/;
else//当前状态是显示日期
SetDate(BIN2BCD(time[4])/*日*/,BIN2BCD(time[5])/*月*/,BIN2BCD(time[6]))/*年*/;
}
//////////////////////////动态显示时间日期/////////////////////////////
void display() //显示时间
{
uchar data six,five,four,three,secon,first;
//将要显示的数字的各位分离
six=time[2+showtime]/10;
five=time[2+showtime]%10;
four=time[1+showtime]/10;
three=time[1+showtime]%10;
secon=time[0+showtime]/10;
first=time[0+showtime]%10;
//将二进制数转换为七段码
six=d2q[six];
five=d2q[five];
four=d2q[four];
three=d2q[three];
secon=d2q[secon];
first=d2q[first];
if(showtime==4)//当前状态是显示日期
showpoint=0x04;//显示日期时显示数点
else//当前状态是显示时间
showpoint=0x00;//显示时间时不显示数点
if(timch_bitchoose==0)//确保不在调时状态时关闭闪动开关变量使不闪
{
six_flash=0x00;
five_flash=0x00;
three_flash=0x00;
four_flash=0x00;
secon_flash=0x00;
first_flash=0x00;
}
if(flash_T<=15)//若在调时状态,闪,灭
{
P8255B=close;
P8255A=six;
P8255B=six_open|six_flash;
delay(3);
P8255B=close;
P8255A=five|showpoint;//显示日期时显示年与月之间的隔点
P8255B=five_open|five_flash;
delay(3);
P8255B=close;
P8255A=four;
P8255B=four_open|four_flash;
delay(3);
P8255B=close;
P8255A=three|showpoint;//显示日期时显示月与日之间的隔点
P8255B=three_open|three_flash;
delay(3);
P8255B=close;
P8255A=secon;
P8255B=secon_open|secon_flash;
delay(3);
P8255B=close;
P8255A=first;
P8255B=first_open|first_flash;
delay(3);
}
else//若在调时状态,闪,亮
{
P8255B=close;
P8255A=six;
P8255B=six_open;
delay(3);
P8255B=close;
P8255A=five|showpoint;//显示日期时显示年与月之间的隔点
P8255B=five_open;
delay(3);
P8255B=close;
P8255A=four;
P8255B=four_open;
delay(3);
P8255B=close;
P8255A=three| showpoint;//显示日期时显示月与日之间的隔点
P8255B=three_open;
delay(3);
P8255B=close;
P8255A=secon;
P8255B=secon_open;
delay(3);
P8255B=close;
P8255A=first;
P8255B=first_open;
delay(3);
}
flash_T++;//flash_T 记录一个闪动周期内动态显示的次数
if(flash_T==50)//一个闪动周期内动态显示50次,闪动周期大于 50*(3*6)ms
flash_T=0;
}
/*************时间延迟***************************/
void delay(uchar data x)//x为要延迟的时间ms级
{
uchar data j;
while (x-->0)
{
for(j=0;j<125;j++) // 延迟的时间1ms
{;}
}
}
/*********************进制转换***************************/
uchar BCD2BIN(uchar data BCD)
{
unsigned char data tem=0;
tem=BCD&0x0f;
BCD=BCD>>4;
tem+=BCD*10;
return tem;
}
uchar BIN2BCD(uchar data BIN)
{
uchar data shi,ge,BCD;
shi=BIN/10;
ge=BIN%10;
shi=shi<<4;
BCD=shi|ge;
return BCD;
}
/************************************************/
/////////////////////判断是否闰年////////////////////
void if_leapyear()
{
uchar data year;
year=2000+time[6];
if(year%4!=0)
leapyear=0;
else if(year%100!=0)
leapyear=1;
else if(year%400!=0)
leapyear=0;
else
leapyear=1;
}
////////////////////////////键盘输入控制显示时间还是显示日期/////////////////////////
void keyscan()
{
P8255C=0Xc0;
if((P8255C&0xc0)!=0xc0)
{
delay(5);
if((P8255C&0xc0)!=0xc0)
{
if(showtime==0)
showtime=4;//显示日期
else
showtime=0;//显示时间
}
}
while((P8255C&0xc0)!=0xc0) //防止一次按键,多次响应
P8255B=0XFF;
}
/*
//////////////////初始化函数///////////////
void Init()//定时器。中断的初始化
{
TMOD=0X16;//0001 0110,定时器0采用外部计数方式2,定时器1采用定时方式1
TH0=0xfe;
TL0=0XFE;//定时初值,定时器0计1满
thl1=15536;//定时器1定时50ms
//12M Hz 晶振
EX0=1;//外部中断0允许
EX1=1;//外部中断1允许
ET0=1;//定时中断0允许
ET1=1;//定时中断1允许
IT0=1;
IT1=1;//外部中断触发方式
TR1=1; //T1运行
TR0=1; // T0 运行
P8255Con=0x88; //初始化8255 A口输入检测数据 0x82
EA=1; //开中断
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -