#includereg51.h#includeabsacc.h#includeintrins.h#defineucharunsignedchar#defineuintunsignedint#defineCOMXBYTE[0x7fff]//8279命令状态地址#defineDATXBYTE[0x77fF]//8279数据地址ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0,1,2,3,4,5,6,70x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71//8,9,A,B,C,D,E,F};//共阳极数码管显示段码ucharidatadiss[8];//显示用数据暂存器8位数据ucharidatamima[6];//密码用数据暂存器6位数据sbitclflag=ACC^7;//记录状态字最高位sbitSDA=P1^1;//24c02数据端sbitSCL=P1^0;//24c02时钟端sbiterror=P1^2;//闭锁指示端sbitright=P1^3;//开锁指示端和开锁输出ucharkeyin();//8279读键号子程序uchardeky();//8279监测有无按键按下子程序voiddisp(ucharidata*d);//8279显示子程序voidstart_bit(void);//2402开始位voidstop_bit(void);//2402停止位voidmast_ack(void);//2402主答函数bitwrite_8bit(ucharch);//2402写一个字节(8位)数据ucharpage_wr(uintfirstw_ad,uintcounter,uchar*firstr_ad);//2402页面写函数ucharpage_rd(uintfirstrd_ad,uintcount,uchar*firstwr_ad);//页面读函数voidmimakey(void);//密码锁设置密码输入密码子程序main()//主函数{uchari;COM=0xd1;//11010001总清除命令do{ACC=COM;}//读状态字直到清除完成while(clflag==1);//读状态字最高位COM=0x00;//键盘/显示器工作方式左端送入8×8显示双键锁定编码扫描COM=0x34;//时钟分频20分频right=0;error=1;//默认闭锁//************以下测试用*****************//for(i=0;i6;i++){mima[i]=i+2;}//设置初始密码为234567测试用while(page_wr(0,6,&mima[0])==0);//写入2402//测试用当2402存好密码后该部分程序可以撤除//************以上测试用*****************//while(1){mimakey();//密码锁设置密码、输入密码子程序}}voidmimakey(void)//密码锁设置密码、输入密码子程序{uchari,key;//i循环变量key键号暂存器bitkeyok;//解锁标志位for(i=0;i6;i++){diss[i]=i;}//在“无输入和设置密码时”默认显示012345disp(diss);//送显示key=keyin();//等待键按下读键号//*************以下为输入密码状态*************//if((key==0x0b)&(keyok==0))//在闭锁状态下,密码输入键按下时,进入输入密码状态{for(i=0;i6;i++)//6位密码输入{key=keyin();//读一位键if(key==0x0d)break;//是取消键时输入密码取消if(key=0x0a){do{key=keyin();}while(key=0x0a);}//不是取消键且输入键号不是0~9的数字键时等待1位数字键输入mima[i]=key;//密码数字存于mima暂存器中diss[i]=15;//每输入一位密码数码管显示“F”disp(diss);//送显示}if(key!=0x0d)//6位密码输入完成时看是否要确认;未完成6位输入时返回{key=keyin();//等待按键输入if(key==0x0d);//是取消键时输入密码取消else//不是取消键时等待输入密码确认{if(key!=0x0c)while(keyin()!=0x0c);//等待确认键按下while(page_rd(0,6,&diss[0])==0);//在2402中读取密码keyok=1;//把解锁标志位设为1解锁for(i=0;i6;i++)//比较6位密码{//有1位密码不同时密码错误无需再比较if(mima[i]!=diss[i]){keyok=0;break;}//密码错误时解锁状态位设为0为闭锁状态}if(keyok==1){right=1;error=0;}//当密码正确时开锁else{right=0;error=1;}//当密码错误时闭锁}}}//*************以上为输入密码状态*************////*************以下为设置密码状态*************//if(keyok==1)//在开锁状态下可以设置密码或关锁{if(key==0x0d)//开锁状态时按下取消键时关锁{keyok=0;right=0;error=1;//解锁状态位设为0闭锁}if(key==0x0a)//是设定键时进入设置密码状态{for(i=0;i6;i++)//6位密码输入{key=keyin();//读一位键if(key==0x0d)break;//是取消键时密码设置取消if(key=0x0a){do{key=keyin();}while(key=0x0a);}//不是取消键且输入键号不是0~9的数字键时等待1位数字键输入mima[i]=key;//密码数字存于mima暂存器中diss[i]=14;//每输入一位密码数码管显示“E”disp(diss);//送显示}if(key!=0x0d)//6位密码输入完成时看是否要确认;未完成6位输入时返回{key=keyin();//读一位键if(key==0x0d);//是取消键时设置密码取消else//不是取消键时等待设置密码确认{if(key!=0x0c)while(keyin()!=0x0c);//等待确认键按下while(page_wr(0,6,&mima[0])==0);//密码写入24lc02}}}}//*************以上为设置密码状态*************//}voiddisp(ucharidata*d)//显示子程序{ucharj;COM=0x90;//写显示RAM自动加1for(j=0;j6;j++)//{COM=j+0x80;//写显示RAM从0~6地址此命令可省略能自动加1DAT=table[*d];//调要显示的数据d++;//指针加1}}ucharkeyin(void)//读键号{ucharj;do{while(deky()==0);//监测有键按下吗无键时等待COM=0x40;//读FIFO/传感器RAM不自动加1地址为0j=DAT;//读数据j=j&0x3f;//读低6位D5D4D3为键盘所在列号D2D1D0为键盘所在行号}while(j=0x0e);//只读取0~9和A~D键不读取E和F键return(j);//返回键号}uchardeky(void)//监测有无按键按下{uchark;k=COM;//读状态return(k&0x03);//只监测2行按键有键返回1无键返回0}/*-----------------------------------------------调用方式:voidstart_bit(void)函数说明:2402开始位在时钟端SCL为高电平时,数据端SDA发生由高到低的变化,为起始条件启动I2C总线-----------------------------------------------*/voidstart_bit(void){SCL=1;//_nop_();SDA=1;//_nop_();SDA=0;//_nop_();SCL=0;//_nop_();}/*-----------------------------------------------调用方式:voidstop_bit(void)函数说明:2402停止位在时钟端SCL为高电平时,数据端SDA发生由低到高的变化,为停止条件停止I2C总线数据传输-----------------------------------------------*/voidstop_bit(void){SDA=0;//_nop_();SCL=1;//_nop_();SDA=1;//_nop_();}/*-----------------------------------------------调用方式:voidmast_ack(void)函数说明:2402主答函数主器件在收发每一个字节后产生一个时钟应答脉冲,在这期间,发送器必须保证SDA为高,由接收器SDA拉低,称为应答信号(ACK)。-----------------------------------------------*/voidmast_ack(void){SCL=0;_nop_();SDA=0;_nop_();SCL=1;_nop_();SCL=0;_nop_();SDA=1;_nop_();}/*-----------------------------------------------调用方式:write_8bit(ucharch)函数说明:2402写一个字节(8位)数据-----------------------------------------------*/bitwrite_8bit(ucharch){uchari=8;bitfan_w;SCL=0;_nop_();while(i--){SDA=(bit)(ch&0x80);//取字节的最高位_nop_();ch=1;//字节左移一位SCL=1;_nop_();//上升沿锁存数据SCL=0;_nop_();}SDA=1;_nop_();SCL=1;_nop_();fan_w=SDA;//读应答信号SCL=0;_nop_();return(fan_w);//返回应答信号}/*-----------------------------------------------调用方式:voidpage_wr(uintfirstw_ad,uintcounter,uintdata*firstr_ad)函数说明:2402页面写函数,firstw_ad为写入字节单元的首地址,*firstr-ad为被写入数据所在首地址指针counter为写入数据字节数-----------------------------------------------*/ucharpage_wr(uintfirstw_ad,uintcounter,uchar*firstr_ad){uchardata*ufirstr_ad;ufirstr_ad=firstr_ad;start_bit();//写开始位if(write_8bit(0xA0)!=0){stop_bit();return(0);}//写命令if(write_8bit(firstw_ad)!=0){stop_bit();return(0);}//写首地址while(counter--)//写字节数减1{if(write_8bit(*ufirstr_ad)!=0){stop_bit();return(0);}//写1字节ufirstr_ad++;//地址加1}stop_bit();//写停