#include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器
#include<intrins.h>
#define LCD1602_DATAPINS P0
#define uchar unsigned char
#define uint unsigned int
uchar m=50,f=5,s=12;
uchar nu,count,g,n,a,v,p,flag,flag1;
sbit LCD1602_RW=P0^3;
sbit LCD1602_RS=P2^6;
sbit LCD1602_E=P2^7;
sbit k1=P2^0;
sbit k2=P2^1;
sbit k3=P2^2;
sbit k4=P2^3;
sbit k5=P1^0;
sbit k6=P1^1;
sbit beep=P1^5;
sbit SCL=P2^1;
sbit SDA=P2^0;
void writekey(uchar key);
void writenum(uchar num);
void write_sfm(uchar add,uchar date);
void bee1(void);
void bee2(void);
void bee4(void);
void bee3(void);
void jian(void);
void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
void Keypros(void);
uchar code table[]="12:05:50";
uchar code table1[]="12:06:06";
uchar code table2[]="start";
void delay1(uint o) //o=1,10us
{
while(o--);
}
void delay(uint z) //按鍵延時
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Delay10us() // 延時10us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
void Lcd1602_Delay1ms(uint c) //1ms
{
uchar a,b;
for (; c>0; c--)
{for (b=199;b>0;b--)
{for(a=1;a>0;a--);}}
}
void writekey(uchar key) //寫指令
{
LCD1602_E=0; //使能清零
LCD1602_RS=0; //選擇寫入命令
LCD1602_RW=0; //選擇寫入
LCD1602_DATAPINS=key; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E=1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
LCD1602_DATAPINS=key<<4; //發送低四位
Lcd1602_Delay1ms(1);
LCD1602_E=1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
}
void writenum(uchar num) //寫數據
{
LCD1602_E=0; //使能清零
LCD1602_RS=1; //選擇寫入數據
LCD1602_RW=0; //選擇寫入
LCD1602_DATAPINS=num; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E=1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
LCD1602_DATAPINS=num<<4; //寫入低四位
Lcd1602_Delay1ms(1);
LCD1602_E=1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E=0;
}
void init()
{
writekey(0x32); //將8位總線轉為4位總線
writekey(0x28); //在四位線下的初始化
writekey(0x0c); //開顯示不顯示光標
writekey(0x06); //寫一個指針加1
writekey(0x01); //清屏
writekey(0x80); //設置數據指針起點
}
void init1(void)
{
SCON=0X50; //設置為工作方式1
TMOD|=0x20; //定時器初始化
PCON=0X80; //波特率加倍
TH1=0XF3; //計數器初始值設置,注意波特率是4800的
TL1=0XF3;
ES=1; //打開接收中斷
EA=1;
TR1=1; //打開計數器
}
void init2(void)
{
TMOD|=0x01; //定時器初始化
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
for(n=0;n<8;n++)
{
writenum(table[n]);
}
writekey(0x80+0x40); //顯示鬧鐘時間
for(nu=0;nu<8;nu++)
{
writenum(table1[nu]);
}
}
void write_sfm(uchar add,uchar date) //讀出時分秒變量
{
uchar shi,ge;
shi=date/10; //十位
ge=date%10; //個位
writekey(0x80+add); //顯示的位置
writenum(0x30+shi); //顯示十位
writenum(0x30+ge); //顯示個位
}
void I2cStart() // 起始信號:在SCL時鐘信號在高電平期間SDA信號產生一個下降沿,起始之后SDA和SCL都為0
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立時間是SDA保持時間>4.7us
SDA=0;
Delay10us();//保持時間是>4us
SCL=0;
Delay10us();
}
void I2cStop() // 終止信號:在SCL時鐘信號高電平期間SDA信號產生一個上升沿
{ //結束之后保持SDA和SCL都為1;表示總線空閑
SDA=0;
Delay10us();
SCL=1;
Delay10us();//建立時間大于4.7us
SDA=1;
Delay10us();
}
unsigned char I2cSendByte(unsigned char dat) //通過I2C發送一個字節。在SCL時鐘信號高電平期間,保持發送信號SDA保持穩定
{ // 0或1。發送成功返回1,發送失敗返回0,發送完一個字節SCL=0,SDA=1
unsigned char a=0,b=0; //最大255,一個機器周期為1us,最大延時255us。
for(a=0;a<8;a++) //要發送8位,從最高位開始
{
SDA=dat>>7; //起始信號之后SCL=0,所以可以直接改變SDA信號
dat=dat<<1;
Delay10us();
SCL=1;
Delay10us(); //建立時間>4.7us
SCL=0;
Delay10us(); //時間大于4us
}
SDA=1;
Delay10us();
SCL=1;
while(SDA) //等待應答,也就是等待從設備把SDA拉低
{
b++;
if(b>200) //如果超過2000us沒有應答發送失敗,或者為非應答,表示接收結束
{
SCL=0;
Delay10us();
return 0;
}
}
SCL=0;
Delay10us();
return 1;
}
unsigned char I2cReadByte() //使用I2c讀取一個字節,接收完一個字節SCL=0,SDA=1.
{
unsigned char a=0,dat=0;
SDA=1; //起始和發送一個字節之后SCL都是0
Delay10us();
for(a=0;a<8;a++)//接收8個字節
{
SCL=1;
Delay10us();
dat<<=1;
dat|=SDA;
Delay10us();
SCL=0;
Delay10us();
}
return dat;
}
void At24c02Write(unsigned char addr,unsigned char dat)// 往24c02的一個地址寫入一個數據
{
I2cStart();
I2cSendByte(0xa0);//發送寫器件地址
I2cSendByte(addr);//發送要寫入內存地址
I2cSendByte(dat); //發送數據
I2cStop();
}
unsigned char At24c02Read(unsigned char addr) // 讀取24c02的一個地址的一個數據
{
unsigned char num;
I2cStart();
I2cSendByte(0xa0); //發送寫器件地址
I2cSendByte(addr); //發送要讀取的地址
I2cStart();
I2cSendByte(0xa1); //發送讀器件地址
num=I2cReadByte(); //讀取數據
I2cStop();
return num;
}
void bee1(void) //模式一
{
while(1)
{
beep=0;
delay1(20); //延時大約200us 通過修改此延時時間達到不同的發聲效果
beep=1;
delay1(20);
if(s==12&&f==6&&m==11) //自動到12:06:09退出或者按鍵到12:06:06退出
break;
}
}
void bee2(void) //模式二
{
while(1)
{
beep=0;
delay1(40); //延時大約400us 通過修改此延時時間達到不同的發聲效果
beep=1;
delay1(40);
if(s==12&&f==6&&m==6) //提前5秒叫,5秒以后尖叫
{
while(1)
{
beep=0;
delay1(10); //延時大約100us 通過修改此延時時間達到不同的發聲效果
beep=1;
delay1(10);
if(s==12&&f==6&&m==11)
break;
}
}
if(s==12&&f==6&&m==11)
break;
}
}
void bee4(void)
{
while(1)
{
beep=0;
delay1(20); //延時大約200us 通過修改此延時時間達到不同的發聲效果
beep=1;
delay1(20);
if((m==11)||(m==41))
break;
}
}
void bee3(void)
{
if(k4==0) //k5按鍵按下
{
delay(5);
if(k4==0)
{
while(!k4);
g++;
}
}
if(g==1)
{
if(s==12&&f==6&&m==1)
{bee2();}
}
if(g==2)
{
if(s==12&&f==6&&m==6)
{bee1();}
}
if(g==3)
{
if(s==12&&f==6&&m==1)
bee1();
if((m==1)||(m==31))
bee4();
}
}
void jian(void) //按鍵設置
{
uchar as; //計算按鍵三按下次數
if(k3==0)
{
delay(5);
if(k3==0)
{
as++;
while(!k3);
}
}
if(as==1) //按鍵三按下一次為秒針設置
{
TR0=0; //關閉計時
writekey(0x0f); //開光標閃爍
writekey(0x80+7); //位置
if(k1==0)
{
delay(5);
if(k1==0)
{
m++;
while(!k1);
if(m==60)
{
m=0;
}
write_sfm(6,m);
}
}
if(k2==0)
{
delay(5);
if(k2==0)
{
m--;
while(!k2);
if(m==-1)
{
m=59;
}
write_sfm(6,m);
}
}
}
if(as==2) //分針設置
{
TR0=0;
writekey(0x0f);
writekey(0x80+4);
if(k1==0)
{
delay(5);
if(k1==0)
{
f++;
while(!k1);
if(f==60)
{
f=0;
}
write_sfm(3,f);
}
}
if(k2==0)
{
delay(5);
if(k2==0)
{
f--;
while(!k2);
if(f==-1)
{
f=59;
}
write_sfm(3,f);
}
}
}
if(as==3) //時針設置
{
TR0=0;
writekey(0x0f);
writekey(0x80+1);
if(k1==0)
{
delay(5);
if(k1==0)
{
s++;
while(!k1);
if(s==24)
{
s=0;
}
write_sfm(0,s);
}
}
if(k2==0)
{
delay(5);
if(k2==0)
{
s--;
while(!k2);
if(s==-1)
{
s=23;
}
write_sfm(0,s);
}
}
}
if(as==4) //時間自己走走動
{
TR0=1;
writekey(0x0c);
}
if(as==4) //時間走動
{
TR0=1;
writekey(0x0c);
as=0;
}
}
void Keypros(void)
{
if(k5==0)
{
delay(5); //消抖處理
if(k5==0)
{
At24c02Write(1,s);
At24c02Write(2,f);
At24c02Write(3,m);
}
while(!k5);
}
if(k6==0)
{
delay(5); //消抖
if(k6==0)
{
s=At24c02Read(1);
write_sfm(0,s);
f=At24c02Read(2);
write_sfm(3,f);
m=At24c02Read(3);
write_sfm(6,m);
}
while(!k6);
}
}
void main(void)
{
init1();
init();
while(1)
{
if(flag==1)
{
writekey(0x80+0x40+9);
for(v=0;v<5;v++)
{
writenum(table2[v]);
}
Lcd1602_Delay1ms(1000);
flag1=1;
writekey(0x01);
}
if(flag1==1)
break;
}
init2();
while(1)
{
jian();
bee3();
Keypros();
}
}
void timer0() interrupt 1 //重裝初值
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20) //1s
{
m++;
count=0;
if(m==60)
{
m=0;f++;
if(f==60)
{
f=0;s++;
if(s==24)
{
s=0;
}
write_sfm(0,s); //寫入小時
}
write_sfm(3,f); //寫入分鐘
}
write_sfm(6,m); //寫入秒
}
}
void Usart() interrupt 4
{
a=SBUF; //接收到的數據
RI=0; //清除接收中斷標志位,取消中斷
flag=1; //標志,看是否已經執行過串口中斷
}
例如存的應該是06;可是顯示的是17。。求助啊,大佬們
|