找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1089|回复: 2
打印 上一主题 下一主题
收起左侧

如何在单片机程序中修改使按下K1按键屏幕开机显示Welcom Back

[复制链接]
跳转到指定楼层
楼主


单片机源程序如下:
  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uchar idata password_old[6] = {1,2,3,4,5,6};//初始密码存放数组
  5. uchar idata password_input[6];//密码输入值保存数组
  6. uchar idata password_input1[6];//密码输入显示*字符存放数组
  7. uchar idata password_set[18];//修改密码时密码输入值保存数组
  8. uchar idata password_set1[18];//修改密码时密码输入显示*字符存放数组
  9. sbit sound = P3^2;//报警控制输出端口
  10. sbit unlock_out = P3^3;//开锁驱动控制输出端口
  11. bit flag_input,flag_modify,flag_unlock,flag_success,flag_error,flag_clr;
  12. //密码输入状态标志,修改密码状态标志,是否可以开锁标志,密码修改成功标志
  13. //密码输入错误或密码修改错误标志,调换显示界面时清屏标志
  14. uchar error_num;//密码输入错误计数
  15. uchar n,m;//密码输入状态下输入个数计数n,修改密码状态下输入个数计数m
  16. #define lcd_out P0        //LCD1602接口设置
  17. sbit lcden = P2^1;
  18. sbit lcdrs = P2^0;
  19. sbit LED=P3^4;
  20. sbit K1=P3^5;        
  21. /*******************************************
  22. lcd1602功能程序需要的延时函数
  23. ********************************************/
  24. void delay(uint z)
  25. {
  26.         uint x,y;
  27.         for(x=z;x>0;x--)
  28.                 for(y=110;y>0;y--);
  29. }
  30. /*******************************************
  31. 向lcd1602写一个字节命令
  32. ********************************************/
  33. void write_com(uchar com)
  34. {
  35.         lcdrs=0;//写命令
  36.         lcd_out = com;
  37.         delay(5);
  38.         lcden=1;
  39.         delay(5);
  40.         lcden=0;
  41. }
  42. /*******************************************
  43. 向lcd1602写一个字节数据
  44. ********************************************/
  45. void write_data(uchar date)
  46. {
  47.         lcdrs=1;//写数据
  48.         lcd_out = date;
  49.         delay(5);
  50.         lcden=1;
  51.         delay(5);
  52.         lcden=0;
  53. }
  54. /*******************************************
  55. lcd1602初始化
  56. ********************************************/
  57. void lcd1602_init()
  58. {
  59.         lcden=0;
  60.         write_com(0x38);//显示模式设置,16*2显示,5*7点阵,8位并行数据接口
  61.         write_com(0x0c);//显示开,不显示光标,光标不闪烁
  62.         write_com(0x06);//写入一个字符后指针加1,写一个字符时整屏不移动
  63.         write_com(0x01);//清屏,数据指针清0,所有显示清0
  64.         write_com(0x80+0x01);//设置字符显示的首地址,第0行第1列所在的位置
  65. }
  66. /*******************************************
  67. 将字符串*str显示在第y行第x列,x=0~15,y=0~1
  68. *******************************************/
  69. void display_str(uchar x,uchar y,uchar *str)
  70. {
  71.         if(flag_clr == 1)//调换显示界面,先清屏一次
  72.         {
  73.                 write_com(0x01);//清屏,数据指针清0,所有显示清0
  74.                 flag_clr = 0;
  75.         }
  76.         if(y == 0)
  77.                 write_com(0x80+x);//坐标定位在第0行
  78.         else
  79.                 write_com(0xc0+x);//坐标定位在第1行
  80.         write_com(0x0c);//显示开,不显示光标,光标不闪烁
  81.         while(*str != '\0') //判断字符串是否结束
  82.         {
  83.                 write_data(*str);//依次显示字符串中的每一个字符
  84.                 str ++;
  85.         }
  86. }
  87. /*******************************************
  88. 密码输入键处理
  89. ********************************************/
  90. void input(void)
  91. {
  92.         flag_input = 1;//进入密码输入状态,置标志
  93.         flag_clr = 1;//进入密码输入显示界面,置清屏标志
  94.         flag_modify = 0;//去除密码修改标志
  95.         flag_unlock = 0;//取消开锁标志
  96.         flag_error = 0;//取消错误标志
  97.         flag_success = 0;//取消密码修改成功标志
  98.         unlock_out = 1;//设置成关锁状态
  99. }
  100. /*******************************************
  101. 数字键输入处理,将相应的数字保存为密码输入
  102. 数组,并在显示界面相应的位置上显示*字符
  103. ********************************************/
  104. void key_number(uchar num)
  105. {
  106.         if(flag_input == 1)//密码输入状态
  107.         {
  108.                 password_input[n] = num;//密码输入值保存
  109.                 password_input1[n] = '*';//密码输入位上显示*字符
  110.                 n ++ ;                //密码输入个数递增
  111.         }
  112.         if(flag_modify == 1)//修改密码状态
  113.         {
  114.                 password_set[m] = num;//密码输入值保存
  115.                 password_set1[m] = '*';//密码输入位上显示*字符
  116.                 m ++;                //密码输入个数递增
  117.         }
  118. }
  119. /*******************************************
  120. 新输入的密码与旧密码进行比较,正确的返回1
  121. ********************************************/
  122. bit password_compare(uchar *p,uchar *q)
  123. {
  124.         uchar i,count = 0;
  125.         for(i=0;i<6;i++)
  126.         {
  127.                 if(p[i] == q[i])//判断两组6位密码是否一致
  128.                         count ++;
  129.         }
  130.         if(count == 6)
  131.                 return 1;//两组6位密码一致
  132.         else
  133.                 return 0;//两组6位密码不一致
  134. }
  135. /*******************************************************
  136. 开锁键处理
  137. 密码输入后确认是否正确,如果正确,则开锁,否则错误的话
  138. 允许重新输入,并且判断错误输入超过三次,则报警
  139. *******************************************************/
  140. void unlock(void)
  141. {
  142.         uchar i;
  143.         flag_unlock = password_compare(password_input,password_old);
  144.         //将输入的密码与原始密码进行比较是否一致
  145.         if(flag_unlock)//输入的密码与原始密码一致
  146.         {
  147.                 flag_clr = 1;
  148.                 display_str(3,1,"ALL RIGHT !");//密码输入成功显示
  149.                 unlock_out = 0;        //开锁驱动输出低电平信号
  150.                 flag_input = 0;        //清除输入密码状态标志
  151.                 flag_error = 0;        //清除密码输入错误标志
  152.                 error_num = 0;        //清除密码输入错误计数次数
  153.                 sound = 1;                //关闭报警
  154.         }
  155.         else                        //输入的密码与原始密码不一致
  156.         {
  157.                 flag_clr = 1;
  158.                 display_str(3,1,"ERROR !");//密码输入错误显示
  159.                 flag_error = 1;//置密码输入错误标志
  160.                 error_num ++;//密码输入错误次数计数
  161.                 if(error_num > 3)
  162.                         sound = 0;LED=~LED;//如果密码输入错误次数超过3次,则报警
  163. /*******************************************
  164. 创新点:密码输入超过六位显示错误
  165. ********************************************/        
  166.                 if(n>6)
  167.                 {
  168.                 flag_clr=1;
  169.                 display_str(3,1,"ERROR !");
  170.                 }
  171.         }
  172.         n = 0;                //6位密码输入结束时,输入个数计数值回零
  173.         for(i=0;i<6;i++)
  174.                 password_input1[i] = 0x20;//密码输入结束,退出输入状态时显示值重新改为0x20               
  175. }
  176. /*******************************************
  177. 密码修改键处理
  178. ********************************************/
  179. void modify(void)
  180. {
  181.         flag_modify = 1;//进入密码修改状态,置标志
  182.         flag_input = 0;//去除密码输入标志
  183.         flag_clr = 1;//进入密码修改显示界面,置清屏标志
  184.         flag_success = 0;//取消密码修改成功标志
  185.         flag_error = 0;//取消错误标志
  186.         flag_unlock = 0;//取消开锁标志
  187. }
  188. /*******************************************
  189. 退格键处理
  190. ********************************************/
  191. void back(void)
  192. {
  193.         if(flag_input == 1)
  194.         {
  195.                 n -- ;        //密码输入个数计数值递减
  196.                 password_input1[n] = 0x20;//清除*字符显示
  197.         }
  198.         if(flag_modify == 1)
  199.         {
  200.                 m --;        //密码输入个数计数值递减
  201.                 password_set1[m] = 0x20;//清除*字符显示
  202.         }
  203. }
  204. /*******************************************
  205. 清除键处理
  206. ********************************************/
  207. void clear(void)
  208. {
  209.         uchar i;
  210.         if(flag_input == 1)
  211.         {
  212.                 n = 0 ;
  213.                 for(i=0;i<6;i++)
  214.                 {
  215.                         password_input[i] = 0;//清除原先输入的所有密码值
  216.                         password_input1[i] = 0x20;//清除*字符显示
  217.                 }
  218.         }
  219.         if(flag_modify == 1)
  220.         {
  221.                 m = 0;
  222.                 for(i=0;i<18;i++)
  223.                 {
  224.                         password_set[i] = 0;//清除原先输入的所有密码值
  225.                         password_set1[i] = 0x20;//清除*字符显示
  226.                 }
  227.         }
  228. }
  229. /*******************************************
  230. 密码修改,确认键处理
  231. ********************************************/
  232. void enter(void)
  233. {
  234.         bit flag_set = 0,modify_success = 0;
  235.         uchar i;
  236.         uchar password_set2[6],password_new[6];
  237.         for(i=0;i<6;i++)
  238.         {
  239.                 password_set2[i] = password_set[i];//取出输入的旧密码
  240.         }
  241.         flag_set = password_compare(password_set2,password_old);//判断输入的旧密码是否正确
  242.         for(i=0;i<6;i++)
  243.         {
  244.                 password_set2[i] = password_set[i+6];//取出第一次输入的新密码
  245.                 password_new[i] = password_set[i+12];//取出第二次输入的新密码
  246.         }
  247.         modify_success = password_compare(password_set2,password_new);//判断两次输入的新密码是否一致
  248.         if(flag_set==1 && modify_success==1)
  249.         {                //密码修改成功
  250.                 flag_input = 1;//置密码输入状态标志
  251.                 flag_modify = 0;//清除修改密码状态标志
  252.                 for(i=0;i<6;i++)
  253.                 {
  254.                         password_old[i] = password_new[i];//将新修改的密码替换旧密码
  255.                 }
  256.                 flag_success = 1;        //置密码密码修改成功标志
  257.                 flag_error = 0;                //清除密码修改错误标志
  258.                 flag_clr = 1;
  259.                 display_str(0,1,"Modify success !");//密码修改成功时的显示界面
  260.         }
  261.         else
  262.         {
  263.                 flag_success = 0;        //清除密码密码修改成功标志
  264.                 flag_error = 1;                //置密码修改错误标志
  265.                 flag_clr = 1;
  266.                 display_str(3,1,"Error !");//密码修改错误的显示界面
  267.         }
  268.         m = 0;                //密码修改结束,确认后,密码输入个数计数值回零
  269.         for(i=0;i<18;i++)
  270.         {
  271.                 password_set[i] = 0;        //将密码输入值全清零
  272.                 password_set1[i] = 0x20;//将密码输入的显示字符全改为0x20
  273.         }               
  274. }
  275. /*******************************************
  276. LCD1602显示
  277. ********************************************/
  278. void display(void)
  279. {
  280.         uchar j;
  281.         if(flag_unlock!=1 &&flag_success!=1&&flag_error!=1)
  282.         {        //避开密码输入正确时、密码修改成功时以及密码输入错误时的显示界面
  283.                 write_com(0x0c);//显示开,不显示光标,光标不闪烁
  284.                 if(flag_input)
  285.                 {
  286.                         display_str(0,0,"Electronic Lock ");//输入密码状态时的显示界面
  287.                         display_str(0,1,"password:");
  288.                         write_com(0xc0+0x09);
  289.                         for(j=0;j<6;j++)
  290.                                 write_data(password_input1[j]);//密码输入当前6个位置上的显示字符
  291.                         write_com(0xc0+0x09+n);        //当前密码的输入位的坐标定位
  292.                         write_com(0x0f);                //对当前输入位实现光标显示而且光标闪烁
  293.                 }
  294.                 if(flag_modify == 1)
  295.                 {
  296.                         
  297.                          delay(1000);
  298.                         if(m<6)                //修改密码状态时的第一个显示界面
  299.                         {
  300.                                 
  301.                                 display_str(0,0,"Password Modify ");
  302.                                 display_str(0,1,"old_code:");
  303.                                 write_com(0xc0+0x09);
  304.                                 for(j=0;j<6;j++)
  305.                                         write_data(password_set1[j]);//旧密码输入的6个位置显示
  306.                                 write_com(0xc0+0x09+m);//当前密码的输入位的坐标定位
  307.                                 write_com(0x0f);//对当前输入位实现光标显示而且光标闪烁
  308.                         }
  309.                         else                //修改密码状态时的第二个显示界面
  310.                         {
  311.                                 if(m==6)
  312.                                         flag_clr = 1;
  313.                                 display_str(0,0,"new_code:");
  314.                                 write_com(0x80+0x09);
  315.                                 for(j=6;j<12;j++)
  316.                                         write_data(password_set1[j]);//第一次新密码输入的6个位置显示
  317.                                 display_str(0,1,"re_input:");
  318.                                 write_com(0xc0+0x09);
  319.                                 for(j=12;j<18;j++)
  320.                                         write_data(password_set1[j]);//第二次新密码输入的6个位置显示
  321.                                 if(m<12)
  322.                                         write_com(0x80+0x09+m-6);//当前密码的输入位的坐标定位
  323.                                 else
  324.                                         write_com(0xc0+0x09+m-12);//当前密码的输入位的坐标定位
  325.                                 write_com(0x0f);//对当前输入位实现光标显示而且光标闪烁
  326.                         }
  327.                 }
  328.         }
  329. }
  330. /*******************************************
  331. 延时xms函数
  332. ********************************************/
  333. void delay_ms(uint x)
  334. {
  335.         uchar j;
  336.         while(x--)
  337.                 for(j=0;j<80;j++);
  338. }
  339. /*******************************************
  340. 矩阵式按键扫描并处理
  341. ********************************************/
  342. void key_scan()//采用线反转法扫描识别4*4矩阵式按键
  343. {
  344.         uchar a,b;
  345.         P1 = 0xf0;                //①行输出低电平
  346.         if(P1 != 0xf0)//②读取列的电平,判定有键按下
  347.         {
  348.                 delay_ms(10);//③延时10ms,避开抖动期
  349.                 if(P1 != 0xf0);//④再次确认有键按下
  350.                 {
  351.                         sound = 0;
  352.                         a = P1;//⑤读取列的电平,通过0所在的位判断按下的键所在的列
  353.                         P1 = 0x0f;        //⑥列输出低电平
  354.                         b = P1;                //⑦读取行的电平,通过0所在的位判断按下的键所在的行
  355.                         while(P1 == b);//⑧等待按键释放
  356.                         sound = 1;
  357.                         a = a | b;        //⑨计算获得键值,综合两个0所在的位,判断按下的键在相应的行与列的交叉点
  358.                         switch(a)        //⑩根据键值得出所按下的按键
  359.                         {
  360.                                 case 0xee:        key_number(0);break;//0~9数字键
  361.                                 case 0xde:        key_number(1);break;
  362.                                 case 0xbe:        key_number(2);break;
  363.                                 case 0x7e:        key_number(3);break;
  364.                                 case 0xed:        key_number(4);break;
  365.                                 case 0xdd:        key_number(5);break;
  366.                                 case 0xbd:        key_number(6);break;
  367.                                 case 0x7d:        key_number(7);break;
  368.                                 case 0xeb:        key_number(8);break;
  369.                                 case 0xdb:        key_number(9);break;
  370.                                 case 0xbb:        unlock();break;        //开锁键
  371.                                 case 0x7b:        input();break;        //密码输入键
  372.                                 case 0xe7:        enter();break;        //密码修改确认键
  373.                                 case 0xd7:        clear();break;        //清除键
  374.                                 case 0xb7:        back();break;        //退格键
  375.                                 case 0x77:        modify();break;        //密码修改键
  376.                                 default:break;
  377.                         }
  378.                         display();//显示
  379.                 }
  380.         }
  381. }

  382. /*******************************************
  383. 主函数
  384. ********************************************/
  385. void main()
  386. {
  387.         uchar i;
  388.         for(i=0;i<6;i++)
  389.                 password_input1[i] = 0x20;//密码输入数组初始化为0x20,显示为空格字符
  390.         for(i=0;i<18;i++)
  391.                 password_set1[i] = 0x20;//修改密码时密码输入数组初始化为0x20

  392.         lcd1602_init();

  393.         while(1)
  394.         {
  395.                 key_scan();
  396.         }
  397. }
复制代码


全部资料51hei下载地址:
循环扫描法.zip (116.8 KB, 下载次数: 2)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:517466 发表于 2021-1-14 21:03 | 只看该作者
1、建立一个标志,在main函数中,如果矩阵按键有按键按下,建立标志。
2、在矩阵按键没有按键按下时,在执行矩阵按键扫描开始前,如果标志没有被修改过(见步骤1),检查K1是否按下。按下了,就执行显示"Welcome Back"的处理。
2所在的处理,要放在主函数的while的循环中,在key_scan之前。
只要逻辑正确,2所在的处理放在key_scan函数中也没有关系。
回复

使用道具 举报

板凳
ID:872539 发表于 2021-1-14 21:09 | 只看该作者
还有一个问题就是,加上什么代码会使密码错误三次时led灯闪
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表