如何在单片机程序中修改使按下K1按键屏幕开机显示Welcom Back,
单片机源程序如下:
- #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, 下载次数: 0)
,1、建立一个标志,在main函数中,如果矩阵按键有按键按下,建立标志。
2、在矩阵按键没有按键按下时,在执行矩阵按键扫描开始前,如果标志没有被修改过(见步骤1),检查K1是否按下。按下了,就执行显示”Welcome Back”的处理。
2所在的处理,要放在主函数的while的循环中,在key_scan之前。
只要逻辑正确,2所在的处理放在key_scan函数中也没有关系。,还有一个问题就是,加上什么代码会使密码错误三次时led灯闪