• 单片机C语言实例:32、实用密码锁


    程序实例1:延时函数

    1. #ifndef __DELAY_H__
    2. #define __DELAY_H__
    3. /*------------------------------------------------
    4. uS延时函数,含有输入参数 unsigned char t,无返回值
    5. unsigned char 是定义无符号字符变量,其值的范围是
    6. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    7. 长度如下 T=tx2+5 uS
    8. ------------------------------------------------*/
    9. void DelayUs2x(unsigned char t);
    10. /*------------------------------------------------
    11. mS延时函数,含有输入参数 unsigned char t,无返回值
    12. unsigned char 是定义无符号字符变量,其值的范围是
    13. 0~255 这里使用晶振12M,精确延时请使用汇编
    14. ------------------------------------------------*/
    15. void DelayMs(unsigned char t);
    16. #endif

    1. #include "delay.h"
    2. /*------------------------------------------------
    3. uS延时函数,含有输入参数 unsigned char t,无返回值
    4. unsigned char 是定义无符号字符变量,其值的范围是
    5. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    6. 长度如下 T=tx2+5 uS
    7. ------------------------------------------------*/
    8. void DelayUs2x(unsigned char t)
    9. {
    10. while(--t);
    11. }
    12. /*------------------------------------------------
    13. mS延时函数,含有输入参数 unsigned char t,无返回值
    14. unsigned char 是定义无符号字符变量,其值的范围是
    15. 0~255 这里使用晶振12M,精确延时请使用汇编
    16. ------------------------------------------------*/
    17. void DelayMs(unsigned char t)
    18. {
    19. while(t--)
    20. {
    21. //大致延时1mS
    22. DelayUs2x(245);
    23. DelayUs2x(245);
    24. }
    25. }

    程序实例2:1602驱动

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. #ifndef __1602_H__
    4. #define __1602_H__
    5. bit LCD_Check_Busy(void) ;
    6. void LCD_Write_Com(unsigned char com) ;
    7. void LCD_Write_Data(unsigned char Data) ;
    8. void LCD_Clear(void) ;
    9. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;
    10. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) ;
    11. void LCD_Init(void) ;
    12. #endif
    1. #include "1602.h"
    2. #include "delay.h"
    3. #define CHECK_BUSY
    4. sbit RS = P2^4; //定义端口
    5. sbit RW = P2^5;
    6. sbit EN = P2^6;
    7. #define RS_CLR RS=0
    8. #define RS_SET RS=1
    9. #define RW_CLR RW=0
    10. #define RW_SET RW=1
    11. #define EN_CLR EN=0
    12. #define EN_SET EN=1
    13. #define DataPort P0
    14. /*------------------------------------------------
    15. 判忙函数
    16. ------------------------------------------------*/
    17. bit LCD_Check_Busy(void)
    18. {
    19. #ifdef CHECK_BUSY
    20. DataPort= 0xFF;
    21. RS_CLR;
    22. RW_SET;
    23. EN_CLR;
    24. _nop_();
    25. EN_SET;
    26. return (bit)(DataPort & 0x80);
    27. #else
    28. return 0;
    29. #endif
    30. }
    31. /*------------------------------------------------
    32. 写入命令函数
    33. ------------------------------------------------*/
    34. void LCD_Write_Com(unsigned char com)
    35. {
    36. while(LCD_Check_Busy()); //忙则等待
    37. RS_CLR;
    38. RW_CLR;
    39. EN_SET;
    40. DataPort= com;
    41. _nop_();
    42. EN_CLR;
    43. }
    44. /*------------------------------------------------
    45. 写入数据函数
    46. ------------------------------------------------*/
    47. void LCD_Write_Data(unsigned char Data)
    48. {
    49. while(LCD_Check_Busy()); //忙则等待
    50. RS_SET;
    51. RW_CLR;
    52. EN_SET;
    53. DataPort= Data;
    54. _nop_();
    55. EN_CLR;
    56. }
    57. /*------------------------------------------------
    58. 清屏函数
    59. ------------------------------------------------*/
    60. void LCD_Clear(void)
    61. {
    62. LCD_Write_Com(0x01);
    63. DelayMs(5);
    64. }
    65. /*------------------------------------------------
    66. 写入字符串函数
    67. ------------------------------------------------*/
    68. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    69. {
    70. while (*s)
    71. {
    72. LCD_Write_Char(x,y,*s);
    73. s ++; x++;
    74. }
    75. }
    76. /*------------------------------------------------
    77. 写入字符函数
    78. ------------------------------------------------*/
    79. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    80. {
    81. if (y == 0)
    82. {
    83. LCD_Write_Com(0x80 + x);
    84. }
    85. else
    86. {
    87. LCD_Write_Com(0xC0 + x);
    88. }
    89. LCD_Write_Data( Data);
    90. }
    91. /*------------------------------------------------
    92. 初始化函数
    93. ------------------------------------------------*/
    94. void LCD_Init(void)
    95. {
    96. LCD_Write_Com(0x38); /*显示模式设置*/
    97. DelayMs(5);
    98. LCD_Write_Com(0x38);
    99. DelayMs(5);
    100. LCD_Write_Com(0x38);
    101. DelayMs(5);
    102. LCD_Write_Com(0x38);
    103. LCD_Write_Com(0x08); /*显示关闭*/
    104. LCD_Write_Com(0x01); /*显示清屏*/
    105. LCD_Write_Com(0x06); /*显示光标移动设置*/
    106. DelayMs(5);
    107. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    108. }

    程序实例3:按键驱动

    1. #ifndef __KEYBOARD_H__
    2. #define __KEYBOARD_H__
    3. /*------------------------------------------------
    4. 按键扫描函数,返回扫描键值
    5. ------------------------------------------------*/
    6. unsigned char KeyScan(void); //键盘扫描函数,使用行列反转扫描法
    7. /*------------------------------------------------
    8. 按键值处理函数,返回扫键值
    9. ------------------------------------------------*/
    10. unsigned char KeyPro(void);
    11. #endif
    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include"keyboard.h"
    3. #include"delay.h"
    4. #define KeyPort P3
    5. /*------------------------------------------------
    6. 按键扫描函数,返回扫描键值
    7. ------------------------------------------------*/
    8. unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法
    9. {
    10. unsigned char cord_h,cord_l;//行列值中间变量
    11. KeyPort=0x0f; //行线输出全为0
    12. cord_h=KeyPort&0x0f; //读入列线值
    13. if(cord_h!=0x0f) //先检测有无按键按下
    14. {
    15. DelayMs(10); //去抖
    16. if((KeyPort&0x0f)!=0x0f)
    17. {
    18. cord_h=KeyPort&0x0f; //读入列线值
    19. KeyPort=cord_h|0xf0; //输出当前列线值
    20. cord_l=KeyPort&0xf0; //读入行线值
    21. while((KeyPort&0xf0)!=0xf0);//等待松开并输出
    22. return(cord_h+cord_l);//键盘最后组合码值
    23. }
    24. }
    25. return(0xff); //返回该值
    26. }
    27. /*------------------------------------------------
    28. 按键值处理函数,返回扫键值
    29. ------------------------------------------------*/
    30. unsigned char KeyPro(void)
    31. {
    32. switch(KeyScan())
    33. {
    34. case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
    35. case 0x7d:return 1;break;//1
    36. case 0x7b:return 2;break;//2
    37. case 0x77:return 3;break;//3
    38. case 0xbe:return 4;break;//4
    39. case 0xbd:return 5;break;//5
    40. case 0xbb:return 6;break;//6
    41. case 0xb7:return 7;break;//7
    42. case 0xde:return 8;break;//8
    43. case 0xdd:return 9;break;//9
    44. case 0xdb:return 10;break;//a
    45. case 0xd7:return 11;break;//b
    46. case 0xee:return 12;break;//c
    47. case 0xed:return 13;break;//d
    48. case 0xeb:return 14;break;//e
    49. case 0xe7:return 15;break;//f
    50. default:return 0xff;break;
    51. }
    52. }

    程序实例4:main文件

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. #include"1602.h"
    4. #include"delay.h"
    5. #include"keyboard.h"
    6. unsigned char code password[]={1,2,3,4,5,6,7,8};//可以更改此密码做多组测试
    7. //定义密码,实际上密码需要存在eeprom中,可以通过程序更改。请用户自行添加
    8. /*------------------------------------------------
    9. 主程序
    10. ------------------------------------------------*/
    11. main()
    12. {
    13. unsigned char num,i,j;
    14. unsigned char passwordtemp[16]; //最大输入16个
    15. unsigned char inputtimes; //密码输入错误次数
    16. unsigned char passwordlength,PLEN; //输入密码长度,实际密码长度
    17. bit Flag;
    18. PLEN=sizeof(password)/sizeof(password[0]);//用于计算出实际密码长度
    19. LCD_Init(); //初始化液晶屏
    20. DelayMs(10); //延时用于稳定,可以去掉
    21. LCD_Clear(); //清屏
    22. LCD_Write_String(0,0," Welcome! "); //写入第一行信息,主循环中不再更改此信息,所以在while之前写入
    23. LCD_Write_String(0,1,"Input password!"); //写入第二行信息,提示输入密码
    24. while (1) //主循环
    25. {
    26. num=KeyPro(); //扫描键盘
    27. if(num!=0xff) //如果扫描是按键有效值则进行处理
    28. {
    29. if(i==0) //输入是第一个字符的时候需要把改行清空,方便观看密码
    30. LCD_Write_String(0,1," ");//清除该行
    31. if(i<16)
    32. {
    33. passwordtemp[i]=num;
    34. LCD_Write_Char(i,1,'*');//输入的密码用"*"代替
    35. }
    36. i++; //输入数值累加
    37. if((15==num)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对
    38. {
    39. passwordlength=i-1; //计算输入密码长度
    40. i=0; //计数器复位
    41. if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误
    42. {
    43. Flag=1;//先把比较位置1
    44. for(j=0;j//循环比较8个数值,如果有一个不等 则最终Flag值为0
    45. Flag=Flag&&(passwordtemp[j]==password[j]);//比较输入值和已有密码
    46. }
    47. if(Flag)//如果比较全部相同,标志位置1
    48. {
    49. LCD_Write_String(0,1," ");//清除该行
    50. LCD_Write_String(0,1,"Right Open!>>>>");//密码正确显示的信息
    51. inputtimes=0;//输入正确则次数清零,重新计数
    52. Flag=0; //清除正确标志
    53. }
    54. else
    55. {
    56. LCD_Write_String(0,1," ");//清除该行
    57. LCD_Write_String(0,1,"Wrong! Retry!");//密码错误,提示重新输入
    58. inputtimes++;//连续输入错误,则次数累加
    59. if(inputtimes==3)
    60. {
    61. LCD_Write_String(0,1," ");//清除该行
    62. LCD_Write_String(0,1,"Wrong 3 times!");//密码错误,提示重新输入
    63. while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
    64. }
    65. }
    66. }
    67. }
    68. }
    69. }

  • 相关阅读:
    python二级备考(2)-简单应用题
    STL的set和map的基本使用
    ViewOptional:一个安全便利的查找View的工具
    拼多多详情API接口深度解读
    基于深度学习LSTM+NLP情感分析电影数据爬虫可视化分析推荐系统(深度学习LSTM+机器学习双推荐算法+scrapy爬虫+NLP情感分析+数据分析可视化)
    Java框架学习顺序,主要讲解三大框架
    jenkins pipeline使用
    推荐算法——Apriori算法原理
    C++基础知识记录
    【驱动开发】创建设备节点、ioctl函数的使用
  • 原文地址:https://blog.csdn.net/m0_49968063/article/details/132916721