下面是源码预览
- 数码管的A--H 引脚 接到单片机的p0 口的 p0^0--P0^7 引脚 .
- 电路图也有点问题,AT24C02 的引脚应该是 sbit Scl=P3^4; //串行时钟信号
- sbit Sda=P3^5; //串行数据信号
- #define uchar unsigned char //定义一下方便使用
- #include "reg52.h"
- #include "intrins.h" //调用头文件
- #define WriteDeviceAddress 0xa0 // AT24C02的识别码是1010,硬件的三个地址引脚接地为000,最后一位为0时表示向存储器写入数据
- #define ReadDviceAddress 0xa1 //最后一位为1时表示从存储器读出数据。0xa0=1010 000 0 ,0xa1=1010 000 1 .
- sbit Scl=P3^4; //串行时钟信号
- sbit Sda=P3^5; //串行数据信号
- sbit xin=P2^0; //在硬件电路上驱动青色发光二极管,用与显示当前处于密码输入状态
- sbit xin_on=P3^6; // 在硬件电路上驱动继电器,当8位密码输入正确时,继电器工作
- sbit ch_pass=P2^2; // 在硬件电路上驱动红色发光二极管,用于显示当前处于修改密码状态
- sbit on=P3^7;
- static cound ; // 用于计算密码输入的个数,每次输入8位密码后,清0
- uchar code DB_dat[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; // 存放数码管显示字符码
- uchar DB_password[8]; // 存放从存储器中读取的原始密码
- uchar DB_inword[8]; // 存放从键盘输入的密码
-
- void DelayMs(unsigned int number) //延时函数 延时1 MS
- {
- unsigned char temp;
- for(;number!=0;number--)
- {
- for(temp=112;temp!=0;temp--) ;
- }
- }
- void Start(void) /
- {
- Sda=0;
- Scl=1;
- _nop_ (); //根据时序图尽心延时
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Sda=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- }
- void Ack(void)
- {
- Sda=0;
- _nop_ ();
- _nop_ (); //延时 根据时序图
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=0;
- }
- void NoAck(void)
- {
- Sda=1;
- _nop_ (); //根据时序图进行延时
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=0;
- }
- void Send(uchar Data)
- {
- uchar BitCounter=8;
- uchar temp;
- do
- {
- temp=Data;
- Scl=0;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- if((temp&0x80)==0x80)
- Sda=1;
- else
- Sda=0; //如果最高位是0就发送0
- Scl=1;
- temp=Data<<1;
- Data=temp;
- BitCounter--; //没发完一位数据就减一
- }while(BitCounter); //如果发送完8位后跳出循环
- Scl=0; //释放总线
- }
- uchar Read(void)
- {
- uchar temp=0;
- uchar temp1=0;
- uchar BitCounter=8; //定义从存储器读出的数据位数
- Sda=1;
- do{
- Scl=0;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- Scl=1;
- _nop_ ();
- _nop_ ();
- _nop_ ();
- _nop_ ();
- if(Sda)
- temp=temp|0x01;
- else
- temp=temp&0xfe;
- if(BitCounter-1)
- { temp1=temp<<1; //逐位的读出
- temp=temp1;
- }
- BitCounter--;
- }while(BitCounter); //读出8位后跳出循环
- return(temp); //返回读出的数据
- }
- void WrToROM(uchar Data,uchar Address) //向存储器写一字节的数据 函数
- {
- uchar i=0;
-
- Start(); //调用起始条件函数
- Send(0xa0); // 发送命令,准备写入数据到存储器,让存储器做好准备
- Ack(); // 调用应答函数
- Send(Address); // 先发送要写入数据的的存储器内存地址
- Ack(); // 调用应答函数
-
- Send(Data); // 开始发送要写入到存储器中的数据
- Ack(); // 调用应答函数
-
- Stop(); // 调用停止发送函数,表示发送完毕
- }
- uchar RdFromROM(uchar Address) // 从存储器读出一字节的数据
- {
- uchar i;
-
- Start(); //调用起始条件函数
- Send(0xa0); // 让存储器准备接受命令
- Ack();
- Send(Address); // 发送要读出来的数据地址
- Ack();
- Start(); // 重新调用起始函数
- Send(0xa1); // 发送读出数据的命令
- Ack();
- i=Read ( ); // 开始读出数据
- Scl=0;
- NoAck(); // 读出数据成功。返回信号成功信号给存储器
- Stop();
- return (i); // 返回读出的数据
- }
-
- uchar Key() //键盘扫描子程序
- { uchar KValue;
- uchar tmp;
- P1|=0xff; //将P1口的接键盘的位置1
- KValue=P1;
- KValue|=0x00; //将未接键的位置1
- if(KValue==0xff) //
- return(0); //返回
- DelayMs(20); //延时10ms,去键抖
- KValue=P1;
- KValue|=0x00; //将未接键的位置1
- if(KValue==0xff) //位均为1,无键按下
- return(0); //返回
- //如尚未返回,说明一定有1或更多位被按下
- for(;;)
- { tmp=P1;
- if((tmp|0x00)==0xff)
- break; //等待按键释放,防止按一次键盘,产生多次输入数据
- }
- return(KValue); //返回按键值
- }
- Keyplay(uchar key) // 按键值 处理函数
- { uchar password;
-
- if (( key&0x80)==0) // 按键值位7时的相应处理
- { password=7;
- P0=DB_dat[7]; // 显示按键值,通过数码管显示
- }
- if (( key&0x40)==0) // 按键值位6时的相应处理
- { password=6;
- P0=DB_dat[6]; // 显示按键值,数码管显示
- }
- if (( key&0x20)==0) // 按键值位5时的的相应处理
- {password=5;
- P0=DB_dat[5] ; // 显示按键值
- }
- if (( key&0x10)==0) // 按键值位4时的相应处理
- {password=4;
- P0=DB_dat[4];
- }
- if (( key&0x08)==0) // 按键值位3时的处理
- {password=3;
- P0=DB_dat[3];
- }
- if (( key&0x04)==0) // 按键值位2时的处理
- {password=2;
- P0=DB_dat[2];
- }
- if (( key&0x02)==0)
- {password=1;
- P0=DB_dat[1];
- }
- if (( key&0x01)==0) // 按键值位0时的处理
- {password=0;
- P0=DB_dat[0];
- }
-
- return password; //返回输入的按键值
-
-
- }
- void Init() //中断初始化
- { //定时器0工作于模式2
- IT0=1; //负变跳电平有效
- EX0=1; //开外部中断
- EA=1; //开总中断
-
- }
- void Init0() interrupt 0 //中断入口,中断后的程序处理 函数
- {
- uchar k,j,key;
- EX0=0; //关闭中断,防止重复中断 ((重要 不可以把EX0=0;放在char k,j,key; 之前 否则将出现编译出错))
- ch_pass=0; //点亮红色发光二极管,显示当前处于密码修改状态 ,当输入8位密码后,取消密码修改状态
- P0=0xff; //清空-数码管
- cound=0; //清空密码输入个数标致,确保修改的密码个数从开始,直到输入8位密码后,再一次清0
- while (1)
- { key=Key(); //调用键盘扫描程序,获取按键值
- if (key) //判断按键值是否位非0,非0代表有按键输入
- { DB_inword[cound]=Keyplay(key); //调用按键值处理程序,并且把按键输入的数字存放到 数组中
- cound++; // 每输入一位的密码,COUND 自加
-
- if(cound==8) // 判断输入的密码个数是否到达8个
- { cound=0;
- // 密码输入个数已经到达8个
- DelayMs(1000);
-
-
- ch_pass=1;
- DelayMs(700);
- ch_pass=0; // 让红色发光二极管闪亮一次后,熄灭,表示密码已经成功输入8位
- DelayMs(700);
- ch_pass=1;
- for(k=0;k<8;k++) // 把输入的8位密码逐位的用数码管显示,并且写入到存储器中
- { j=DB_inword[k]; // 断电后密码仍然保存起来,不会消失
- P0=DB_dat[j]; // 获取数码管字符码,并且显示
- DelayMs(1000);
- WrToROM(j,k); // 写入密码到存储器,写入的内存地址为0~7
- DelayMs(1000);
- }
- for(k=0;k<8;k++)
- { DB_password[k]=RdFromROM(k) ;}
-
- P0=0xff;
- break; // 密码修改成功后,跳出中断程序,返回主程序
- }
- }
-
- }
- EX0=1; //重新开启中断
- }
- void main () // 主程序
- {
- uchar i,j,key,pass=0;
- Init(); // 中断初始化
-
-
- cound=0;
-
- for (i=0;i<8;i++) // 逐为的显示可以输入的密码值0~7,只能输入这8为有效数字
- { P0=DB_dat[ i];
- DelayMs(1000);
- P0=0xff;
- }
-
- for (i=0;i<8;i++)
- { DB_password[ i]=RdFromROM(i) ; } //从存储器读出密码值,并保存起来
- while (1)
- { on=0;
- DelayMs(200); // 点亮右下脚的青色发光二极管,表明发光二极管在闪耀表明单片机在正常工作
- on=1;
- key=Key(); // 获取按键值
- if (key) // 判断是否有按键按下
- { DB_inword[cound]=Keyplay(key); // 调用按键值处理函数,把输入的按键值保存起来
- cound++; // 每输入一个值,自加1
- xin=0; // 显示当前处于密码输入状态,点亮左上脚的青色发光二极管
- if(cound==8)
- { cound=0; // 输入的密码个数到达8个后,进行密码验证
-
- DelayMs(1000);
-
-
- xin=1; // 取消当前处于密码输入状态
-
- for (i=0;i<8;i++)
- { DelayMs(1000);
- j=DB_inword[ i];
- P0=DB_dat[j]; // 逐位的显示输入的密码值,用送到P0口,数码管显示
- DelayMs(1000);
- if( DB_password[ i]==DB_inword[ i] ) // 逐位的验证输入的密码值是否和原始密码一致
- { pass++; } // 输入的密码和原始密码一致是 变量PASS自加1
-
- if ( pass==8) // PASS为8时,表明输入的密码和原始密码8位都一致
- { xin_on=0;
- DelayMs(10000); // 密码完全正确,驱动继电器工作,将听到“嗒”的一声
- xin_on=1;
-
- }
- }
- pass=0; // 清空验证位
- P0=0xff; // 清空数码管
- for (i=0;i<8;i++)
- DB_inword[ i]=9; // 清空用于存放输入密码的数组,由于输入的密码限制在0~7之间
- } // 9为无效的输入密码值。确保下次输入密码时,数组里边为无效值
- }
- }
- }
复制代码 |