找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 1762|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

如何在單片機(jī)程序中修改使按下K1按鍵屏幕開(kāi)機(jī)顯示W(wǎng)elcom Back

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主


單片機(jī)源程序如下:
  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};//初始密碼存放數(shù)組
  5. uchar idata password_input[6];//密碼輸入值保存數(shù)組
  6. uchar idata password_input1[6];//密碼輸入顯示*字符存放數(shù)組
  7. uchar idata password_set[18];//修改密碼時(shí)密碼輸入值保存數(shù)組
  8. uchar idata password_set1[18];//修改密碼時(shí)密碼輸入顯示*字符存放數(shù)組
  9. sbit sound = P3^2;//報(bào)警控制輸出端口
  10. sbit unlock_out = P3^3;//開(kāi)鎖驅(qū)動(dòng)控制輸出端口
  11. bit flag_input,flag_modify,flag_unlock,flag_success,flag_error,flag_clr;
  12. //密碼輸入狀態(tài)標(biāo)志,修改密碼狀態(tài)標(biāo)志,是否可以開(kāi)鎖標(biāo)志,密碼修改成功標(biāo)志
  13. //密碼輸入錯(cuò)誤或密碼修改錯(cuò)誤標(biāo)志,調(diào)換顯示界面時(shí)清屏標(biāo)志
  14. uchar error_num;//密碼輸入錯(cuò)誤計(jì)數(shù)
  15. uchar n,m;//密碼輸入狀態(tài)下輸入個(gè)數(shù)計(jì)數(shù)n,修改密碼狀態(tài)下輸入個(gè)數(shù)計(jì)數(shù)m
  16. #define lcd_out P0        //LCD1602接口設(shè)置
  17. sbit lcden = P2^1;
  18. sbit lcdrs = P2^0;
  19. sbit LED=P3^4;
  20. sbit K1=P3^5;        
  21. /*******************************************
  22. lcd1602功能程序需要的延時(shí)函數(shù)
  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寫(xiě)一個(gè)字節(jié)命令
  32. ********************************************/
  33. void write_com(uchar com)
  34. {
  35.         lcdrs=0;//寫(xiě)命令
  36.         lcd_out = com;
  37.         delay(5);
  38.         lcden=1;
  39.         delay(5);
  40.         lcden=0;
  41. }
  42. /*******************************************
  43. 向lcd1602寫(xiě)一個(gè)字節(jié)數(shù)據(jù)
  44. ********************************************/
  45. void write_data(uchar date)
  46. {
  47.         lcdrs=1;//寫(xiě)數(shù)據(jù)
  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);//顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣,8位并行數(shù)據(jù)接口
  61.         write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
  62.         write_com(0x06);//寫(xiě)入一個(gè)字符后指針加1,寫(xiě)一個(gè)字符時(shí)整屏不移動(dòng)
  63.         write_com(0x01);//清屏,數(shù)據(jù)指針清0,所有顯示清0
  64.         write_com(0x80+0x01);//設(shè)置字符顯示的首地址,第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)//調(diào)換顯示界面,先清屏一次
  72.         {
  73.                 write_com(0x01);//清屏,數(shù)據(jù)指針清0,所有顯示清0
  74.                 flag_clr = 0;
  75.         }
  76.         if(y == 0)
  77.                 write_com(0x80+x);//坐標(biāo)定位在第0行
  78.         else
  79.                 write_com(0xc0+x);//坐標(biāo)定位在第1行
  80.         write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
  81.         while(*str != '\0') //判斷字符串是否結(jié)束
  82.         {
  83.                 write_data(*str);//依次顯示字符串中的每一個(gè)字符
  84.                 str ++;
  85.         }
  86. }
  87. /*******************************************
  88. 密碼輸入鍵處理
  89. ********************************************/
  90. void input(void)
  91. {
  92.         flag_input = 1;//進(jìn)入密碼輸入狀態(tài),置標(biāo)志
  93.         flag_clr = 1;//進(jìn)入密碼輸入顯示界面,置清屏標(biāo)志
  94.         flag_modify = 0;//去除密碼修改標(biāo)志
  95.         flag_unlock = 0;//取消開(kāi)鎖標(biāo)志
  96.         flag_error = 0;//取消錯(cuò)誤標(biāo)志
  97.         flag_success = 0;//取消密碼修改成功標(biāo)志
  98.         unlock_out = 1;//設(shè)置成關(guān)鎖狀態(tài)
  99. }
  100. /*******************************************
  101. 數(shù)字鍵輸入處理,將相應(yīng)的數(shù)字保存為密碼輸入
  102. 數(shù)組,并在顯示界面相應(yīng)的位置上顯示*字符
  103. ********************************************/
  104. void key_number(uchar num)
  105. {
  106.         if(flag_input == 1)//密碼輸入狀態(tài)
  107.         {
  108.                 password_input[n] = num;//密碼輸入值保存
  109.                 password_input1[n] = '*';//密碼輸入位上顯示*字符
  110.                 n ++ ;                //密碼輸入個(gè)數(shù)遞增
  111.         }
  112.         if(flag_modify == 1)//修改密碼狀態(tài)
  113.         {
  114.                 password_set[m] = num;//密碼輸入值保存
  115.                 password_set1[m] = '*';//密碼輸入位上顯示*字符
  116.                 m ++;                //密碼輸入個(gè)數(shù)遞增
  117.         }
  118. }
  119. /*******************************************
  120. 新輸入的密碼與舊密碼進(jìn)行比較,正確的返回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. 開(kāi)鎖鍵處理
  137. 密碼輸入后確認(rèn)是否正確,如果正確,則開(kāi)鎖,否則錯(cuò)誤的話
  138. 允許重新輸入,并且判斷錯(cuò)誤輸入超過(guò)三次,則報(bào)警
  139. *******************************************************/
  140. void unlock(void)
  141. {
  142.         uchar i;
  143.         flag_unlock = password_compare(password_input,password_old);
  144.         //將輸入的密碼與原始密碼進(jìn)行比較是否一致
  145.         if(flag_unlock)//輸入的密碼與原始密碼一致
  146.         {
  147.                 flag_clr = 1;
  148.                 display_str(3,1,"ALL RIGHT !");//密碼輸入成功顯示
  149.                 unlock_out = 0;        //開(kāi)鎖驅(qū)動(dòng)輸出低電平信號(hào)
  150.                 flag_input = 0;        //清除輸入密碼狀態(tài)標(biāo)志
  151.                 flag_error = 0;        //清除密碼輸入錯(cuò)誤標(biāo)志
  152.                 error_num = 0;        //清除密碼輸入錯(cuò)誤計(jì)數(shù)次數(shù)
  153.                 sound = 1;                //關(guān)閉報(bào)警
  154.         }
  155.         else                        //輸入的密碼與原始密碼不一致
  156.         {
  157.                 flag_clr = 1;
  158.                 display_str(3,1,"ERROR !");//密碼輸入錯(cuò)誤顯示
  159.                 flag_error = 1;//置密碼輸入錯(cuò)誤標(biāo)志
  160.                 error_num ++;//密碼輸入錯(cuò)誤次數(shù)計(jì)數(shù)
  161.                 if(error_num > 3)
  162.                         sound = 0;LED=~LED;//如果密碼輸入錯(cuò)誤次數(shù)超過(guò)3次,則報(bào)警
  163. /*******************************************
  164. 創(chuàng)新點(diǎn):密碼輸入超過(guò)六位顯示錯(cuò)誤
  165. ********************************************/        
  166.                 if(n>6)
  167.                 {
  168.                 flag_clr=1;
  169.                 display_str(3,1,"ERROR !");
  170.                 }
  171.         }
  172.         n = 0;                //6位密碼輸入結(jié)束時(shí),輸入個(gè)數(shù)計(jì)數(shù)值回零
  173.         for(i=0;i<6;i++)
  174.                 password_input1[i] = 0x20;//密碼輸入結(jié)束,退出輸入狀態(tài)時(shí)顯示值重新改為0x20               
  175. }
  176. /*******************************************
  177. 密碼修改鍵處理
  178. ********************************************/
  179. void modify(void)
  180. {
  181.         flag_modify = 1;//進(jìn)入密碼修改狀態(tài),置標(biāo)志
  182.         flag_input = 0;//去除密碼輸入標(biāo)志
  183.         flag_clr = 1;//進(jìn)入密碼修改顯示界面,置清屏標(biāo)志
  184.         flag_success = 0;//取消密碼修改成功標(biāo)志
  185.         flag_error = 0;//取消錯(cuò)誤標(biāo)志
  186.         flag_unlock = 0;//取消開(kāi)鎖標(biāo)志
  187. }
  188. /*******************************************
  189. 退格鍵處理
  190. ********************************************/
  191. void back(void)
  192. {
  193.         if(flag_input == 1)
  194.         {
  195.                 n -- ;        //密碼輸入個(gè)數(shù)計(jì)數(shù)值遞減
  196.                 password_input1[n] = 0x20;//清除*字符顯示
  197.         }
  198.         if(flag_modify == 1)
  199.         {
  200.                 m --;        //密碼輸入個(gè)數(shù)計(jì)數(shù)值遞減
  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. 密碼修改,確認(rèn)鍵處理
  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;//置密碼輸入狀態(tài)標(biāo)志
  251.                 flag_modify = 0;//清除修改密碼狀態(tài)標(biāo)志
  252.                 for(i=0;i<6;i++)
  253.                 {
  254.                         password_old[i] = password_new[i];//將新修改的密碼替換舊密碼
  255.                 }
  256.                 flag_success = 1;        //置密碼密碼修改成功標(biāo)志
  257.                 flag_error = 0;                //清除密碼修改錯(cuò)誤標(biāo)志
  258.                 flag_clr = 1;
  259.                 display_str(0,1,"Modify success !");//密碼修改成功時(shí)的顯示界面
  260.         }
  261.         else
  262.         {
  263.                 flag_success = 0;        //清除密碼密碼修改成功標(biāo)志
  264.                 flag_error = 1;                //置密碼修改錯(cuò)誤標(biāo)志
  265.                 flag_clr = 1;
  266.                 display_str(3,1,"Error !");//密碼修改錯(cuò)誤的顯示界面
  267.         }
  268.         m = 0;                //密碼修改結(jié)束,確認(rèn)后,密碼輸入個(gè)數(shù)計(jì)數(shù)值回零
  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.         {        //避開(kāi)密碼輸入正確時(shí)、密碼修改成功時(shí)以及密碼輸入錯(cuò)誤時(shí)的顯示界面
  283.                 write_com(0x0c);//顯示開(kāi),不顯示光標(biāo),光標(biāo)不閃爍
  284.                 if(flag_input)
  285.                 {
  286.                         display_str(0,0,"Electronic Lock ");//輸入密碼狀態(tài)時(shí)的顯示界面
  287.                         display_str(0,1,"password:");
  288.                         write_com(0xc0+0x09);
  289.                         for(j=0;j<6;j++)
  290.                                 write_data(password_input1[j]);//密碼輸入當(dāng)前6個(gè)位置上的顯示字符
  291.                         write_com(0xc0+0x09+n);        //當(dāng)前密碼的輸入位的坐標(biāo)定位
  292.                         write_com(0x0f);                //對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
  293.                 }
  294.                 if(flag_modify == 1)
  295.                 {
  296.                         
  297.                          delay(1000);
  298.                         if(m<6)                //修改密碼狀態(tài)時(shí)的第一個(gè)顯示界面
  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個(gè)位置顯示
  306.                                 write_com(0xc0+0x09+m);//當(dāng)前密碼的輸入位的坐標(biāo)定位
  307.                                 write_com(0x0f);//對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
  308.                         }
  309.                         else                //修改密碼狀態(tài)時(shí)的第二個(gè)顯示界面
  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個(gè)位置顯示
  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個(gè)位置顯示
  321.                                 if(m<12)
  322.                                         write_com(0x80+0x09+m-6);//當(dāng)前密碼的輸入位的坐標(biāo)定位
  323.                                 else
  324.                                         write_com(0xc0+0x09+m-12);//當(dāng)前密碼的輸入位的坐標(biāo)定位
  325.                                 write_com(0x0f);//對(duì)當(dāng)前輸入位實(shí)現(xiàn)光標(biāo)顯示而且光標(biāo)閃爍
  326.                         }
  327.                 }
  328.         }
  329. }
  330. /*******************************************
  331. 延時(shí)xms函數(shù)
  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()//采用線反轉(zhuǎn)法掃描識(shí)別4*4矩陣式按鍵
  343. {
  344.         uchar a,b;
  345.         P1 = 0xf0;                //①行輸出低電平
  346.         if(P1 != 0xf0)//②讀取列的電平,判定有鍵按下
  347.         {
  348.                 delay_ms(10);//③延時(shí)10ms,避開(kāi)抖動(dòng)期
  349.                 if(P1 != 0xf0);//④再次確認(rèn)有鍵按下
  350.                 {
  351.                         sound = 0;
  352.                         a = P1;//⑤讀取列的電平,通過(guò)0所在的位判斷按下的鍵所在的列
  353.                         P1 = 0x0f;        //⑥列輸出低電平
  354.                         b = P1;                //⑦讀取行的電平,通過(guò)0所在的位判斷按下的鍵所在的行
  355.                         while(P1 == b);//⑧等待按鍵釋放
  356.                         sound = 1;
  357.                         a = a | b;        //⑨計(jì)算獲得鍵值,綜合兩個(gè)0所在的位,判斷按下的鍵在相應(yīng)的行與列的交叉點(diǎn)
  358.                         switch(a)        //⑩根據(jù)鍵值得出所按下的按鍵
  359.                         {
  360.                                 case 0xee:        key_number(0);break;//0~9數(shù)字鍵
  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;        //開(kāi)鎖鍵
  371.                                 case 0x7b:        input();break;        //密碼輸入鍵
  372.                                 case 0xe7:        enter();break;        //密碼修改確認(rèn)鍵
  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. 主函數(shù)
  384. ********************************************/
  385. void main()
  386. {
  387.         uchar i;
  388.         for(i=0;i<6;i++)
  389.                 password_input1[i] = 0x20;//密碼輸入數(shù)組初始化為0x20,顯示為空格字符
  390.         for(i=0;i<18;i++)
  391.                 password_set1[i] = 0x20;//修改密碼時(shí)密碼輸入數(shù)組初始化為0x20

  392.         lcd1602_init();

  393.         while(1)
  394.         {
  395.                 key_scan();
  396.         }
  397. }
復(fù)制代碼


全部資料51hei下載地址:
循環(huán)掃描法.zip (116.8 KB, 下載次數(shù): 2)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:517466 發(fā)表于 2021-1-14 21:03 | 只看該作者
1、建立一個(gè)標(biāo)志,在main函數(shù)中,如果矩陣按鍵有按鍵按下,建立標(biāo)志。
2、在矩陣按鍵沒(méi)有按鍵按下時(shí),在執(zhí)行矩陣按鍵掃描開(kāi)始前,如果標(biāo)志沒(méi)有被修改過(guò)(見(jiàn)步驟1),檢查K1是否按下。按下了,就執(zhí)行顯示"Welcome Back"的處理。
2所在的處理,要放在主函數(shù)的while的循環(huán)中,在key_scan之前。
只要邏輯正確,2所在的處理放在key_scan函數(shù)中也沒(méi)有關(guān)系。
回復(fù)

使用道具 舉報(bào)

板凳
ID:872539 發(fā)表于 2021-1-14 21:09 | 只看該作者
還有一個(gè)問(wèn)題就是,加上什么代碼會(huì)使密碼錯(cuò)誤三次時(shí)led燈閃
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表