找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机密码锁程序 存储在I2C 密码掉电不丢失

[复制链接]
跳转到指定楼层
楼主
设计内容:
1、密码存储在I2C器件中,实现密码掉电不丢失。
2、电路板一上电四个数码管显示“-“
3、实现数字键0-9和功能键的设计:
4、四个功能键:
(1)密码输入
(2)退出
(3)密码修改:当密码密码修改键按下,若输入密码正确后,按下此键时,将修改的密码进行存储。输入密码正确显示”8888“
输入失败显示”HHHH“

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

单片机源程序如下:
  1. #include <reg51.h>
  2. #include <intrins.h>
  3. #include <string.h>

  4. typedef unsigned char u8;
  5. typedef unsigned int u16;

  6. #define SMG_PORT P0
  7. #define KEY_MATRIX_PORT  P1
  8. #define AT24C02_ADDRESS  0xA0

  9. u8 gsmg_code[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,0x40,0x76};//0-9 "-" "H"
  10. u8 e_mima[4] = {1, 2, 3, 4}; // 初始密码是1234
  11. u8 read_mima[4];
  12. u8 entered_password[4];  // 存储用户输入的密码
  13. u8 input_index = 0;
  14. u8 key = 0;
  15. u8 wei=0;
  16. u8 panduan=0;//判断密码是否正确
  17. u8 state=0;
  18. u8 xiugai=0;
  19. u8 wdata=0;
  20. u8 show_h=0;

  21. sbit led=P2^7;
  22. sbit LSA = P2^2;
  23. sbit LSB = P2^3;
  24. sbit LSC = P2^4;

  25. sbit sda=P2^0;  
  26. sbit scl=P2^1;

  27. u8 chushi = 1;

  28. //@11.0592MHz
  29. void Delay10ms()
  30. {
  31.     unsigned char i, j;
  32.     i = 108;
  33.     j = 145;
  34.     do
  35.     {
  36.         while (--j);
  37.     } while (--i);
  38. }

  39. //@11.0592MHz
  40. void delay_us(unsigned int us)
  41. {
  42.     unsigned int i;
  43.     while(us--)
  44.     {
  45.         i = 11;  // 11 是根据 11.0592MHz 晶振频率调整的数值
  46.         while (--i);
  47.     }
  48. }

  49. void delayms(u16 x)
  50. {
  51. u8 i;
  52. while(x--)
  53. {
  54.   for(i=150;i>0;i--);
  55. }
  56. }


  57. void nop()
  58. {
  59.         _nop_();
  60.         _nop_();
  61. }
  62. /////////24C02读写驱动程序////////////////////
  63. void delay1(unsigned int m)
  64. {        unsigned int n;
  65.           for(n=0;n<m;n++);
  66. }

  67. void init()  //24c02初始化子程序
  68. {
  69.         scl=1;
  70.         nop();
  71.         sda=1;
  72.         nop();
  73. }

  74. void start()        //启动I2C总线
  75. {
  76.         sda=1;
  77.         nop();
  78.         scl=1;
  79.         nop();
  80.         sda=0;
  81.         nop();
  82.         scl=0;
  83.         nop();
  84. }

  85. void stop()         //停止I2C总线
  86. {
  87.         sda=0;
  88.         nop();
  89.         scl=1;
  90.         nop();
  91.         sda=1;
  92.         nop();
  93. }

  94. void writebyte(unsigned char j)  //写一个字节
  95. {
  96.         unsigned char i,temp;
  97.            temp=j;
  98.            for (i=0;i<8;i++)
  99.    {
  100.            temp=temp<<1;
  101.            scl=0;
  102.            nop();
  103.            sda=CY;                //temp左移时,移出的值放入了CY中
  104.            nop();
  105.            scl=1;                //待sda线上的数据稳定后,将scl拉高
  106.            nop();
  107.    }
  108.    scl=0;
  109.    nop();
  110.    sda=1;
  111.    nop();
  112. }

  113. unsigned char readbyte()   //读一个字节
  114. {
  115.    unsigned char i,j,k=0;
  116.    scl=0; nop(); sda=1;
  117.    for (i=0;i<8;i++)
  118.    {  
  119.                 nop(); scl=1; nop();
  120.               if(sda==1)
  121.                 j=1;
  122.               else
  123.                 j=0;
  124.               k=(k<<1)|j;
  125.                   scl=0;
  126.         }
  127.            nop();
  128.         return(k);
  129. }

  130. void clock()         //I2C总线时钟
  131. {
  132.    unsigned char i=0;
  133.    scl=1;
  134.    nop();
  135.    while((sda==1)&&(i<255))
  136.              i++;
  137.    scl=0;
  138.    nop();
  139. }

  140. ////////从24c02的地址address中读取一个字节数据/////
  141. unsigned char read24c02(unsigned char address)
  142. {
  143.    unsigned char i;
  144.    start();
  145.    writebyte(0xa0);
  146.    clock();
  147.    writebyte(address);
  148.    clock();
  149.    start();
  150.    writebyte(0xa1);
  151.    clock();
  152.    i=readbyte();
  153.    stop();
  154.    delay1(10);
  155.    return(i);
  156. }

  157. //////向24c02的address地址中写入一字节数据info/////
  158. void write24c02(unsigned char address,unsigned char info)
  159. {
  160.    start();
  161.    writebyte(0xa0);
  162.    clock();
  163.    writebyte(address);
  164.    clock();
  165.    writebyte(info);
  166.    clock();
  167.    stop();
  168.    delay1(50);
  169. }

  170. u8 key_matrix_ranks_scan(void)
  171. {
  172.     u8 key_value = 0;
  173.     KEY_MATRIX_PORT = 0xf7; //第一列为低电平
  174.     if (KEY_MATRIX_PORT!= 0xf7) //有按键按下
  175.     {
  176.         Delay10ms();
  177.         switch(KEY_MATRIX_PORT)
  178.         {
  179.             case 0x77: key_value = 1; break; //S1按下时
  180.             case 0xb7: key_value = 4; break;
  181.             case 0xd7: key_value = 7; break;
  182.             case 0xe7: key_value = 10; break;
  183.         }
  184.     }
  185.     while(KEY_MATRIX_PORT!= 0xf7); //等待释放,当按键按下时KEY值不等于0xf7,一直循环,当按键释放时,KEY等于0xf7,跳出循环

  186.     KEY_MATRIX_PORT = 0xfb; //第二列为低电平
  187.     if (KEY_MATRIX_PORT!= 0xfb) //有按键按下
  188.     {
  189.         Delay10ms();
  190.         switch(KEY_MATRIX_PORT)
  191.         {
  192.             case 0x7b: key_value = 2; break;
  193.             case 0xbb: key_value = 5; break;
  194.             case 0xdb: key_value = 8; break;
  195.             case 0xeb:/* key_value = 11;*/ break;
  196.         }
  197.     }
  198.     while(KEY_MATRIX_PORT!= 0xfb);

  199.     KEY_MATRIX_PORT = 0xfd; //第三列为低电平
  200.     if (KEY_MATRIX_PORT!= 0xfd) //有按键按下
  201.     {
  202.         Delay10ms();
  203.         switch(KEY_MATRIX_PORT)
  204.         {
  205.             case 0x7d: key_value = 3; break;
  206.             case 0xbd: key_value = 6; break;
  207.             case 0xdd: key_value = 9; break;
  208.             case 0xed:/* key_value = 12; */break;
  209.         }
  210.     }
  211.     while(KEY_MATRIX_PORT!= 0xfd);

  212.     KEY_MATRIX_PORT = 0xfe; //第四列为低电平
  213.     if (KEY_MATRIX_PORT!= 0xfe)
  214.     {
  215.         Delay10ms();
  216.         switch(KEY_MATRIX_PORT)
  217.         {
  218.             case 0x7e: key_value = 13; break; //S1按键按下时
  219.             case 0xbe: key_value = 14; break;
  220.             case 0xde: key_value = 15; break;
  221.             case 0xee: key_value = 16; break;
  222.         }
  223.     }
  224.     while(KEY_MATRIX_PORT!= 0xfe);

  225.     return key_value;
  226. }

  227. // 显示单个数字到指定的数码管位
  228. void display_on_smg(u8 num, u8 pos)
  229. {
  230.     switch (pos)
  231.     {
  232.         case 1: LSC = 1; LSB = 1; LSA = 1; break; // 第1位
  233.         case 2: LSC = 1; LSB = 1; LSA = 0; break; // 第2位
  234.         case 3: LSC = 1; LSB = 0; LSA = 1; break; // 第3位
  235.         case 4: LSC = 1; LSB = 0; LSA = 0; break; // 第4位
  236.     }
  237.     SMG_PORT = 0x00;
  238.     SMG_PORT = gsmg_code[num];
  239.                 delay_us(5);
  240.                 SMG_PORT = 0x00;
  241. }


  242. void clear_display(void)
  243. {
  244.     LSC = 1; LSB = 0; LSA = 0;
  245.     SMG_PORT = 0x00; // 清空显示
  246. }

  247. void show_8888(void)
  248. {
  249.   display_on_smg(8,1);
  250.         display_on_smg(8,2);
  251.         display_on_smg(8,3);
  252.         display_on_smg(8,4);
  253. }

  254. void show_HHHH(void)
  255. {
  256.   display_on_smg(11,1);
  257.         display_on_smg(11,2);
  258.         display_on_smg(11,3);
  259.         display_on_smg(11,4);
  260. }

  261. void show____(void)
  262. {
  263.         display_on_smg(10,1);
  264.         display_on_smg(10,2);
  265.         display_on_smg(10,3);
  266.         display_on_smg(10,4);
  267. }

  268. //输入密码
  269. void import_ss()
  270. {
  271.         u8 i;
  272.         for (i = 0; i < 4; i++)
  273.         {
  274.                         e_mima[i] = read_mima[i];
  275.         }
  276.   if (key!= 0 && key!=13 && key!=14 && key!=15 && key!=16)
  277.         {
  278.                 wei++;
  279.                 entered_password[input_index] = key-1;
  280.                 input_index++;
  281.                 if (input_index >= 4)
  282.                 {
  283.                         input_index = 0;
  284.                 }
  285.         }
  286.         if(wei==1)
  287.         {
  288.           display_on_smg(10, 1);
  289.   }
  290.         else if(wei==2)
  291.         {
  292.           display_on_smg(10, 1);
  293.                 display_on_smg(10, 2);
  294.         }
  295.         else if(wei==3)
  296.         {
  297.           display_on_smg(10, 1);
  298.                 display_on_smg(10, 2);
  299.                 display_on_smg(10, 3);
  300.         }
  301.         else if(wei==4)
  302.         {
  303.                 display_on_smg(10, 1);
  304.                 display_on_smg(10, 2);
  305.                 display_on_smg(10, 3);
  306.                 display_on_smg(10, 4);
  307.                 panduan=1;
  308.                 wei=0;
  309.         }
  310.         if(panduan==1)
  311.         {
  312.                 if(panduan==1)
  313.                 {
  314.                         // 比较密码
  315.                         if (entered_password[0] == e_mima[0] && entered_password[1] == e_mima[1] && entered_password[2] == e_mima[2] && entered_password[3] == e_mima[3])
  316.                         {
  317.                                 show_8888();
  318.                                 led=0;
  319.                         }
  320.                         else
  321.                         {
  322.                                 show_HHHH();
  323.                                 led=1;
  324.                         }
  325.                 }
  326.         }
  327. }
  328. // 密码修改
  329. void xiugai_ss(void)
  330. {
  331.         u8 i,j;
  332.         
  333.         for (i = 0; i < 4; i++)
  334.         {
  335.                         e_mima[i] = read_mima[i];
  336.         }
  337.     if (key!= 0 && key!= 13 && key!= 14 && key!= 15 && key!= 16)
  338.     {
  339.         entered_password[input_index] = key - 1;
  340.         input_index++;
  341.         if (input_index >= 4)
  342.         {
  343.             if (state == 0)
  344.             {
  345.                 // 输入原密码阶段
  346.                 if (entered_password[0] == e_mima[0] && entered_password[1] == e_mima[1] && entered_password[2] == e_mima[2] && entered_password[3] == e_mima[3])
  347.                 {
  348.                     state = 1; // 原密码正确,进入输入新密码状态
  349.                     input_index = 0;
  350.                     clear_display();
  351.                                                                           led=0;
  352.                                                                         show_h=0;
  353.                 }
  354.                 else
  355.                 {
  356.                     show_h=1;
  357.                     state = 0;
  358.                     input_index = 0;
  359.                 }
  360.             }
  361.             else if (state == 1)
  362.             {
  363.                 // 输入新密码阶段
  364.                 if (input_index == 4 )
  365.                 {
  366.                                                                           // 输入新密码阶段
  367.                 if (input_index == 4)
  368.                 {
  369.                     state = 2; // 输入新密码完成,进入确认状态
  370.                     input_index = 0;
  371.                 }
  372.                 }
  373.             }
  374.         }
  375.     }
  376.     // 显示已输入的密码
  377.     for (j = 0; j < input_index; j++)
  378.     {
  379.         display_on_smg(10, j + 1);
  380.     }
  381.                 if (state == 2 && key == 16)
  382.     {
  383.                         led=1;
  384.         // 确认修改密码
  385.         for (i = 0; i < 4; i++)
  386.         {
  387.            e_mima[i] = entered_password[i];
  388.                                  }
  389.                                 wdata=1;
  390.                                 show_8888();
  391.         state = 0;
  392.         input_index = 0;
  393.         chushi = 1;
  394.         xiugai = 0;
  395.         show____(); // 修改完成后返回初始界面显示
  396.     }
  397. }


  398. void main()
  399. {
  400.         u8 i;
  401.         led=1;
  402.         init();        //初始化24C02
  403.         // 上电从 24C02 读取数据
  404.         for (i = 0; i < 4; i++)
  405.         {
  406.                 read_mima[i] = read24c02(i);
  407.                 delayms(3);
  408.         }
  409.     while(1)
  410.     {
  411.                         // 上电从 24C02 读取数据
  412.                         for (i = 0; i < 4; i++)
  413.                         {
  414.                                 read_mima[i] = read24c02(i);
  415.                                 delayms(3);
  416.                         }
  417.                         if(wdata==1)
  418.                         {
  419.                           write24c02(0, entered_password[0]); // 将修改后的密码发送给 24C02
  420.                                 delayms(3);
  421.         write24c02(1, entered_password[1]);
  422.                                 delayms(3);
  423.                                 write24c02(2, entered_password[2]);
  424.                                 delayms(3);
  425.                                 write24c02(3, entered_password[3]);
  426.                                 delayms(3);
  427.                                 wdata=0;
  428.                         }
  429.                         if(show_h==1)
  430.                         {
  431.                           show_HHHH();
  432.                         }
  433.                         
  434.         key = key_matrix_ranks_scan();
  435.         if (key == 13)//输入键
  436.         {
  437.                                         chushi = 0;
  438.                                         panduan=0;
  439.                                         clear_display();
  440.         }
  441.                                 if(key==14)//退出键
  442.                                 {
  443.                                   chushi=1;
  444.                                 }
  445.                                 if(key==15)//密码修改
  446.                                 {
  447.                                         show_h=0;
  448.                                         chushi=2;
  449.                                         panduan=0;
  450.                                   clear_display();
  451.                                 }
  452.                                 if(key==16)
  453.                                 {
  454.                                         xiugai=1;
  455.                                 }
  456.                                 
  457.                                 if(chushi==1)
  458.                                 {
  459.                                         show____();
  460.                                         led=1;
  461.                                 }
  462.         else if (chushi == 0)
  463.         {
  464.            import_ss();
  465.         }
  466.                                 else if(chushi==2)
  467.                                 {
  468.                                   xiugai_ss();
  469.                                 }
  470.     }
  471. }
复制代码

仿真程序.7z (222.12 KB, 下载次数: 0)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:433219 发表于 2025-1-22 09:10 | 只看该作者
mcu 有 IAP功能,当eeprom 可省略iic的24c
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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