要求:
1、在锁开的状态下输入密码,设置的密码共6位,用数据开关K1∼K10分别代表数字1、2、…、9、0,输入的密码用1602显示,可删除输入的数字,删除的是最后输入的数字,每删除一位。
2、可以修改密码,断电不掉数据。
3、三次密码输入错误,开始警报,需要按下复位才能重新输入。
一、Protues仿真图:
二、程序源码:
因为注释非常的全,这里就不再进行讲解了。
/*******************************************************************************
================================================================================
【平 台】STC89C51_sumjess平台
【编 写】sumjess
【E-mail 】1371129880@qq.com
【软件版本】V2.0
【最后更新】2019年06月10日
【相关信息参考下列地址】
【网 站】
https://blog.csdn.net/qq_38351824
http://www.51hei.com/bbs/mcu-2-1.html
---------------------------------------------------------------------------------
【dev.env.】MDK4.02及以上版本
【Target 】STC89C51
第一次修订:2019/05/09
第二次修订:2019/05/21
第三次修订:2019/06/10
【problem 】
(1)库内补充的不全面;
(2)库内解释部分不全面;
(3)库内还存在一定的bug;
【direction】
下一步的目标就是把库继续集成!
【explain 】
为了方便使用,我也自己写了很多的库,和优化了算法和表示方式!
【warning】
目前程序中暂无错误 !
---------------------------------------------------------------------------------
没有完美的代码,只有不断的奉献,大家一起努力;
赠人玫瑰手留余香,欢迎大家反馈bug!
================================================================================
********************************************************************************/
#include #include #define uchar unsigned char #define uint unsigned int sbit beep=P2^4;//蜂鸣器接口 sbit D1=P2^2; //开锁信号 sbit k1=P3^2; //恢复初始密码按键 sbit RS=P2^7; //数据命令选择 sbit RW=P2^6; //读写控制 sbit E=P2^5; //液晶使能 sbit SDA=P2^1; //数据线接口 sbit SCL=P2^0; //时钟线接口 uchar idata table1[6]={1,2,3,4,5,6}; //初始密码 uchar dd; uchar aa;//存放密码错误的次数,够三次报警 uchar bb; uchar cc; //延时子函数 void delay1(uint z) { uint x,y; for(x=0;x } void delay2() { ;; } //总线初始化子函数 void i2cinit() { SDA=1; delay2(); SCL=1; delay2(); } //启动信号子函数 void start() { SDA=1; SCL=1; delay2(); SDA=0; delay2(); } //停止信号子函数 void stop() { SDA=0; delay2(); SCL=1; delay2(); SDA=1; delay2(); } //应答信号子函数 void respons() { uchar i=0; SCL=1; delay2(); while(SDA==1&&i<255)//等待应答,过一段时间不应答退出循环 i++; SCL=0; delay2(); } //写一个字节子函数 void writebyte(uchar date) { uchar i,temp; temp=date; for(i=0;i<8;i++) { temp<<=1;//temp左移一位后高位进CY SCL=0; delay2(); SDA=CY; delay2(); SCL=1; delay2(); } SCL=0;//应答信号中SCL = 1,所以这里要置0 delay2(); SDA=1;//用完要释放数据总线 delay2(); } //读一个字节子函数 uchar readbyte() { uchar i,k; SCL=0; delay2(); SDA=1; for(i=0;i<8;i++) { SCL=1; delay2(); k=(k<<1)|SDA; //和最低位或,一位位送到K SCL=0; delay2(); } delay2(); return k; } //向地址写一个字节数据子函数 void write_add(uchar address,uchar date) { start(); writebyte(0xa0);//A0,A1,A2接地,AT24C02芯片地址为1010,送控制字为1010A2A1A0R/~W respons(); writebyte(address); respons(); writebyte(date); respons(); stop(); } //向地址读一个字节数据子函数 uchar read_add(uchar address) { uchar date; start(); writebyte(0xa0);//A0,A1,A2接地,AT24C02芯片地址为1010,送控制字为1010A2A1A0R/~W respons(); writebyte(address); respons(); start(); writebyte(0xa1);//A0,A1,A2接地,AT24C02芯片地址为1010,送控制字为1010A2A1A0R/~W respons(); date=readbyte(); stop(); return date; } //向地址写n个字节数据子函数 void write_n_add(uchar *p,uchar address,uchar n) { uchar i; for(i=0;i write_add((address+i),*(p+i)); delay1(20);//一定要适当延时,不然写不进去 } } //向地址读n个字节数据子函数 void read_n_add(uchar *p,uchar address,uchar n) { uchar i; for(i=0;i *(p+i)=read_add(address+i); } } //LCD1602液晶读忙子函数 bit LCD1602_busy() { bit a; RS=0; RW=1; E=1; _nop_(); _nop_(); a=(bit)(P0&0x80); E=0; return a; } //LCD1602液晶写命令子函数 void write_com(uchar com) { while(LCD1602_busy()); RW=0; RS=0; E=0; P0=com; delay1(5); E=1; delay1(5); E=0; } //LCD1602液晶写数据子函数 void write_date(uchar date) { while(LCD1602_busy()); RW=0; RS=1; E=0; P0=date; delay1(5); E=1; delay1(5); E=0; } //写一个字符子函数 void write_1_char(uchar zifu) { write_date(zifu); } //向液晶写n个字符子函数 void write_n_char(uchar zifu[]) { uchar i; for(i=0;;i++) { write_1_char(zifu[i]); if(zifu[i+1]=='