|
#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();
}
}
}
|
-
-
基于ds1302的萬年歷設計.rar
2020-6-29 20:06 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
136.04 KB, 下載次數: 44, 下載積分: 黑幣 -5
|