📄 51
字号:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define COM XBYTE [0x7fff] //8279命令状态地址
#define DAT XBYTE [0x77fF] //8279数据地址
uchar code table[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //0,1,2,3,4,5,6,7
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 //8,9,A,B,C,D,E,F
}; //共阳极数码管显示段码
uchar idata diss[8]; //显示用数据暂存器 8位数据
uchar idata mima[6]; //密码用数据暂存器 6位数据
sbit clflag=ACC^7; //记录状态字 最高位
sbit SDA=P1^1; //24c02数据端
sbit SCL=P1^0; //24c02时钟端
sbit error=P1^2; //闭锁指示端
sbit right=P1^3; //开锁指示端 和开锁输出
uchar keyin(); //8279读键号子程序
uchar deky(); //8279监测有无按键按下子程序
void disp(uchar idata *d); //8279显示子程序
void start_bit(void); //2402开始位
void stop_bit(void); //2402停止位
void mast_ack(void); //2402主答函数
bit write_8bit(uchar ch); //2402写一个字节(8位)数据
uchar page_wr(uint firstw_ad,uint counter,uchar *firstr_ad);
//2402页面写函数
uchar page_rd(uint firstrd_ad,uint count,uchar *firstwr_ad);
//页面读函数
void mimakey(void); //密码锁设置密码 输入密码子程序
main() //主函数
{
uchar i;
COM=0xd1; //11010001 总清除命令
do{ACC=COM;} //读状态字 直到清除完成
while(clflag==1); //读状态字 最高位
COM=0x00; //键盘/显示器工作方式 左端送入8×8显示双键锁定编码扫描
COM=0x34; //时钟分频 20分频
right=0;error=1; //默认闭锁
//************以下测试用*****************//
for(i=0;i<6;i++) {mima[i]=i+2;} //设置初始密码为234567 测试用
while(page_wr(0,6,&mima[0])==0); //写入2402
//测试用 当2402存好密码后 该部分程序可以撤除
//************以上测试用*****************//
while(1)
{
mimakey(); //密码锁 设置密码、输入密码子程序
}
}
void mimakey(void) //密码锁 设置密码、输入密码子程序
{
uchar i,key; //i循环变量 key键号暂存器
bit keyok; //解锁标志位
for(i=0;i<6;i++){diss[i]=i;}//在“无输入和设置密码时”默认显示012345
disp(diss); //送显示
key=keyin(); //等待键按下 读键号
//*************以下为 输入密码状态*************//
if((key==0x0b)&(keyok==0)) //在闭锁状态下,密码输入键按下时,进入输入密码状态
{
for(i=0;i<6;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;i<6;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;i<6;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
}
}
}
}
//*************以上为设置密码状态*************//
}
void disp(uchar idata *d) //显示子程序
{
uchar j;
COM=0x90; //写显示RAM 自动加1
for(j=0;j<6;j++) //
{
COM=j+0x80; //写显示RAM 从0~6地址 此命令可省略 能自动加1
DAT=table[*d]; //调要显示的数据
d++; //指针加1
}
}
uchar keyin(void) //读键号
{
uchar j;
do
{
while(deky()==0); //监测有键按下吗 无键时等待
COM=0x40; //读FIFO/传感器RAM 不自动加1 地址为0
j=DAT; //读数据
j=j&0x3f; //读低6位 D5D4D3为键盘所在列号 D2D1D0为键盘所在行号
}while(j>=0x0e); //只读取0~9和A~D键 不读取E和F键
return(j); //返回键号
}
uchar deky(void) //监测有无按键按下
{
uchar k;
k=COM; //读状态
return(k&0x03); //只监测2行按键 有键返回1 无键返回0
}
/*-----------------------------------------------
调用方式:void start_bit(void)
函数说明:2402开始位
在时钟端SCL为高电平时,数据端SDA发生由高到低的变化,为起始条件
启动I2C总线
-----------------------------------------------*/
void start_bit(void)
{
SCL=1;//_nop_();
SDA=1;//_nop_();
SDA=0;//_nop_();
SCL=0;//_nop_();
}
/*-----------------------------------------------
调用方式:void stop_bit(void)
函数说明:2402停止位
在时钟端SCL为高电平时,数据端SDA发生由低到高的变化,为停止条件
停止I2C总线数据传输
-----------------------------------------------*/
void stop_bit(void)
{
SDA=0;//_nop_();
SCL=1;//_nop_();
SDA=1;//_nop_();
}
/*-----------------------------------------------
调用方式:void mast_ack(void)
函数说明:2402主答函数
主器件在收发每一个字节后产生一个时钟应答脉冲,
在这期间,发送器必须保证SDA为高,由接收器SDA拉低,
称为应答信号(ACK)。
-----------------------------------------------*/
void mast_ack(void)
{
SCL=0;_nop_();
SDA=0;_nop_();
SCL=1;_nop_();
SCL=0;_nop_();
SDA=1;_nop_();
}
/*-----------------------------------------------
调用方式:write_8bit(uchar ch)
函数说明:2402写一个字节(8位)数据
-----------------------------------------------*/
bit write_8bit(uchar ch)
{
uchar i=8;
bit fan_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); //返回应答信号
}
/*-----------------------------------------------
调用方式:void page_wr(uint firstw_ad,uint counter,uint data *firstr_ad)
函数说明:2402页面写函数,firstw_ad为写入字节单元的首地址,
*firstr-ad为被写入数据所在首地址指针
counter为写入数据字节数
-----------------------------------------------*/
uchar page_wr(uint firstw_ad,uint counter,uchar *firstr_ad)
{
uchar data *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(); //写停止位
return(1);
}
/*-----------------------------------------------
调用方式:void page_rd(uint firstrd_ad,uint count,uint firstwr_ad)
函数说明:2402页面读函数,firstrd-ad为所读字节首地址,count为读字节数
*ufirstwr-ad为读出数据存储首地址指针
-----------------------------------------------*/
uchar page_rd(uint firstrd_ad,uint count,uchar *firstwr_ad)
{
uchar j=8;
uchar data *ufirstwr_ad;
ufirstwr_ad=firstwr_ad;
start_bit(); //写开始位
if(write_8bit(0xA0)!=0){stop_bit();return(0);} //写命令
if(write_8bit(firstrd_ad)!=0){stop_bit();return(0);}//写首地址
start_bit(); //写开始位
if(write_8bit(0xA1)!=0){stop_bit();return(0);} //读命令
while(count--) //读字节数减1
{
uchar i=8;
while(i--)
{
(*ufirstwr_ad)<<=1; //读对应地址的数据左移
SCL=1;_nop_(); //上升沿
if(SDA) (*ufirstwr_ad)|=0x01; //数据端为1时 存1
SCL=0; _nop_();
}
ufirstwr_ad++; //地址加1
mast_ack(); //应答信号
}
while(j--)
{
(*ufirstwr_ad)<<=1;
SCL=0;_nop_();_nop_();SCL=1;
if(SDA) (*ufirstwr_ad)|=0x01;
}
stop_bit(); //写停止位
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -