找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6033|回复: 15
收起左侧

关于单片机密码锁*号显示的一个简单问题!

[复制链接]
ID:289777 发表于 2018-5-2 18:00 | 显示全部楼层 |阅读模式
密码锁已经编写号,但有一个功能求助
我想实现这么一个功能,就是输入密码全是 * ,然后如果一直按下仿真中那个按钮A,所有*号显示成相应的数字,这个功能一直没实现,求助应该如何改写程序?


I@7UOT8`)4B9CP4M7PRQN}P.png

项目设计-密码锁.zip (1.36 MB, 下载次数: 28)
回复

使用道具 举报

ID:213173 发表于 2018-5-2 20:23 | 显示全部楼层
可以设一个标志,为0所有字符显示“*”,为1所有字符正常显示,这个标志由按钮A控制。
回复

使用道具 举报

ID:289777 发表于 2018-5-2 21:50 | 显示全部楼层
跪求解答
回复

使用道具 举报

ID:198543 发表于 2018-5-3 09:10 | 显示全部楼层
设定一个显示缓存区,保存输入接收的密码,当检测到按钮A按下时,调用显示缓存区的值,否则显示“*”
回复

使用道具 举报

ID:289777 发表于 2018-5-3 14:04 | 显示全部楼层
wulin 发表于 2018-5-2 20:23
可以设一个标志,为0所有字符显示“*”,为1所有字符正常显示,这个标志由按钮A控制。

具体如何设定呢,能写一下吗?在线等,拜托了
回复

使用道具 举报

ID:289777 发表于 2018-5-3 14:04 | 显示全部楼层
nbhmwj 发表于 2018-5-3 09:10
设定一个显示缓存区,保存输入接收的密码,当检测到按钮A按下时,调用显示缓存区的值,否则显示“*”

具体如何设定呢,能写一下吗?在线等,拜托了
回复

使用道具 举报

ID:213173 发表于 2018-5-3 15:49 | 显示全部楼层
无标题2.jpg 无标题3.jpg
示例代码
#include<reg51.h>
#define led P0
#define LED P2
sbit K1=P2^4;
unsigned int i=0,j=0;
unsigned char k=0,s=0;
bit sign=0;
unsigned char code LedChar[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char code LedArr[]={0,1,2,3,4,5,6,7};
unsigned char LedBuff[9]={0,0,0,0,0,0,0,0,0x40};
void keyscan()                                        //按键扫描程序
{
        static bit key_sign=0;        //按键自锁标志
        static unsigned int count=0;//计数变量                       
        if(!K1)                                        //检测按键如果为0
        {
                count++;                                        //消抖计数
                if((count>=100)&&(key_sign==0))
                {                       
                        key_sign=1;                        //按键自锁标志置1
                        sign=~sign;                        //显示标志取反
                }
        }
        else                                                        //按键抬起
        {
                key_sign=0;                                //按键自锁标志清0
                count=0;                                        //消抖计数清0
        }
}
void main()
{
        TMOD=0x01;
        TH0=0xb1;
        TL0=0xe0;
        TR0=1;
        while(1)
        {
                if(TF0==1)
                {
                        TF0=0;
                        TH0=0xb1;
                        TL0=0xe0;
                        s++;
                }
                if(s>=50)
                {
                        s=0;
                        i++;
                        if(i>9999)
                        {
                                i=0;
                                j++;
                                if(j>9999)
                                        j=0;
                        }
                }
/************数据分解到缓存************/
                LedBuff[0]=LedChar[j/1000];
                LedBuff[1]=LedChar[j%1000/100];
                LedBuff[2]=LedChar[j%100/10];       
                LedBuff[3]=LedChar[j%10];
                LedBuff[4]=LedChar[i/1000];
                LedBuff[5]=LedChar[i%1000/100];
                LedBuff[6]=LedChar[i%100/10];
                LedBuff[7]=LedChar[i%10];

                keyscan();//调用按键程序
/************8位数码管显示************/
                led=0x00;                        //消隐
                LED&=0xF8;                        //清除P2低3位,保留高5位状态不变
                LED|=LedArr[k];        //送位码
                if(sign==1)
                        led=LedBuff[8];        //送段码*
                else
                        led=LedBuff[k];        //送段码
                k++;
                if(k>=8)
                        k=0;
        }
}


回复

使用道具 举报

ID:289777 发表于 2018-5-3 17:36 | 显示全部楼层
感谢上面那位大佬的指点,但是他的历程显示屏和我的这道题显示不大一样啊
请问我的如何改呢,有没有人会,拜托
回复

使用道具 举报

ID:19715 发表于 2018-5-3 18:11 | 显示全部楼层
主程序里面的switch(NUM)不能相应按钮A,只有12个按键有按下才能执行switch(NUM)
回复

使用道具 举报

ID:213173 发表于 2018-5-4 16:38 | 显示全部楼层
本帖最后由 wulin 于 2018-5-6 16:53 编辑
haohaoxue51 发表于 2018-5-3 14:04
具体如何设定呢,能写一下吗?在线等,拜托了

你这程序框架有缺陷,K1功能只能在矩阵键盘功能内有效。目前只能单独写一个按键程序放在主循环中,刷新LCD显示内容。 无标题.jpg



回复

使用道具 举报

ID:289777 发表于 2018-5-6 14:17 | 显示全部楼层
wulin 发表于 2018-5-4 16:38
你这程序框架有缺陷,K1功能只能在矩阵键盘功能内有效。

不行啊,帖子里没有你的截图。你发的这个改正程序我也试了,没效果啊,K1按下后,在按键盘啥都不显示,我的目的是输入完密码,它不是显示*号吗,按下K1后,所有*变为对应的数字
回复

使用道具 举报

ID:213173 发表于 2018-5-6 17:15 | 显示全部楼层
haohaoxue51 发表于 2018-5-6 14:17
不行啊,帖子里没有你的截图。你发的这个改正程序我也试了,没效果啊,K1按下后,在按键盘啥都不显示,我 ...

这是改过的程序
  1. #include <REG52.h>
  2. #include<intrins.h>
  3. sbit K1=P1^2;
  4. sbit ALAM = P2^5;                                                                                                //报警        
  5. sbit open_led=P2^3;                                                                                                //开锁指示灯        
  6. /*LCD接口定义*/
  7. sbit LcdRS   = P2^0;                                                                                      //lcd数据/命令选择端  数据1命令0
  8. sbit LcdRW   = P2^1;                                                                                      //lcd读/写选择端    读1写0
  9. sbit LcdEn   = P2^2;                                                                                      //lcd使能控制端  1有效
  10. sfr  LcdIO   = 0x80;                                                                                      //lcd数据接口 P0=0x80

  11. unsigned char code a[]={0xFE,0xFD,0xFB,0xF7};                                         //控盘扫描控制表
  12.                
  13. unsigned char countt0,second;                                                                        //t0中断计数器,秒计数器
  14. unsigned char code start_line[]        = {"password:       "};
  15. unsigned char code name[]                  = {"===Coded Lock==="};                     //显示名称                 
  16. unsigned char code Error[]           = {"      error     "};                  //输入错误
  17. unsigned char code codepass[]        = {"      pass      "};
  18. unsigned char code LockOpen[]        = {"      open      "};                        //OPEN

  19. char InputData[6];                                                                                                //输入密码暂存区
  20. unsigned char CurrentPassword[6]={6,5,4,3,2,1};                                 //当前密码值
  21. unsigned char N=0;                                                                                                //密码输入位数记数
  22. unsigned char ErrorCont;                                                                                //错误次数计数
  23. unsigned char KEY_SCAN,NUM;

  24. /****向LCD写入命令或数据部分****/
  25. #define LCD_COMMAND         0         // 输出指令
  26. #define LCD_DATA            1         // 输出数据
  27. #define LCD_CLEAR_SCREEN    0x01      // 清屏指令
  28. #define LCD_HOME            0x02      // 光标返回原点指令

  29. //=====================16us短延时==============================
  30. void Delay_short(unsigned int n)
  31. {
  32.          unsigned int i;
  33.          for(i=0;i<n;i++)     
  34.          {;}
  35. }
  36. //=====================长延时==============================
  37. void Delay_long(unsigned char N)
  38. {
  39.         unsigned char i;
  40.           unsigned int j;
  41.            for(i=0;i<N;i++)
  42.            {
  43.                 for(j=0;j<315;j++)  //一个循环16us,共5ms
  44.               {;}
  45.    }
  46. }
  47. //=====================5ms延时==============================
  48. void Delay5Ms(void)
  49. {
  50.         unsigned int TempCyc = 5552;
  51.         while(TempCyc--);
  52. }
  53. //===================400ms延时==============================
  54. void Delay400Ms(void)
  55. {
  56.          unsigned char TempCycA = 5;
  57.          unsigned int TempCycB;
  58.          while(TempCycA--)
  59.          {
  60.                   TempCycB=7269;
  61.                   while(TempCycB--);
  62.          }
  63. }

  64. /*写LCD子程序                                          */
  65. /*入口参数:数据style=1 指令, style=0 input:写入的内容*/

  66. void LCD_Write(bit style, unsigned char input)  
  67. {
  68.     LcdRS=style;         //数据style=1  指令style=0
  69.     LcdRW=0;             //写
  70.     LcdIO=input;         //P0口输出
  71.     Delay_short(10);     //延时
  72.     LcdEn=1;             //lcd使能
  73.     Delay_short(10);     //延时
  74.     LcdEn=0;             //停止
  75. }

  76. /****初始化LCD程序****/
  77. void LCD_Initial()
  78. {
  79.     Delay_long(6);                                     //延迟5*6=30ms
  80.     LCD_Write(LCD_COMMAND,0x38);                       //8位数据端口,2行显示,5*7点阵
  81.     LCD_Write(LCD_COMMAND,0x38);
  82.     LCD_Write(LCD_COMMAND,0x38);                       //发送三遍
  83.     Delay_short(2);                                    //延迟大于39us
  84.     LCD_Write(LCD_COMMAND,0x0c);                            //显示模式设置:开启显示, 无光标 0x0c
  85.     Delay_short(2);                             //延迟大于39us
  86.     LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);           //清屏                          0x01
  87.     Delay_short(100);                           //延迟大于1.53ms
  88.     LCD_Write(LCD_COMMAND,0x06);                               //输入模式设置:AC递增, 画面不动 0x06
  89. }


  90. /*液晶字符输入的位置定位程序*/
  91. /*入口参数:x范围:0-15     y范围:1,2*/
  92. void GotoXY(unsigned char x, unsigned char y)  
  93. {
  94.     unsigned char address;
  95.     if(y==1)
  96.         {
  97.         address=0x80+x;         //y=1显示在第一行
  98.     }
  99.         else
  100.         {
  101.         address=0xc0+x;      //y=2显示在第二行
  102.     }
  103.         LCD_Write(LCD_COMMAND, address);
  104. }

  105. /*将字符串输出到液晶显示函数*/
  106. /*入口参数:字符串指针      */
  107. void Print(unsigned char *str)
  108. {
  109.     while(*str!='\0')
  110.     {
  111.         LCD_Write(LCD_DATA,*str);
  112.         str++;
  113.     }
  114. }
  115. //*********************************************************************
  116. //==============将按键值编码为数值=========================
  117. unsigned char coding(unsigned char m)         
  118. {
  119.         unsigned char k;
  120.         switch(m)
  121.         {
  122. //                case (0x18): k=3;break;
  123. //                case (0x28): k=7;break;
  124. //                case (0x48): k='#';break;
  125. //                case (0x88): k='D';break;
  126.                 case (0x14): k=3;break;
  127.                 case (0x24): k=6;break;
  128.                 case (0x44): k=9;break;
  129.                 case (0x84): k='#';break;
  130.                 case (0x12): k=2;break;
  131.                 case (0x22): k=5;break;
  132.                 case (0x42): k=8;break;
  133.                 case (0x82): k=0;break;
  134.                 case (0x11): k=1;break;
  135.                 case (0x21): k=4;break;
  136.                 case (0x41): k=7;break;
  137.                 case (0x81): k='*';break;
  138.         }
  139.         return(k);
  140. }
  141. //=====================按键检测并返回按键值===============================
  142. unsigned char keynum(void)
  143. {
  144.          unsigned char row,col,i;
  145.          P3=0xf0;
  146.          if((P3&0xf0)!=0xf0)
  147.          {
  148.                    Delay5Ms();
  149.               Delay5Ms();
  150.                    if((P3&0xf0)!=0xf0)
  151.                 {
  152.                     row=P3^0xf0;          //确定行线
  153.                         i=0;
  154.                         P3=a[i];                  //精确定位
  155.                         while(i<4)
  156.                         {
  157.                                  if((P3&0xf0)!=0xf0)
  158.                                   {
  159.                                            col=~(P3&0xff);          //确定列线
  160.                                            break;            //已定位后提前退出   
  161.                                   }
  162.                                 else
  163.                                   {
  164.                                            i++;
  165.                                            P3=a[i];
  166.                                   }
  167.                         }
  168.                 }
  169.                 else
  170.                 {                 
  171.                         return 0xff;        
  172.                 }
  173.                 while((P3&0xf0)!=0xf0);
  174.                 return (row|col);                         //行线与列线组合后返回
  175.          }
  176.          else
  177.         {
  178.                 return 0xff;                                 //无键按下时返回0xff
  179.         }
  180. }
  181. //***************************************************************************************/
  182. //=======================一声提示音,表示有效输入========================
  183. void OneAlam(void)
  184. {
  185.         unsigned char y;
  186.         for(y=0;y<30;y++)
  187.         {
  188.         ALAM=0;
  189.         Delay_short(50);
  190.           ALAM=1;
  191.         Delay_short(50);
  192.         }

  193. }

  194. //========================二声提示音,表示操作成功========================
  195. void TwoAlam(void)
  196. {
  197.         OneAlam();
  198.         Delay5Ms();
  199.     ALAM=1;
  200.           Delay5Ms();
  201.         OneAlam();
  202.         Delay5Ms();
  203.     ALAM=1;
  204. }
  205. //========================三声提示音,表示错误========================
  206. void ThreeAlam(void)
  207. {
  208.         OneAlam();
  209.         Delay5Ms();
  210.     ALAM=1;
  211.         Delay5Ms();
  212.         OneAlam();
  213.         Delay5Ms();
  214.     ALAM=1;
  215.           Delay5Ms();
  216.         OneAlam();
  217.         Delay5Ms();
  218.     ALAM=1;
  219. }
  220. //=======================输入密码错误超过三过,报警并锁死键盘======================
  221. void Alam_KeyUnable(void)
  222. {
  223.         P3=0x00;
  224.         {
  225.                 OneAlam();
  226.                 Delay5Ms();
  227.             ALAM=1;
  228.                 Delay5Ms();
  229.         }
  230. }
  231. //=======================取消所有操作============================================
  232. void Cancel(void)
  233. {        
  234.         unsigned char i;
  235.         GotoXY(0,2);
  236.         Print(start_line);        
  237.         TwoAlam();                                //提示音
  238.         for(i=0;i<6;i++)
  239.         {
  240.                 InputData[i]=0;
  241.         }
  242.         ALAM=1;                                        //报警关
  243.         ErrorCont=0;                        //密码错误输入次数清零
  244.         open_led=1;                                  //指示灯关闭
  245.         N=0;                                        //输入位数计数器清零
  246. }
  247. //==========================确认键,并通过相应标志位执行相应功能===============================
  248. void Ensure(void)
  249. {        
  250.         unsigned char i,j;
  251.         for(i=0;i<6;)
  252.         {                                       
  253.                 if(CurrentPassword[i]==InputData[i])
  254.                 {
  255.                         i++;
  256.                 }
  257.                 else
  258.                 {                        
  259.                         ErrorCont++;
  260.                         if(ErrorCont==3)                        //错误输入计数达三次时,报警并锁定键盘
  261.                         {
  262.                                 GotoXY(0,2);
  263.                                 Print("  KeypadLocked! ");
  264.                                 TR0=1;
  265.                                 do
  266.                                     Alam_KeyUnable();
  267.                                 while(TR0);
  268.                 return ;
  269.                         }
  270.             break;
  271.                 }
  272.         }

  273.         if(i==6)   //密码正确输入
  274.         {
  275.                         GotoXY(0,2);
  276.                         Print(codepass);
  277.                         Delay400Ms();
  278.                         Delay400Ms();
  279.                         GotoXY(0,2);
  280.                         Print(LockOpen);        
  281.                         TwoAlam();                                           //操作成功提示音
  282.                         //KEY_CLOCK=0;                                                                                        //开锁
  283.                         //pass=1;                                                                                        //置正确标志位
  284.                         open_led=0;                                                                                //开锁指示灯亮
  285.                         for(j=0;j<6;j++)                                                                //将输入清除
  286.                         {
  287.                                 InputData[i]=0;
  288.                         }
  289.                         while(1);
  290.         }
  291.         else
  292.         {
  293.         GotoXY(0,2);
  294.                 Print(Error);        
  295.                  ThreeAlam();                                                                                //错误提示音
  296.         Delay400Ms();
  297.         GotoXY(0,2);
  298.                 Print(start_line);
  299.         for(j=0;j<6;j++)                                                                //将输入清除
  300.                 {
  301.                         InputData[i]=0;
  302.                  }
  303.     }
  304.         N=0;                                                                                                        //将输入数据计数器清零,为下一次输入作准备
  305. }

  306. void test_led()
  307. {
  308.         while(1)
  309.         {
  310.                 open_led=0;
  311.                 Delay400Ms();
  312.                 open_led=1;
  313.                 Delay400Ms();
  314.         }
  315. }

  316. void test_alarm()
  317. {
  318.     while(1)
  319.         {
  320.                 ALAM=1;
  321.                 Delay_short(60);
  322.                 ALAM=0;
  323.                 Delay_short(60);
  324.         }
  325. }
  326. void timer_init()
  327. {
  328.         TMOD=0x11;
  329.          TL0=0xB0;
  330.          TH0=0x3C;
  331.          EA=1;
  332.          ET0=1;        
  333.          TR0=0;
  334. }

  335. void test_key()
  336. {
  337.         unsigned char code ascii[]={"0123456789ABCDEF"};
  338.         KEY_SCAN=keynum();
  339.         if(KEY_SCAN!=0xff)
  340.         {
  341.                 GotoXY(0,1);
  342.                 Print("key_code:0x");
  343.                 LCD_Write(LCD_DATA, ascii[KEY_SCAN/16]);
  344.                 LCD_Write(LCD_DATA, ascii[KEY_SCAN%16]);
  345.         }
  346. }
  347. void keyscan()                                        //按键扫描程序
  348. {
  349.         static bit key_sign=0;        //按键自锁标志
  350.         static bit sign=0;
  351.         static unsigned char count=0;//计数变量                        
  352.         unsigned char i;
  353.         if(K1==0)                                        //检测按键如果为0
  354.         {
  355.                 count++;                                        //消抖计数
  356.                 if((count>=250)&&(key_sign==0))
  357.                 {                        
  358.                         key_sign=1;                        //按键自锁标志置1
  359.                         sign=~sign;
  360.                         if(sign==1)
  361.                         {
  362.                                 for(i=0;i<N;i++)
  363.                                 {
  364.                                         GotoXY(9+i,2);
  365.                                         LCD_Write(LCD_DATA,InputData[i]+0x30);
  366.                                 }
  367.                         }
  368.                         else
  369.                         {
  370.                                 for(i=0;i<N;i++)
  371.                                 {
  372.                                         GotoXY(9+i,2);
  373.                                         LCD_Write(LCD_DATA,'*');
  374.                                 }
  375.                         }
  376.                 }
  377.         }
  378.         else                                                        //按键抬起
  379.         {
  380.                 key_sign=0;                                //按键自锁标志清0
  381.                 count=0;                                        //消抖计数清0
  382.         }
  383. }

  384. //==============================主函数===============================
  385. void main(void)
  386. {
  387.          
  388.         unsigned char j;
  389. //        test_led();
  390. //        test_alarm();
  391.          Delay400Ms();         //启动等待,等LCM讲入工作状态
  392.          LCD_Initial();         //LCD初始化

  393. //        while(1)
  394. //        {
  395. //                test_key();
  396. //        }

  397.         GotoXY(0,1);//日历显示固定符号从第一行第0个位置之后开始显示
  398.         Print(name);//向液晶屏写日历显示的固定符号部分
  399.         GotoXY(0,2);//时间显示固定符号写入位置,从第2个位置后开始显示
  400.         Print(start_line);//写显示时间固定符号,两个冒号
  401.         GotoXY(9,2);        //设置光标位置
  402.         LCD_Write(LCD_COMMAND,0x0f);        //设置光标为闪烁

  403. //        while(1);

  404.          P3=0xFF;
  405.         timer_init();



  406.          Delay5Ms(); //延时片刻(可不要)
  407.         N=0;                                                                                                                //初始化数据输入位数
  408.          while(1)
  409.          {
  410.         if (!TR0)
  411.                 {
  412.                     KEY_SCAN=keynum();
  413.                 }
  414.         else
  415.                 {
  416.             KEY_SCAN = 0xff;
  417.         }

  418.                 if(KEY_SCAN!=0xff)
  419.                 {                                   
  420.                                         NUM=coding(KEY_SCAN);
  421.                                         switch(NUM)
  422.                                         {
  423.                                                 case 'A':         ;                                         break;
  424.                                                 case 'B':        ;                                     break;
  425.                                                 case 'C':         ;                                         break;
  426.                                                 case 'D':         ;                                        break;   
  427.                                                 case '*': Cancel();                                break;      //取消当前输入
  428.                                                 case '#': Ensure();                         break;           //确认键,
  429.                                                 default:
  430.                                                 {        
  431.                                                         if(N<6)                                                           //当输入的密码少于6位时,接受输入并保存,大于6位时则无效。
  432.                                                         {
  433. //                                                                  unsigned        char temp;
  434.                                                                 OneAlam();                                                                //按键提示音                                                
  435.                                                                 for(j=N;j<=N;j++)
  436.                                                                 {
  437.                                                                         GotoXY(9+j,2);
  438.                                                                         LCD_Write(LCD_DATA,'*');
  439.                                                                 }
  440. /*                                                           if(K1==0)
  441.                                                            {
  442.                                                                         GotoXY(9+N,2);
  443.                                                                         temp=NUM+0x30           ;
  444.                                                                         LCD_Write(LCD_DATA,temp);
  445.                                                                                                   
  446.                                                                 }*/
  447.                                                                 InputData[N]=NUM;
  448.                                                                 N++;
  449.                                                         }
  450.                                                         else                                                                                //输入数据位数大于6后,忽略输入
  451.                                                         {
  452.                                                                 N=6;
  453.                                                                  
  454.                                                         }
  455.                             break;
  456.                                                 }
  457.                                         }
  458.                         }
  459.                 keyscan();
  460.         }
  461. }

  462. //*********************************中断服务函数**************************************
  463. void  time0_int(void) interrupt 1
  464. {
  465.          TL0=0xB0;
  466.          TH0=0x3C;
  467.          countt0++;
  468.           if(countt0==20)
  469.            {
  470.                 countt0=0;
  471.                 second++;
  472.                 if(second==10)
  473.                 {
  474.                                 P3=0xf0;
  475.                                 TL0=0xB0;
  476.                                  TH0=0x3C;
  477.                                 second=0;
  478.                                 ErrorCont=0;                        //密码错误输入次数清零
  479.         GotoXY(0,2);
  480.                                 Print(start_line);
  481.         TR0=0;                                //关定时器
  482.                 }
  483.                         
  484.            }
  485. }
复制代码

回复

使用道具 举报

ID:289777 发表于 2018-5-14 22:18 | 显示全部楼层
wulin 发表于 2018-5-6 17:15
这是改过的程序

十分感谢
回复

使用道具 举报

ID:329641 发表于 2018-5-14 22:41 | 显示全部楼层
是不是定时器没设定好?
回复

使用道具 举报

ID:324844 发表于 2020-5-3 22:49 | 显示全部楼层
我有一个问题,那个延时函数是怎么回事儿啊,如果认为125是1ms,短延时只有8us,长延时是2.5ms,他的5ms延时有44ms,他的400ms延时是290ms,看不懂求问
回复

使用道具 举报

ID:420836 发表于 2020-5-4 00:41 | 显示全部楼层
谢谢您的帮助! 我学到很多
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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