📄 linshi.c
字号:
#include <reg51.h>
#include <absacc.h>
#include <stdio.h>
#include <math.h>
#include <INTRINS.h>
#define WriteDeviceAddress 0xa0 // 写密码锁的地址
#define ReadDviceAddress 0xa1 // 读密码锁的地址
bit enter; // 确认键(1为按下0为未按下)
bit alter; // 修改确认剑(1为按下0为未按下)
bit keyflag; // 密码正确与否(1为正确0为非正确)
bit light; // 7段是否亮(1为亮2为灭)
sbit open=P3^0; // 继电器开关低电平为开,高电平为关
sbit buzzer=P3^1; // 喇叭
sbit SCL=P3^6; // 定义I2C SCK端口
sbit SDA=P3^7; // 定义I2C SDA端口
unsigned char digit; // 7段码的显示位
unsigned char font[4]; // 7段码缓冲区(共4位)
unsigned char t1count; // 定时器1由50ms累积到1s所用的计数器
unsigned char count; // 密码位计数
unsigned char recount; // 修改密码时新密码计数
unsigned char keyword[4]; // 密码存储数组
unsigned char setkey[4]; // 修改密码时密码的缓存数组
unsigned char keyinterim[4]; // 输入密码存储区
void Delay(unsigned int number); // 定义延时函数
void Resetkey(void); // 定义密码修改函数
unsigned char keyscan(void); // 定义键盘扫描函数
void time0_int(void); // 定义中断0
void time1_int(void); // 定义中断1
unsigned char getfont(unsigned char i); // 根据获取七段码
void display(void); // 定义显示函数
bit keycmp(void); // 定义密码比较函数
void Resetkey(void);
void Start(); // 下面都是I2C函数
void Stop();
void NoAck();
bit TestAck();
void Write_I2C(unsigned char address,unsigned char ch);
unsigned char Read8Bit(void);
unsigned char Read_I2C(unsigned char address);
/* 主程序 */
void main()
{
int wait,wait1; // 定义等待时用的变量
unsigned char j,key; // 定义扫描后输入的键值
unsigned char num=0; // 定义密码输入次数
P2 = 0xff; // 关闭数码管显示
TMOD = 0x11; // T0,T1工作方式1
TH0 = -2000/256; // 2ms 定时设置
TL0 = 2000%256;
TH1 = -50000/256; // 50ms 定时设置
TL1 = -50000%256;
TR0 = 1; // 启动计数器0,关闭计数器1
ET0 = 1;
TR1 = 0;
ET1 = 1;
EA = 1;
count = 0; // 初始没有输入密码,计数器设为0
enter= 0; // 没有按下确认键
keyflag = 0; // 密码标志先置为0
open = 1; // 门关
buzzer = 0; // 报警器关
digit = 0x01; // 从第一位数码管开始动态扫描
keyword[0] = 0; // 假设内定密码为0000
keyword[1] = 0;
keyword[2] = 0;
keyword[3] = 0;
for (j=0;j<4;j++) // 刚加电时,显示----
font[j] = 15;
light= 1; // 打开数码管显示
Write_I2C(0x00,keyword[0]); // 写入ROM
Write_I2C(0x01,keyword[1]);
Write_I2C(0x02,keyword[2]);
Write_I2C(0x03,keyword[3]);
keyword[0]=Read_I2C(0x00); // 从ROM中读数,并存储在密码数组中
keyword[1]=Read_I2C(0x01);
keyword[2]=Read_I2C(0x02);
keyword[3]=Read_I2C(0x03);
while(1)
{
key = keyscan(); // 调用键盘扫描函数
switch(key)
{
case 0x11: // 1行1列,数字7
if (count<4)
{
font[count] = 7;
keyinterim[count] = 7;
count++;
}
break;
case 0x21: // 1行2列,数字8
if (count<4)
{
font[count] = 8;
keyinterim[count] = 8;
count++;
}
break;
case 0x41: // 1行3列,数字9
if (count<4)
{
font[count] = 9;
keyinterim[count] = 9;
count++;
}
break;
case 0x81: // 1行4列
if (count<4)
{
font[count]=10;
keyinterim[count]=10;
count++;
}
break;
case 0x12: // 2行1列,数字4
if (count<4)
{
font[count] = 4;
keyinterim[count] = 4;
count++;
}
break;
case 0x22: // 2行2列,数字5
if (count<4)
{
font[count] = 5;
keyinterim[count] = 5;
count++;
}
break;
case 0x42: // 2行3列,数字6
if (count<4)
{
font[count] = 6;
keyinterim[count] = 6;
count++;
}
break;
case 0x82: // 2行4列
if (count<4)
{
font[count] =11;
keyinterim[count] = 11;
count++;
}
break;
case 0x14: // 3行1列,数字1
if (count<4)
{
font[count] = 1;
keyinterim[count] = 1;
count++;
}
break;
case 0x24: // 3行2列,数字2
if (count<4)
{
font[count] = 2;
keyinterim[count] = 2;
count++;
}
break;
case 0x44: // 3行3列,数字3
if (count<4)
{
font[count]=3;
keyinterim[count]=3;
count++;
}
break;
case 0x84: //3行4列,开始修改密码
Resetkey();
break;
case 0x18: //4行1列,取消
count = 0;
for (j=0;j<4;j++)
{
font[j] = 15; // 数码管显示----
keyinterim[j] = 15;
}
break;
case 0x28: // 4行2列,数字0
if (count<4)
{
font[count]=0;
keyinterim[count]=0;
count++;
}
break;
case 0x48: // 4行3列
enter= 1;
if (count==4)
keyflag = keycmp();
else
keyflag = 0; // 否则直接pmflag赋0
break;
case 0x88: // 4行4列 显示-
if (count<4)
{
font[count]=15;
keyinterim[count]=15;
count++;
}
break;
default:break;
}
Delay(300); // 延时防止重复读取键盘
if (enter==1) // 如果按下确认键
{
num=num+1;
enter= 0;
count = 0;
for (j=0;j<4;j++)
keyinterim[j] = 0x0f;
light= 0; // 关闭数码管显示
TR1 = 1; // 计数器1开始计数
t1count = 0; // 定时器1由50ms累积到1s所用的计数器
if (keyflag==1) // 如果密码正确
{
open = 0; // 门开
num=0; // 密码确认次数清0
}
else
{
buzzer= 1; // 报警器响
P0=0x7C;
P2=0x01;
if(num==3) // 如果输入错误次数为3
{ num=0;
P0=0x7C;
buzzer=1; // 报警器响,并挂起3分钟
for (wait1=1;wait1<999;wait1++)
{for (wait=1;wait<9999;wait++);
}
}
for (wait1=1;wait1<9;wait1++)
{for (wait=1;wait<9999;wait++);
}
buzzer=0;
}
}
}
}
unsigned char keyscan(void)
{
unsigned char scancode,tmpcode;
P1 = 0xf0; // 开始扫描
if ((P1&0xf0)!=0xf0) // 若有键按下
{
Delay(500); // 延时去抖动并防止重复写入
if ((P1&0xf0)!=0xf0)
{
scancode = 0xfe;
while((scancode&0x10)!=0) // 逐行扫描
{
P1 = scancode; // 输出行扫描码
if ((P1&0xf0)!=0xf0) // 本行有键按下
{
tmpcode = (P1&0xf0)|0x0f;
return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列
}
else scancode = (scancode<<1)|0x01; // 行扫描码左移一位
}
}
}
return(0); // 无键按下,返回值为0
}
void time0_int(void) interrupt 1
{
TH0 = -2000/256; // 重置2ms定时
TL0 = -2000%256;
if (light==1) // 如果显示器为开
display(); // 调用显示函数
}
void time1_int(void) interrupt 3
{
unsigned char k;
TH1 = -50000/256; // 重置50ms定时
TL1 = -50000%256;
if (t1count<20)
{
t1count++;
}
else
{
TR1 = 0; // 关闭计数器1
t1count = 0;
open = 1; // 关门
light= 1; // 打开数码管显示
digit = 0x01; // 从数码管第1位开始动态显示
for (k=0;k<4;k++) // 显示----
font[k] = 15;
}
}
unsigned char getfont(unsigned char i)
{
unsigned char word;
switch (i)
{
case 0: word=0x3f;break; //0
case 1: word=0x06;break; //1
case 2: word=0x5B;break; //2
case 3: word=0x4F;break; //3
case 4: word=0x66;break; //4
case 5: word=0x6D;break; //5
case 6: word=0x7D;break; //6
case 7: word=0x07;break; //7
case 8: word=0x7F;break; //8
case 9: word=0x6f;break; //9
case 10: word=0x77;break; //A
case 11: word=0x7C;break; //B
case 12: word=0x39;break; //C
case 13: word=0x5E;break; //D
case 14: word=0x79;break; //E
case 15: word=0x40;break; //-
default: break;
}
return(word);
}
void display(void)
{
unsigned char i;
switch (digit)
{
case 1: i=0; break;
case 2: i=1; break;
case 4: i=2; break;
case 8: i=3; break;
case 16: i=4; break;
case 32: i=5; break;
default: break;
}
P2 = 0xff; // 关闭显示
P0 = getfont(font[i]); // 送字型码
P2 = ~(digit); // 送字位码
if (digit<0x08) // 共4位
digit = digit*2; // 左移一位
else
digit = 0x01;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -