#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。。求助啊,大佬们
|