|
#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit lcden=P2^5;//液晶使能
sbit lcdrw=P2^4;//液晶读写
sbit lcdrs=P2^3;//液晶命令/数据
sbit ds1302rst=P2^0;//1302复位端
sbit ds1302clk=P2^1;//1302时钟输入
sbit ds1302io=P2^2;//1302IO口
sbit key1=P1^2;//功能选择键
sbit key2=P1^3;//数值增加键
sbit key3=P1^4;//数值减少键
sbit key4=P1^5;//启动确认键
sbit key5=P1^6;//12/24小时切换键
sbit key6=P1^7;
sbit key7=P1^1;//闹钟设置
sbit beep=P1^0;
char year=10,mon=9,day=8;hou=14,min=33,sec=12;
char naohou=20,naomin=25;
u8 key1pushflag,key2pushflag,key3pushflag,key4pushflag,key5pushflag=0,key6pushflag=0;//定义按键1,2,3,4,5标志位
u8 countkey1,runmode=1,naomode=0,countkey2=0;//按键1标志,运行标志位
u8 init_display1[]="2010-09-08";
u8 init_display2[]="14:33:12";
void delay(u16 ms){
u8 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
//液晶显示模块
void write_com(u8 com){//写命令
lcdrs=0;
lcden=0;
lcdrw=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(u8 date){//写数据
lcdrs=1;
lcden=0;
lcdrw=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init_lcd(){//初始化显示函数
u8 num;
lcden=0;
write_com(0x38); //设置16*2行显示,5*7点阵,8位数据口
write_com(0x0c); //开显示,不显示光标
write_com(0x06); //写一个字符后地址自动加一
write_com(0x01); //显示清零,数据指针清零
write_com(0x80+0x03); //第一行起始地址
for(num=0;num<10;num++){
write_date(init_display1[num]);
delay(5);
}
write_com(0x80+0x42); //第二行起始地址
for(num=0;num<9;num++){
write_date(init_display2[num]);
delay(5);
}
}
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
write_com(0x80 + x);
}
else
{
write_com(0xC0 + x);
}
write_date( Data);
}
void write_dat_to_lcd(u8 add,u8 dat){
u8 ge,shi;
ge=dat%10;
shi=dat/10;
write_com(0x0c);
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void ds1302_write_byte(u8 dat){//1302写一字节函数
u8 temp,num1;
temp=dat;
ds1302rst=1;
for(num1=0;num1<8;num1++){
ds1302io=temp&0x01;
ds1302clk=0;
ds1302clk=1;
temp=temp>>1;
}
}
u8 ds1302_read_byte(){//1302读一字节函数
u8 num,temp;
ds1302rst=1;
for(num=0;num<8;num++){
if(ds1302io)
temp=temp|0x80;
else
temp=temp&0x7f;
ds1302clk=1;
ds1302clk=0;
temp=temp>>1;
}
return temp;
}
void ds1302_write_add_dat(u8 address,u8 dat){//向ds1302特定地址写入一字节数据
ds1302rst=0;
ds1302clk=0;
ds1302rst=1;
ds1302_write_byte(address);
ds1302_write_byte(dat);
ds1302clk=1;
ds1302rst=0;
}
u8 ds1302_read_add_dat(u8 address,u8 dat){//向ds1302特定地址读入一字节数据
u8 temp;
ds1302rst=0;
ds1302clk=0;
ds1302rst=1;
ds1302_write_byte(address);//先写地址再读数据
temp=ds1302_read_byte();
ds1302clk=1;
ds1302rst=0;
return temp;
}
u8 BCD_Decimal(u8 bcd){//BCD码转十进制
u8 Decimal;
Decimal=bcd>>4;
return (Decimal=Decimal*10+(bcd&=0x0f));
}
void init_ds1302(){
ds1302rst=0;
ds1302clk=0;
ds1302_write_add_dat(0x8e,0x00);
}
//按键模块
void keyscan(){
if(key1==0){//加速键
delay(5);
if(key1==0){//功能按键
while(!key1);
runmode=0;
key1pushflag=1;//功能按键按下,万年历设置状态
countkey1++;//年月日时分秒设置
if(countkey1>6)
countkey1=1;
}
}
if(key7==0){//闹钟模式
delay(5);
if(key7==0){
while(!key7);
naomode=1;
key6pushflag=1;
countkey2++;
if(countkey2>1)
countkey2=0;
}
}
if(key1pushflag==1||key6pushflag==1){
if(key2==0){//加键
delay(5);
if(key2==0){
while(!key2);
key2pushflag=1;
}
}
if(key3==0){//减键
delay(5);
if(key3==0){
while(!key3);
key3pushflag=1;
}
}
if(key4==0){
delay(5);
if(key4==0){
while(!key4);
key4pushflag=1;
key1pushflag=0;
key6pushflag=0;
}
}
}
if(key5==0){//12/24小时切换键
delay(5);
if(key5==0){
while(!key5);
key5pushflag=1;
}
}
if(key6==0){//12/24小时切换键
delay(5);
if(key6==0){
while(!key6);
key5pushflag=0;
}
}
}
//按键处理
void keyhandle(){
u8 temp;
switch(countkey1){
case 1: //功能按键按一次,年数据处理
write_com(0x80+0x05);//光标处于年的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
year++;
if(year>99)
year=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x05,year);//显示增加数字
write_com(0x80+0x05); //光标回到年起始位置
}
else if(key3pushflag==1){
year--;
if(year<0)
year=99;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x05,year);//显示减少数字
write_com(0x80+0x05); //光标回到年起始位置
}
break;
case 2:
write_com(0x80+0x08);//光标处于月的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
mon++;
if(mon>12)
mon=1;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x08,mon);//显示增加数字
write_com(0x80+0x08); //光标回到月起始位置
}
else if(key3pushflag==1){
mon--;
if(mon<0)
mon=12;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x08,mon);//显示减少数字
write_com(0x80+0x08); //光标回到月起始位置
}
break;
case 3:
write_com(0x80+0x0b);//光标处于日的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
day++;
if(day>30)
day=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x0b,day);//显示增加数字
write_com(0x80+0x0b); //光标回到日起始位置
}
else if(key3pushflag==1){
day--;
if(day<1)
day=30;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x0b,day);//显示减少数字
write_com(0x80+0x0b); //光标回到日起始位置
}
break;
case 4:
write_com(0x80+0x42);//光标处于时的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
hou++;
if(hou>23)
hou=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x42,hou);//显示增加数字
write_com(0x80+0x42); //光标回到时起始位置
}
else if(key3pushflag==1){
hou--;
if(hou<0)
hou=23;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x42,hou);//显示减少数字
write_com(0x80+0x42); //光标回到时起始位置
}
break;
case 5:
write_com(0x80+0x45);//光标处于分的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
min++;
if(min>59)
min=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x45,hou);//显示增加数字
write_com(0x80+0x45); //光标回到分起始位置
}
else if(key3pushflag==1){
min--;
if(min<0)
min=59;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x45,min);//显示减少数字
write_com(0x80+0x45); //光标回到分起始位置
}
break;
case 6:
write_com(0x80+0x48);//光标处于秒的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
sec++;
if(sec>59)
sec=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x48,sec);//显示增加数字
write_com(0x80+0x48); //光标回到秒起始位置
}
else if(key3pushflag==1){
sec--;
if(sec<0)
sec=59;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x48,sec);//显示减少数字
write_com(0x80+0x48); //光标回到秒起始位置
}
break;
}
if(key4pushflag==1){
temp=sec/10*16+sec%10;//秒钟数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x80,temp); //将秒钟数据写入1302秒钟寄存器
temp=min/10*16+min%10;//分钟数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x82,temp); //将秒钟数据写入1302秒钟寄存器
temp=hou/10*16+hou%10;//时钟数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x84,temp); //将秒钟数据写入1302秒钟寄存器
temp=day/10*16+day%10;//日数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x86,temp); //将秒钟数据写入1302秒钟寄存器
temp=mon/10*16+mon%10;//月数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x88,temp); //将秒钟数据写入1302秒钟寄存器
temp=year/10*16+year%10;//年数据变成BCD码
ds1302_write_add_dat(0x8e,0x00);//禁止DS1302写保护
ds1302_write_add_dat(0x8c,temp); //将秒钟数据写入1302秒钟寄存器
write_com(0x0c);
key4pushflag=0;
runmode=1;
}
}
void naozhongmozhi(void){
u8 temp;
switch(countkey2){
case 0:
write_com(0x80+0x42);//光标处于时的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
naohou++;
if(naohou>23)
naohou=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x42,naohou);//显示增加数字
write_com(0x80+0x42); //光标回到时起始位置
}
else if(key3pushflag==1){
naohou--;
if(naohou<0)
naohou=23;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x42,naohou);//显示减少数字
write_com(0x80+0x42); //光标回到时起始位置
}
break;
case 1:
write_com(0x80+0x45);//光标处于分的位置
write_com(0x0f);//光标闪烁
if(key2pushflag==1){//增加按键按下
naomin++;
if(naomin>59)
naomin=0;
key2pushflag=0;//清除按键标志,放置按1次该键,数值一直增加
write_dat_to_lcd(0x45,naomin);//显示增加数字
write_com(0x80+0x45); //光标回到分起始位置
}
else if(key3pushflag==1){
naomin--;
if(naomin<0)
naomin=59;
key3pushflag=0;//清除按键标志,放置按1次该键,数值一直减少
write_dat_to_lcd(0x45,naomin);//显示减少数字
write_com(0x80+0x45); //光标回到分起始位置
}
break;
}
if(key4pushflag==1){
write_com(0x0c);
key4pushflag=0;
naomode=0;
}
}
void shijianmoshiqiehuan(void){
if(key5pushflag==1){
if(hou>12){
hou=hou-12;
LCD_Write_Char(10,1,'P');
LCD_Write_Char(11,1,'M');
}
else{
hou=hou;
LCD_Write_Char(10,1,'A');
LCD_Write_Char(11,1,'M');
}
write_dat_to_lcd(0x48,sec);//把秒送入液晶
write_dat_to_lcd(0x45,min);
write_dat_to_lcd(0x42,hou);
write_dat_to_lcd(0x0b,day);
write_dat_to_lcd(0x08,mon);
write_dat_to_lcd(0x05,year);
}
else{
write_dat_to_lcd(0x48,sec);//把秒送入液晶
write_dat_to_lcd(0x45,min);
write_dat_to_lcd(0x42,hou);
write_dat_to_lcd(0x0b,day);
write_dat_to_lcd(0x08,mon);
write_dat_to_lcd(0x05,year);
LCD_Write_Char(10,1,' ');
LCD_Write_Char(11,1,' ');
}
}
void main(void)
{
init_lcd();
init_ds1302();
while (1){
keyscan();
if(runmode==1){
sec=BCD_Decimal(ds1302_read_add_dat(0x81));//读1302秒钟寄存器数据,并转化为十进制
min=BCD_Decimal(ds1302_read_add_dat(0x83));
hou=BCD_Decimal(ds1302_read_add_dat(0x85));
day=BCD_Decimal(ds1302_read_add_dat(0x87));
mon=BCD_Decimal(ds1302_read_add_dat(0x89));
year=BCD_Decimal(ds1302_read_add_dat(0x8d));
write_com(0x0c);
if(naomode==0){
shijianmoshiqiehuan();
}
if(naomode==1){
write_dat_to_lcd(0x45,naomin);
write_dat_to_lcd(0x42,naohou);
naozhongmozhi();
}
if(hou==naohou&&min==naomin){
beep=0;
}
else{
beep=1;
}
}
else{//万年历参数设置模式
keyhandle();
}
}
}
|
|