标题:
如何在单片机程序中修改使按下K1按键屏幕开机显示Welcom Back
[打印本页]
作者:
ooopppppp
时间:
2021-1-14 20:21
标题:
如何在单片机程序中修改使按下K1按键屏幕开机显示Welcom Back
51hei.png
(17.61 KB, 下载次数: 20)
下载附件
2021-1-14 20:39 上传
单片机源程序如下:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar idata password_old[6] = {1,2,3,4,5,6};//初始密码存放数组
uchar idata password_input[6];//密码输入值保存数组
uchar idata password_input1[6];//密码输入显示*字符存放数组
uchar idata password_set[18];//修改密码时密码输入值保存数组
uchar idata password_set1[18];//修改密码时密码输入显示*字符存放数组
sbit sound = P3^2;//报警控制输出端口
sbit unlock_out = P3^3;//开锁驱动控制输出端口
bit flag_input,flag_modify,flag_unlock,flag_success,flag_error,flag_clr;
//密码输入状态标志,修改密码状态标志,是否可以开锁标志,密码修改成功标志
//密码输入错误或密码修改错误标志,调换显示界面时清屏标志
uchar error_num;//密码输入错误计数
uchar n,m;//密码输入状态下输入个数计数n,修改密码状态下输入个数计数m
#define lcd_out P0 //LCD1602接口设置
sbit lcden = P2^1;
sbit lcdrs = P2^0;
sbit LED=P3^4;
sbit K1=P3^5;
/*******************************************
lcd1602功能程序需要的延时函数
********************************************/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*******************************************
向lcd1602写一个字节命令
********************************************/
void write_com(uchar com)
{
lcdrs=0;//写命令
lcd_out = com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/*******************************************
向lcd1602写一个字节数据
********************************************/
void write_data(uchar date)
{
lcdrs=1;//写数据
lcd_out = date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/*******************************************
lcd1602初始化
********************************************/
void lcd1602_init()
{
lcden=0;
write_com(0x38);//显示模式设置,16*2显示,5*7点阵,8位并行数据接口
write_com(0x0c);//显示开,不显示光标,光标不闪烁
write_com(0x06);//写入一个字符后指针加1,写一个字符时整屏不移动
write_com(0x01);//清屏,数据指针清0,所有显示清0
write_com(0x80+0x01);//设置字符显示的首地址,第0行第1列所在的位置
}
/*******************************************
将字符串*str显示在第y行第x列,x=0~15,y=0~1
*******************************************/
void display_str(uchar x,uchar y,uchar *str)
{
if(flag_clr == 1)//调换显示界面,先清屏一次
{
write_com(0x01);//清屏,数据指针清0,所有显示清0
flag_clr = 0;
}
if(y == 0)
write_com(0x80+x);//坐标定位在第0行
else
write_com(0xc0+x);//坐标定位在第1行
write_com(0x0c);//显示开,不显示光标,光标不闪烁
while(*str != '\0') //判断字符串是否结束
{
write_data(*str);//依次显示字符串中的每一个字符
str ++;
}
}
/*******************************************
密码输入键处理
********************************************/
void input(void)
{
flag_input = 1;//进入密码输入状态,置标志
flag_clr = 1;//进入密码输入显示界面,置清屏标志
flag_modify = 0;//去除密码修改标志
flag_unlock = 0;//取消开锁标志
flag_error = 0;//取消错误标志
flag_success = 0;//取消密码修改成功标志
unlock_out = 1;//设置成关锁状态
}
/*******************************************
数字键输入处理,将相应的数字保存为密码输入
数组,并在显示界面相应的位置上显示*字符
********************************************/
void key_number(uchar num)
{
if(flag_input == 1)//密码输入状态
{
password_input[n] = num;//密码输入值保存
password_input1[n] = '*';//密码输入位上显示*字符
n ++ ; //密码输入个数递增
}
if(flag_modify == 1)//修改密码状态
{
password_set[m] = num;//密码输入值保存
password_set1[m] = '*';//密码输入位上显示*字符
m ++; //密码输入个数递增
}
}
/*******************************************
新输入的密码与旧密码进行比较,正确的返回1
********************************************/
bit password_compare(uchar *p,uchar *q)
{
uchar i,count = 0;
for(i=0;i<6;i++)
{
if(p[i] == q[i])//判断两组6位密码是否一致
count ++;
}
if(count == 6)
return 1;//两组6位密码一致
else
return 0;//两组6位密码不一致
}
/*******************************************************
开锁键处理
密码输入后确认是否正确,如果正确,则开锁,否则错误的话
允许重新输入,并且判断错误输入超过三次,则报警
*******************************************************/
void unlock(void)
{
uchar i;
flag_unlock = password_compare(password_input,password_old);
//将输入的密码与原始密码进行比较是否一致
if(flag_unlock)//输入的密码与原始密码一致
{
flag_clr = 1;
display_str(3,1,"ALL RIGHT !");//密码输入成功显示
unlock_out = 0; //开锁驱动输出低电平信号
flag_input = 0; //清除输入密码状态标志
flag_error = 0; //清除密码输入错误标志
error_num = 0; //清除密码输入错误计数次数
sound = 1; //关闭报警
}
else //输入的密码与原始密码不一致
{
flag_clr = 1;
display_str(3,1,"ERROR !");//密码输入错误显示
flag_error = 1;//置密码输入错误标志
error_num ++;//密码输入错误次数计数
if(error_num > 3)
sound = 0;LED=~LED;//如果密码输入错误次数超过3次,则报警
/*******************************************
创新点:密码输入超过六位显示错误
********************************************/
if(n>6)
{
flag_clr=1;
display_str(3,1,"ERROR !");
}
}
n = 0; //6位密码输入结束时,输入个数计数值回零
for(i=0;i<6;i++)
password_input1[i] = 0x20;//密码输入结束,退出输入状态时显示值重新改为0x20
}
/*******************************************
密码修改键处理
********************************************/
void modify(void)
{
flag_modify = 1;//进入密码修改状态,置标志
flag_input = 0;//去除密码输入标志
flag_clr = 1;//进入密码修改显示界面,置清屏标志
flag_success = 0;//取消密码修改成功标志
flag_error = 0;//取消错误标志
flag_unlock = 0;//取消开锁标志
}
/*******************************************
退格键处理
********************************************/
void back(void)
{
if(flag_input == 1)
{
n -- ; //密码输入个数计数值递减
password_input1[n] = 0x20;//清除*字符显示
}
if(flag_modify == 1)
{
m --; //密码输入个数计数值递减
password_set1[m] = 0x20;//清除*字符显示
}
}
/*******************************************
清除键处理
********************************************/
void clear(void)
{
uchar i;
if(flag_input == 1)
{
n = 0 ;
for(i=0;i<6;i++)
{
password_input[i] = 0;//清除原先输入的所有密码值
password_input1[i] = 0x20;//清除*字符显示
}
}
if(flag_modify == 1)
{
m = 0;
for(i=0;i<18;i++)
{
password_set[i] = 0;//清除原先输入的所有密码值
password_set1[i] = 0x20;//清除*字符显示
}
}
}
/*******************************************
密码修改,确认键处理
********************************************/
void enter(void)
{
bit flag_set = 0,modify_success = 0;
uchar i;
uchar password_set2[6],password_new[6];
for(i=0;i<6;i++)
{
password_set2[i] = password_set[i];//取出输入的旧密码
}
flag_set = password_compare(password_set2,password_old);//判断输入的旧密码是否正确
for(i=0;i<6;i++)
{
password_set2[i] = password_set[i+6];//取出第一次输入的新密码
password_new[i] = password_set[i+12];//取出第二次输入的新密码
}
modify_success = password_compare(password_set2,password_new);//判断两次输入的新密码是否一致
if(flag_set==1 && modify_success==1)
{ //密码修改成功
flag_input = 1;//置密码输入状态标志
flag_modify = 0;//清除修改密码状态标志
for(i=0;i<6;i++)
{
password_old[i] = password_new[i];//将新修改的密码替换旧密码
}
flag_success = 1; //置密码密码修改成功标志
flag_error = 0; //清除密码修改错误标志
flag_clr = 1;
display_str(0,1,"Modify success !");//密码修改成功时的显示界面
}
else
{
flag_success = 0; //清除密码密码修改成功标志
flag_error = 1; //置密码修改错误标志
flag_clr = 1;
display_str(3,1,"Error !");//密码修改错误的显示界面
}
m = 0; //密码修改结束,确认后,密码输入个数计数值回零
for(i=0;i<18;i++)
{
password_set[i] = 0; //将密码输入值全清零
password_set1[i] = 0x20;//将密码输入的显示字符全改为0x20
}
}
/*******************************************
LCD1602显示
********************************************/
void display(void)
{
uchar j;
if(flag_unlock!=1 &&flag_success!=1&&flag_error!=1)
{ //避开密码输入正确时、密码修改成功时以及密码输入错误时的显示界面
write_com(0x0c);//显示开,不显示光标,光标不闪烁
if(flag_input)
{
display_str(0,0,"Electronic Lock ");//输入密码状态时的显示界面
display_str(0,1,"password:");
write_com(0xc0+0x09);
for(j=0;j<6;j++)
write_data(password_input1[j]);//密码输入当前6个位置上的显示字符
write_com(0xc0+0x09+n); //当前密码的输入位的坐标定位
write_com(0x0f); //对当前输入位实现光标显示而且光标闪烁
}
if(flag_modify == 1)
{
delay(1000);
if(m<6) //修改密码状态时的第一个显示界面
{
display_str(0,0,"Password Modify ");
display_str(0,1,"old_code:");
write_com(0xc0+0x09);
for(j=0;j<6;j++)
write_data(password_set1[j]);//旧密码输入的6个位置显示
write_com(0xc0+0x09+m);//当前密码的输入位的坐标定位
write_com(0x0f);//对当前输入位实现光标显示而且光标闪烁
}
else //修改密码状态时的第二个显示界面
{
if(m==6)
flag_clr = 1;
display_str(0,0,"new_code:");
write_com(0x80+0x09);
for(j=6;j<12;j++)
write_data(password_set1[j]);//第一次新密码输入的6个位置显示
display_str(0,1,"re_input:");
write_com(0xc0+0x09);
for(j=12;j<18;j++)
write_data(password_set1[j]);//第二次新密码输入的6个位置显示
if(m<12)
write_com(0x80+0x09+m-6);//当前密码的输入位的坐标定位
else
write_com(0xc0+0x09+m-12);//当前密码的输入位的坐标定位
write_com(0x0f);//对当前输入位实现光标显示而且光标闪烁
}
}
}
}
/*******************************************
延时xms函数
********************************************/
void delay_ms(uint x)
{
uchar j;
while(x--)
for(j=0;j<80;j++);
}
/*******************************************
矩阵式按键扫描并处理
********************************************/
void key_scan()//采用线反转法扫描识别4*4矩阵式按键
{
uchar a,b;
P1 = 0xf0; //①行输出低电平
if(P1 != 0xf0)//②读取列的电平,判定有键按下
{
delay_ms(10);//③延时10ms,避开抖动期
if(P1 != 0xf0);//④再次确认有键按下
{
sound = 0;
a = P1;//⑤读取列的电平,通过0所在的位判断按下的键所在的列
P1 = 0x0f; //⑥列输出低电平
b = P1; //⑦读取行的电平,通过0所在的位判断按下的键所在的行
while(P1 == b);//⑧等待按键释放
sound = 1;
a = a | b; //⑨计算获得键值,综合两个0所在的位,判断按下的键在相应的行与列的交叉点
switch(a) //⑩根据键值得出所按下的按键
{
case 0xee: key_number(0);break;//0~9数字键
case 0xde: key_number(1);break;
case 0xbe: key_number(2);break;
case 0x7e: key_number(3);break;
case 0xed: key_number(4);break;
case 0xdd: key_number(5);break;
case 0xbd: key_number(6);break;
case 0x7d: key_number(7);break;
case 0xeb: key_number(8);break;
case 0xdb: key_number(9);break;
case 0xbb: unlock();break; //开锁键
case 0x7b: input();break; //密码输入键
case 0xe7: enter();break; //密码修改确认键
case 0xd7: clear();break; //清除键
case 0xb7: back();break; //退格键
case 0x77: modify();break; //密码修改键
default:break;
}
display();//显示
}
}
}
/*******************************************
主函数
********************************************/
void main()
{
uchar i;
for(i=0;i<6;i++)
password_input1[i] = 0x20;//密码输入数组初始化为0x20,显示为空格字符
for(i=0;i<18;i++)
password_set1[i] = 0x20;//修改密码时密码输入数组初始化为0x20
lcd1602_init();
while(1)
{
key_scan();
}
}
复制代码
全部资料51hei下载地址:
循环扫描法.zip
(116.8 KB, 下载次数: 2)
2021-1-14 20:21 上传
点击文件名下载附件
作者:
suncat0504
时间:
2021-1-14 21:03
1、建立一个标志,在main函数中,如果矩阵按键有按键按下,建立标志。
2、在矩阵按键没有按键按下时,在执行矩阵按键扫描开始前,如果标志没有被修改过(见步骤1),检查K1是否按下。按下了,就执行显示"Welcome Back"的处理。
2所在的处理,要放在主函数的while的循环中,在key_scan之前。
只要逻辑正确,2所在的处理放在key_scan函数中也没有关系。
作者:
ooopppppp
时间:
2021-1-14 21:09
还有一个问题就是,加上什么代码会使密码错误三次时led灯闪
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1