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

QQ登錄

只需一步,快速開始

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

51單片機(jī)+LCD12864實(shí)現(xiàn)密碼鎖Proteus仿真和代碼

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:410062 發(fā)表于 2018-12-23 15:08 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
51單片機(jī)-密碼鎖仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include <reg51.h>      //  包含51單片機(jī)寄存器定義的頭文件
  2. #include <intrins.h>    //包含_nop_()函數(shù)定義的頭文件
  3. #include<string.h>
  4. #include <12864.h>
  5. #include<KEYPAD4_3.h>
  6. #define N 8
  7. #define        NOP5() {_nop_();_nop_();_nop_();_nop_();_nop_();}        // 執(zhí)行5個(gè)空操作,延時(shí)5微秒
  8. unsigned char readerror=0;  //讀取成功為0,否則為1
  9. unsigned char writeerror=0; //寫入成功為0,否則為1
  10. unsigned char Rbuff[10]={0};
  11. unsigned char Wbuff[10]="0000";
  12. sbit SDA=P2^7;          //將串行數(shù)據(jù)總線SDA位定義在為P3.4引腳
  13. sbit SCL=P2^6;          //將串行時(shí)鐘總線SDA位定義在為P3.3引腳
  14. sbit led = P2^0;
  15. u8 str[]="123456789*0#";
  16. u8 s[10]={0};
  17. /*****************************************************
  18. 函數(shù)功能:延時(shí)若干毫秒
  19. 入口參數(shù):n
  20. *****************************************************/
  21. void delay_ms(unsigned int n)
  22. {
  23.    unsigned int i,j;       
  24.          for(i=0;i<n;i++)
  25.           for(j=0;j<110;j++);                 
  26. }
  27. /***************************************************
  28. 函數(shù)功能:開始數(shù)據(jù)傳送
  29. ***************************************************/
  30. void start()
  31. // 開始位
  32. {
  33.         SDA = 1;    //SDA初始化為高電平“1”
  34.     SCL = 1;    //開始數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
  35.         NOP5();
  36.         SDA = 0;    //SDA的下降沿被認(rèn)為是開始信號(hào)
  37.         NOP5();
  38.         SCL = 0;    //SCL為低電平時(shí),SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)  
  39. }
  40. /***************************************************
  41. 函數(shù)功能:結(jié)束數(shù)據(jù)傳送
  42. ***************************************************/
  43. void stop()
  44. // 停止位
  45. {
  46.         SDA = 0;     //SDA初始化為低電平“0”        _n
  47.         SCL = 1;     //結(jié)束數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
  48.         NOP5();
  49.         SDA = 1;    //SDA的上升沿被認(rèn)為是結(jié)束信號(hào)
  50.         NOP5();       
  51. }
  52. /***************************************************
  53. 函數(shù)功能:發(fā)送應(yīng)答/非應(yīng)答信號(hào)
  54. ***************************************************/
  55. void Send_Ack(bit ack)
  56. //ack=0表示應(yīng)答;ack=1表示非應(yīng)答
  57. {
  58.         SCL = 0; //拉低SCL為輸出數(shù)據(jù)到SDA做準(zhǔn)備
  59.         SDA = ack; //輸出ack到SDA,表示應(yīng)答/不應(yīng)答
  60.         SCL = 1;
  61.         NOP5();   //NOP5()>4us
  62.     SCL = 0;    //SCL從0-1-0為一個(gè)完整的時(shí)鐘周期
  63.     SDA=1;//釋放總線
  64. }
  65. /***************************************************
  66. 函數(shù)功能:查詢/接收應(yīng)答信號(hào)
  67. ***************************************************/
  68. unsigned char Rec_Ack(void)   
  69. //返回值為0表示應(yīng)答,為1表示非應(yīng)答
  70. {unsigned char i,ack;
  71. SCL=0;  //拉低SCL為輸出數(shù)據(jù)到SDA做準(zhǔn)備
  72. SDA = 1; //釋放總線,讓從設(shè)備能輸出數(shù)據(jù)到SDA
  73. SCL=1;
  74. while((SDA==1)&&(i<250)) i++;
  75. /*等待從設(shè)備發(fā)送應(yīng)答信號(hào),若為0,表示應(yīng)答,循環(huán)結(jié)束;若為1,可能是從機(jī)還未將信號(hào)送上來,循環(huán)延時(shí)到i>250,若仍為1,此時(shí)才認(rèn)為是未應(yīng)答*/
  76. ack=SDA;
  77. SCL = 0;//SCL從0-1-0為一個(gè)完整的時(shí)鐘周期
  78. SDA=1; //釋放總線
  79. return(ack);
  80. }
  81. /***************************************************
  82. 函數(shù)功能:從AT24Cxx讀取數(shù)據(jù)
  83. 出口參數(shù):recbyte
  84. ***************************************************/
  85. unsigned char ReadData()
  86. // 從AT24Cxx中讀取一個(gè)字節(jié)數(shù)據(jù)到MCU
  87. {
  88.         unsigned char i;
  89.         unsigned char recbyte;   //儲(chǔ)存從AT24Cxx中讀出的數(shù)據(jù)
  90.         SCL=0;         //拉低SCL為從設(shè)備輸出數(shù)據(jù)到SDA做準(zhǔn)備
  91.     SDA=1; //釋放總線
  92.     for(i = 0; i < 8; i++)
  93.         {
  94.                 SCL = 1;                //SCL置為高電平
  95.                 NOP5();
  96.         recbyte=(recbyte<<1)|SDA;       //讀SDA
  97.         SCL=0;                       //SCL從0-1-0為一個(gè)完整的時(shí)鐘周期
  98.     }
  99.     SDA=1;
  100.         return(recbyte);         //返回所讀數(shù)據(jù)
  101. }
  102. /***************************************************
  103. 函數(shù)功能:向AT24Cxx的當(dāng)前地址寫入數(shù)據(jù)
  104. 入口參數(shù):sendbyte (儲(chǔ)存待寫入的數(shù)據(jù))
  105. ***************************************************/
  106. //在調(diào)用此數(shù)據(jù)寫入函數(shù)前需首先調(diào)用開始函數(shù)start(),所以SCL=0
  107. void WriteData(unsigned char sendbyte)
  108. {
  109.         unsigned char i;
  110.         for(i = 0; i < 8; i++)                // 循環(huán)移入8個(gè)位
  111.         {
  112.             sendbyte<<=1; //左移時(shí)最低位補(bǔ)0,最高位移入PSW的CY位
  113.         SDA=CY;        //輸出數(shù)據(jù)到SDA
  114.         SCL = 1;            //在SCL的上升沿將數(shù)據(jù)寫入AT24Cxx      
  115.                NOP5();                 
  116.             SCL = 0;            //將SCL重新置為低電平,以在SCL線形成傳送數(shù)據(jù)所需的8?jìng)(gè)脈沖
  117.          }
  118.         SDA = 1;  // 發(fā)送設(shè)備(主機(jī))應(yīng)在時(shí)鐘脈沖的高電平期間(SCL=1)釋放SDA線,
  119. }
  120. /***************************************************
  121. 函數(shù)功能:向AT24Cxx中的指定地址寫入數(shù)據(jù)
  122. 入口參數(shù):add (儲(chǔ)存指定的地址);dat(儲(chǔ)存待寫入的數(shù)據(jù))
  123. ***************************************************/
  124. void WriteRom(unsigned char add, unsigned char dat[],unsigned char j)
  125. // 將數(shù)組里的j個(gè)字節(jié)的數(shù)據(jù)寫入到起始地址為addr處的連續(xù)區(qū)域中
  126. {  unsigned char flag=0,k=0,i=3;//i為允許最大重寫次數(shù),若出現(xiàn)i次操作失效后,則函數(shù)中止操作,并返回
  127.    while(i--)
  128.    {start();             //開始數(shù)據(jù)傳遞
  129.         WriteData(0xa0);  //選擇要操作的AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù),器件地址以及寫入操作為1010 0000B(0xa0)
  130.         if(Rec_Ack()) continue;
  131.     WriteData(add);   //寫入器件內(nèi)部地址
  132.         if(Rec_Ack()) continue;
  133.     while(j--)
  134.         {WriteData(dat[k++]);   //向當(dāng)前地址(上面指定的地址)寫入數(shù)據(jù)
  135.          if(!Rec_Ack()) continue;
  136.      flag=1;
  137.          break;
  138.         }
  139.         if(flag)  continue;/*能不能改成:if(j>=0)  continue? (j>=0意味著數(shù)據(jù)未寫完,即出現(xiàn)了未應(yīng)答,要重寫)*/
  140.         break;
  141.    }
  142.    stop();                //停止數(shù)據(jù)傳遞         
  143.    if(i<0) writeerror=1;     
  144. }
  145. /***************************************************
  146. 函數(shù)功能:從AT24Cxx中的指定地址讀取數(shù)據(jù)
  147. 入口參數(shù):set_addr
  148. 出口參數(shù):x
  149. ***************************************************/
  150. void ReadRom(unsigned char set_addr,unsigned char dat[],unsigned char j)
  151. // 在指定地址開始連續(xù)讀取j個(gè)字節(jié),并將數(shù)據(jù)存放到數(shù)組中
  152. { unsigned char i=3,k=0;//i為允許最大重讀次數(shù),若出現(xiàn)i次操作失效后,則函數(shù)中止操作,并返回
  153.   while(i--)
  154.   {        start();             //開始數(shù)據(jù)傳遞
  155.         WriteData(0xa0);     //選擇要操作的AT24Cxx芯片,并告知要對(duì)其寫入數(shù)據(jù),器件地址以及寫入操作為1010 0000B(0xa0)
  156.         if(Rec_Ack()) continue;
  157.     WriteData(set_addr);       //寫入指定地址
  158.         if(Rec_Ack()) continue;
  159.     start();//調(diào)啟動(dòng)總線函數(shù)
  160.     WriteData(0xa1);    //選擇器件要操作的AT24Cxx芯片,并告知要對(duì)其讀取數(shù)據(jù),器件地址以及讀取操作為1010 0001B(0xa1)
  161.     if(Rec_Ack()) continue;//如果操作失敗,就退出
  162.     while(--j)
  163.         { dat[k++]=ReadData();
  164.           Send_Ack(0);          
  165.         }//接收前j-1個(gè)字節(jié),并應(yīng)答
  166.         dat[k++]=ReadData();//接收最后一個(gè)字節(jié)
  167.         Send_Ack(1);//向從設(shè)備發(fā)出非應(yīng)答信號(hào),結(jié)束數(shù)據(jù)傳輸
  168.     break;
  169.   }
  170.   stop();
  171.   if(i<0) readerror=1;  
  172. }


  173. //密碼錯(cuò)誤時(shí)
  174. void mimacuowu(){
  175.         lcd_wcmd(0x01);
  176.         lcd12864_pos(0,0);
  177.         LCD12864disp("密碼錯(cuò)誤!");
  178.         lcd12864_pos(1,0);
  179.         LCD12864disp("請(qǐng)重新輸入!");
  180.         delay_ms(1000);
  181.         lcd_wcmd(0x01);
  182.         lcd12864_pos(0,0);
  183.         LCD12864disp("請(qǐng)輸入密碼:");
  184.         lcd12864_pos(1,0);
  185. }


  186. //密碼正確時(shí)
  187. u8 zhengque(){
  188.                   u8 key;
  189.                 lcd_wcmd(0x01);
  190.                 lcd12864_pos(0,0);
  191.                 LCD12864disp("開鎖成功!");
  192.                 lcd12864_pos(1,0);
  193.                 LCD12864disp("是否修改密碼?");
  194.                 lcd12864_pos(2,0);
  195.                 LCD12864disp("1:是,2:否");
  196.                 lcd12864_pos(3,0);
  197.                 while(1){
  198.                         key=keypad4_3();
  199.                         if(key==0 || key==1){
  200.                                 if(key==0)  LCD12864disp("1");
  201.                                 else        LCD12864disp("2");
  202.                                 delay_ms(1000);
  203.                                 return key;
  204.                                 }
  205.                 }
  206. }

  207. //改密碼
  208. void gai(){
  209.         u8 key,a=0;
  210.         u8 s1[10]={0};
  211.         u8 s2[10]={0};
  212.         lcd_wcmd(0x01);
  213.         lcd12864_pos(0,0);
  214.         LCD12864disp("請(qǐng)輸入密碼:");
  215.         lcd12864_pos(1,0);
  216.         while(1){
  217.                 key=keypad4_3();
  218.                 if(key<12)
  219.                 {
  220.                         if(key==9)         LCD12864_backspace();
  221.                         if(key==11)  break;
  222.                         if(key!=9 && key!=11){s1[a++]=str[key]; LCD12864disp("*");}
  223.                 }
  224.         }
  225.         lcd12864_pos(2,0);
  226.         LCD12864disp("再次輸入密碼:");
  227.         lcd12864_pos(3,0);
  228.         a=0;
  229.         while(1){
  230.         key=keypad4_3();       
  231.         if(key<12)
  232.         {
  233.                 if(key==9)         LCD12864_backspace();
  234.                 if(key==11)  break;
  235.                 if(key!=9 && key!=11){s2[a++]=str[key]; LCD12864disp("*");}
  236.                 }
  237.         }
  238.         if(strcmp(s1,s2)==0){
  239.                 SDA = 1;           //I2C初始化:SDA=1,SCL=1,使主從設(shè)備處于空閑狀態(tài)
  240.                    SCL = 1;
  241.                 memset(Rbuff,0,sizeof(s));   //再次初始化數(shù)組
  242.                 strcpy(Rbuff,s2);
  243.                 //WriteRom(0x32,s2,10);   //向起始地址為“0x32”的連續(xù)區(qū)域中寫入數(shù)組Wbuff中的5個(gè)數(shù)據(jù)
  244.                    //ReadRom(0x32,Rbuff,10);    //從起始地址為“0x32”的連續(xù)區(qū)域中讀取5個(gè)數(shù)據(jù)到數(shù)組Rbuff中
  245.                   
  246.                 lcd_wcmd(0x01);
  247.                 lcd12864_pos(0,0);
  248.                 LCD12864disp("密碼修改成功");
  249.                 delay_ms(2000);

  250.                    lcd_wcmd(0x01);
  251.                 lcd12864_pos(0,0);
  252.                 LCD12864disp("請(qǐng)輸入密碼:");
  253.                 lcd12864_pos(1,0);
  254.         }
  255.         else
  256.         {
  257.                 lcd_wcmd(0x01);
  258.                 lcd12864_pos(0,0);
  259.                 LCD12864disp("兩次輸入不一致");
  260.                 lcd12864_pos(1,0);
  261.                 LCD12864disp("密碼修改失敗");
  262.                 delay_ms(2000);

  263.                 lcd_wcmd(0x01);
  264.                 lcd12864_pos(0,0);
  265.                 LCD12864disp("請(qǐng)輸入密碼:");
  266.                 lcd12864_pos(1,0);       
  267.         }
  268. }

  269. /***************************************************
  270. 函數(shù)功能:主函數(shù)
  271. ***************************************************/
  272. void main()
  273. {  
  274.    int a=0,flage=1;
  275.    unsigned char i=0;
  276.    u8 key,f;
  277.    SDA = 1;           //I2C初始化:SDA=1,SCL=1,使主從設(shè)備處于空閑狀態(tài)
  278.    SCL = 1;  
  279.    //led = 1;               
  280.    WriteRom(0x32,Wbuff,10);   //向起始地址為“0x32”的連續(xù)區(qū)域中寫入數(shù)組Wbuff中的5個(gè)數(shù)據(jù)
  281.    ReadRom(0x32,Rbuff,10);    //從起始地址為“0x32”的連續(xù)區(qū)域中讀取5個(gè)數(shù)據(jù)到數(shù)組Rbuff中
  282.           
  283.     //初始化

  284.    /*while(i<N)
  285.      { P1=Rbuff[i];
  286.            delaynms(1000);
  287.            i++;        //將讀出的數(shù)據(jù)送P1口顯示
  288.          }*/
  289.        
  290.         lcd12864_init();
  291.           lcd12864_pos(0,0);
  292.         //lcd_wcmd(0x01);
  293.         LCD12864disp("請(qǐng)輸入密碼:");
  294.         lcd12864_pos(1,0);
  295.           while(1)
  296.           {

  297.           key=keypad4_3();

  298.         if(key<12){ if(key==9) {LCD12864_backspace();}  //刪除
  299.                            if(key==11) //密碼確認(rèn)
  300.                            {
  301.                                   
  302.                                      if(strcmp(Rbuff,s)==0) flage=0;  //正確
  303.                                   else flage=1;                                           //錯(cuò)誤
  304.                                   if(flage==0)
  305.                                   {
  306.                                              led=0;   //燈亮
  307.                                             f=zhengque();
  308.                                           if(f==0){
  309.                                              
  310.                                                     gai();
  311.                                           }
  312.                                           if(f==1){
  313.                                                           lcd_wcmd(0x01);
  314.                                                           lcd12864_pos(0,0);
  315.                                                         LCD12864disp("請(qǐng)輸入密碼:");
  316.                                                         lcd12864_pos(1,0);       
  317.                                           }
  318.                                           led = 1;   //燈滅
  319.                                           a=0;
  320.                                           memset(s,0,sizeof(s));   //再次初始化數(shù)組
  321.                                   }
  322.                                   else
  323.                                   {
  324.                                             mimacuowu();
  325.                                           a=0;
  326.                                           memset(s,0,sizeof(s));   //再次初始化數(shù)組
  327.                                   }
  328.                            }
  329.                           if(key!=9 && key!=11) {s[a++]=str[key]; LCD12864disp("*");}
  330.                           }          
  331.   }                 
  332. }
復(fù)制代碼

所有資料51hei提供下載:
密碼鎖.zip (295.89 KB, 下載次數(shù): 233)


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:393984 發(fā)表于 2019-1-15 15:54 | 只看該作者
這個(gè)可以成功的嗎?
回復(fù)

使用道具 舉報(bào)

板凳
ID:454000 發(fā)表于 2019-1-16 01:24 | 只看該作者
yangqun1998 發(fā)表于 2019-1-15 15:54
這個(gè)可以成功的嗎?

我空間有16位的,仿真絕對(duì)沒任何問題

評(píng)分

參與人數(shù) 2黑幣 +30 收起 理由
還有誰? + 15
鉆牛尖滴劉尖尖 + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

地板
ID:524025 發(fā)表于 2019-5-6 16:53 | 只看該作者
這個(gè)初始密碼是什么啊
回復(fù)

使用道具 舉報(bào)

5#
ID:473704 發(fā)表于 2019-6-21 17:35 | 只看該作者
帶中文字庫的12864怎么做出來的
回復(fù)

使用道具 舉報(bào)

6#
ID:432151 發(fā)表于 2019-9-8 15:07 | 只看該作者
非常感謝,很有用
回復(fù)

使用道具 舉報(bào)

7#
ID:247623 發(fā)表于 2021-4-10 23:16 | 只看該作者
shuisheng 發(fā)表于 2019-1-16 01:24
我空間有16位的,仿真絕對(duì)沒任何問題

你好,你空間我看了,沒有找到16按鍵的密碼鎖啊
回復(fù)

使用道具 舉報(bào)

8#
ID:895926 發(fā)表于 2021-4-12 23:09 | 只看該作者
你這個(gè)是做了一個(gè)中文字庫嗎?
回復(fù)

使用道具 舉報(bào)

9#
ID:895926 發(fā)表于 2021-4-13 13:35 | 只看該作者
1145483334 發(fā)表于 2019-6-21 17:35
帶中文字庫的12864怎么做出來的

你會(huì)做字庫了嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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