📄 locker_with_lcd_and_clock.txt
字号:
/************************************************************************************************************
从指定地址读取数据子函数:
在rst为低scl2为低的情况下将rst置高,即允许数据被读出(注意加入延时可以防止干扰)
先写入地址
在分八次吧数据一位位读出,在scl2的一个下降沿数据被读出,数据位从0开始
***************************************************************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char temp1,temp2;
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL2=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_();_nop_();_nop_();_nop_();_nop_(); //开启,写入数据地址,这是本串口协议的开始,加入延时防止干扰
Write_Ds1302_Byte(address);
temp1=Read_Ds1302_Byte();
temp2=temp1>>4;
temp2=temp2*10;
temp1=temp1&0x0f;
temp1=temp1+temp2;//读出数据的时候要将BCD码转换成十进制
RST=0;
return (temp1); //返回
}
/***************************************************************************************************
设定时间初值:
在写入之前应当把要写入的数据转换成BCD码的形式
每写入一次数据记得都要打开1302的写入允许
****************************************************************************************************/
void Set_RTC(void) //设定 日历
{
unsigned char i,*p,tmp;
for(i=0;i<8;i++)
{ //数据的转换,DS1302以4位存储一个10进制数,因此需要将数据进行转换
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0X00); //打开DS1302的写入允许
p=write_rtc_address; //传地址
for(i=0;i<8;i++) //7次写入 年月日时分秒星期
{
Write_Ds1302(*p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80); //关闭DS1302的写入允许
}
/****************************************************************************************************
读取时钟日历:
循环几次分别读出数据,存放在一个数组中,注意此时读出的数据为BCD码形式
每读一次数值让1302空运行一次 可有效的防治干扰
******************************************************************************************************/
void Read_RTC(void) //读取 日历
{
unsigned char i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<8;i++) //分7次读取 年月日时分秒星期
{
l_tmpdisplay[i]=Read_Ds1302(*p);//读取数据存放于数组变量中
p++;
_nop_();_nop_();_nop_();_nop_();_nop_(); //5个空指令
Read_Ds1302(0x00); //让1302空运行一次是最好的防干扰方法
_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
/****************************************************************************************************************
液晶显示扫描程序
*****************************************************************************************************************/
void display_scan(uchar add,uchar date)
{
uchar sw,gw;
sw=date/10;
gw=date%10;
write_com(0x80+add,1);
write_date(0x30+sw);
write_date(0x30+gw);
}
void week_display()//星期显示函数,自己感觉写的复杂了点,不知道你有什么好的办法没有,我估计用数组实现应该
{ //要代码简洁些。你不妨试下
uchar j;
write_com(0x80+0x40+11,1);
switch(xin)
{
case 1:
for(j=0;j<3;j++)
{
write_date(date1[j]);
} break;
case 2:
for(j=0;j<3;j++)
{
write_date(date2[j]);
} break;
case 3:
for(j=0;j<3;j++)
{
write_date(date3[j]);
} break;
case 4:
for(j=0;j<3;j++)
{
write_date(date4[j]);
} break;
case 5:
for(j=0;j<3;j++)
{
write_date(date5[j]);
} break;
case 6:
for(j=0;j<3;j++)
{
write_date(date6[j]);
} break;
case 7:
for(j=0;j<3;j++)
{
write_date(date7[j]);
}
}
}
void main(void) //入口函数
{
uchar j,flag1,flag0;
init();
Set_RTC();
EA=1; //首先开启总中断
EX0=1; //开启外部中断 0
IT0=1; // 设置成 下降沿触发方式
P0=0xf0;//P0口高位输高电平,经过74HC21四输入与门,连接外中断0,有键按下调用中断函数
while(1)
{
Read_RTC();
if(take==1)
{
if(flag0==0)
{
write_com(0x80+6,1);
write_date(0x3a); //加入:号显示
write_com(0x80+9,1);
write_date(0x3a);
write_com(0x80+0x47,1);
write_date(0x2d);//加入-显示
write_com(0x80+0x44,1);
write_date(0x2d);
shi = l_tmpdisplay[2];
fen = l_tmpdisplay[1];
miao = l_tmpdisplay[0];
nian = l_tmpdisplay[5];
yue = l_tmpdisplay[4];
ri = l_tmpdisplay[3];
xin = l_tmpdisplay[6];
week_display();
display_scan(4,shi);
display_scan(7,fen);
display_scan(10,miao);
display_scan(0x40+2,nian);
display_scan(0x40+5,yue);
display_scan(0x40+8,ri);
}
}
else//如果开锁键按下了
{
delay(20);
if(take==0)
{
while(!take)
{
SPK=0;
}
flag0=1;
SPK=1;
flag1=1;
write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
write_com(0x80,1);//在第一行显示请输入密码
for(j=0;j<15;j++)
write_date(table_num[j]);
}
if(flag1==1)//如果开锁键已经按下了
{
write_com(0x80+0x40,1); //在第二行显示被按下的数字
for(j=0;j<4;j++)//有按键按下一次显示一个数
{
write_date(l_tmpdate1[j]+0x30);
}
}
}
if(OK==0) //如果确认键被按下
{
delay(20);
if(OK==0)
{
while(!OK)
{SPK=0;}
SPK=1;
if(mima==1)//并且密码正确
{
mima=0;
write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
write_com(0x80+3,1);
for(j=0;j<12;j++)//流动显示欢迎使用
{
write_date(table_right[j]);
delay(20);
}
}
else //如果密码不正确
{
SPK=0;
write_com(0x01,1); //显示清屏,数据指针和地址指针全部清零
write_com(0x80+2,1);
for(j=0;j<12;j++)
{
write_date( table_error[j]);
delay(20);
}
write_com(0x80+0X41,1);
for(j=0;j<14;j++)
{
write_date(table_error1[j]);
delay(20);
}
}
}
}
}//while(1)
}//main
void key_scan() interrupt 0 //外部中断 0 0的优先级最高
{
EX0=0; //在读键盘期间,我们关闭中断,防止干扰带来的多次中断
//为了消除抖动带来的干扰,在按下键后我们采用延时十多毫秒再读取键值
//如果采用循环语句来延时,比如(for,while。。。)会使CPU处理循环而占用 //系统资源,所以这里我们采用定时器中断法,让定时器等待十多毫秒触发定时器 //中断,这里用到定时器0
TMOD&=0XF1; //设置定时器0为模式1方式,
TH0=0X2E; //设置初值,为12毫秒
TL0=0X00;
ET0=1; //开启定时器中断0
TR0=1; //启动定时器计数
}
void timer0_isr(void) interrupt 1 //定时器0的中断函数
{
TR0=0; //中断后我们停止计数
ReadKey(); //定时器计数12毫秒后产生中断,调用此函数,读取键值
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -