找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STM32密码锁设计 功能很全 带源码

  [复制链接]
跳转到指定楼层
楼主
**功能:支持3~20位的密码设置,初始密码为123456;若要重设密码,需先输入正确密码开锁。
** 正常显示情况下,按下确认键上锁;按下密码键,开始输入密码。
**接线:PE[0..3]----4*4键盘的行线,均用中断方式,上拉输入,下降沿触发
** PE[4..7]----4*4键盘的列线,下拉输入,在中断内临时改为上拉输入,用于读键值
** PD[0..7]----LCD12864 D0~D7
** PD[13..15]--LCD12864 RS,RW,E
** PA.1 连接继电器,低电平时合上,高电平时断开相当于开锁与上锁

完整代码下载:
电子密码锁设计.rar (1.5 MB, 下载次数: 666)



单片机源码:
  1. /*****************************************************************************
  2. **                          电子密码锁设计
  3. **文件名称:main.c
  4. **by 追梦 2011-5-12
  5. **功能:支持3~20位的密码设置,初始密码为123456;若要重设密码,需先输入正确密码开锁。
  6. **      正常显示情况下,按下确认键上锁;按下密码键,开始输入密码。
  7. **接线:PE[0..3]----4*4键盘的行线,均用中断方式,上拉输入,下降沿触发
  8. **      PE[4..7]----4*4键盘的列线,下拉输入,在中断内临时改为上拉输入,用于读键值
  9. **      PD[0..7]----LCD12864  D0~D7
  10. **      PD[13..15]--LCD12864  RS,RW,E
  11. **      PA.1 连接继电器,低电平时合上,高电平时断开相当于开锁与上锁
  12. *****************************************************************************/

  13. #include "stm32f10x.h"
  14. #include "LCD12864.h"

  15. extern __IO uint16_t keyval;
  16. extern __IO uint16_t keyflag;

  17. uint16_t password[21]={1,2,3,4,5,6,'

  18. [/color]};  //初始密码为 123456
  19. uint16_t passwordtmp[21];

  20. #define OPEN_DOOR  GPIOA->BRR  = GPIO_Pin_1
  21. #define CLOSE_DOOR GPIOA->BSRR = GPIO_Pin_1

  22. //数组中存放各个备份数据寄存器基于BKP基地址的偏移地址,用于存储密码
  23. uint16_t BKPDataReg[21] =
  24.   {
  25.     BKP_DR2,  BKP_DR3,  BKP_DR4,  BKP_DR5,  BKP_DR6,  BKP_DR7, BKP_DR8, BKP_DR9,
  26.         BKP_DR10, BKP_DR11, BKP_DR12, BKP_DR13, BKP_DR14, BKP_DR15,BKP_DR16,BKP_DR17,
  27.         BKP_DR18, BKP_DR19, BKP_DR20, BKP_DR21, BKP_DR22
  28.   };
  29. /**
  30.   * 写密码到备份寄存器,掉电不丢失,电源复位不丢失
  31.   */
  32. void WritePasswordToBackupReg(uint16_t passwordarray[])
  33. {
  34.   uint32_t index = 0;
  35.   /* 使能写入BKP */
  36.   PWR_BackupAccessCmd(ENABLE);
  37.   /* 清除事件挂起位 pin Event(TE) */
  38.   BKP_ClearFlag();
  39.   for (index = 0; passwordarray[index]!='

  40. [/color]; index++)
  41.   {                                                         //偏移地址  和   数据
  42.     BKP_WriteBackupRegister(BKPDataReg[index], passwordarray[index]);
  43.   }
  44.   BKP_WriteBackupRegister(BKPDataReg[index], passwordarray[index]); //写入密码结尾符  
  45. }
  46. /**
  47.   * 上电或复位后读出备份区里保存的密码
  48.   */
  49. void Load_Password(void)
  50. {
  51.     uint32_t index = 0;
  52.    for(index = 0; BKP_ReadBackupRegister(BKPDataReg[index])!='

  53. [/color]; index++)
  54.    {                                                       
  55.       password[index]=BKP_ReadBackupRegister(BKPDataReg[index]);
  56.    }
  57.    password[index]='

  58. [/color];       
  59. }
  60. /*************************************************************
  61. **时钟配置函数  系统时钟为72MHz
  62. *************************************************************/
  63. void RCC_Configuration()
  64. {
  65.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC|\
  66.                            RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE,ENABLE);//使能所有GPIO的时钟
  67. }
  68. //GPIO配置函数
  69. void GPIO_Configuration(void)
  70. {
  71.   GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO的模式设置结构体变量
  72.   // PA1 接继电器 模拟开锁功能
  73.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  74.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  75.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  
  76.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  77.   CLOSE_DOOR; // 初始锁上
  78. }

  79. // 矩阵键盘接口配置
  80. void KeyBoard_Config(void)
  81. {
  82.         GPIO_InitTypeDef GPIO_InitStructure;
  83.         // 行线上拉输入
  84.         GPIO_InitStructure.GPIO_Pin = 0x000f;
  85.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  86.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  87.         GPIO_Init(GPIOE, &GPIO_InitStructure);
  88.         // 列线下拉输入
  89.         GPIO_InitStructure.GPIO_Pin = 0x00f0;
  90.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  91.         GPIO_Init(GPIOE, &GPIO_InitStructure);
  92. }
  93. // 列线转换为浮空输入
  94. void KeyBoard_Conv(uint16_t GPIO_Pin)
  95. {
  96.     GPIO_InitTypeDef GPIO_InitStructure;
  97.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
  98.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  99.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  100.         GPIO_Init(GPIOE, &GPIO_InitStructure);
  101.         // 列线浮空输入
  102.         GPIO_InitStructure.GPIO_Pin = 0x00f0;
  103.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  104.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  105.         GPIO_Init(GPIOE, &GPIO_InitStructure);
  106. }
  107. /********************************************************************
  108. *名   称: EXTI_Configuration
  109. *功   能:外部中断配置函数
  110. *说   明:PE.0~PE.3 键盘中断
  111. *********************************************************************/
  112. void EXTI_Configuration(void)
  113. {
  114.   EXTI_InitTypeDef EXTI_InitStructure;
  115.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);         //复用功能使能
  116.   GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0);
  117.   GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource1);
  118.   GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
  119.   GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);
  120.   EXTI_ClearITPendingBit(EXTI_Line0); //清除挂起/请求标志
  121.   EXTI_ClearITPendingBit(EXTI_Line1); //清除挂起/请求标志
  122.   EXTI_ClearITPendingBit(EXTI_Line2);
  123.   EXTI_ClearITPendingBit(EXTI_Line3);
  124.   // PE.0
  125.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  126.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  127.   EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  128.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  129.   EXTI_Init(&EXTI_InitStructure);
  130.   // PE.1
  131.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  132.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  133.   EXTI_InitStructure.EXTI_Line = EXTI_Line1;
  134.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  135.   EXTI_Init(&EXTI_InitStructure);
  136.   // PE.2
  137.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  138.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  139.   EXTI_InitStructure.EXTI_Line = EXTI_Line2;
  140.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  141.   EXTI_Init(&EXTI_InitStructure);
  142.   // PE.3
  143.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
  144.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  145.   EXTI_InitStructure.EXTI_Line = EXTI_Line3;
  146.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  147.   EXTI_Init(&EXTI_InitStructure);
  148. }
  149. /********************************************************************
  150. *名   称: NVIC_Configuration
  151. *功   能:中断配置
  152. *说   明:PE.0~PE.3 键盘中断,均为下降沿触发
  153. *********************************************************************/
  154. void NVIC_Configuration(void)
  155. {
  156.   NVIC_InitTypeDef NVIC_InitStructure;
  157.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  158.   // PE.0
  159.   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  160.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  161.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  162.   NVIC_Init(&NVIC_InitStructure);
  163.   // PE.1
  164.   NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
  165.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  166.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  167.   NVIC_Init(&NVIC_InitStructure);
  168.   // PE.2
  169.   NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
  170.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  171.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  172.   NVIC_Init(&NVIC_InitStructure);
  173.   // PE.3
  174.   NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
  175.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  176.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  177.   NVIC_Init(&NVIC_InitStructure);
  178. }

  179. //延时n us
  180. void delay_nus(unsigned long n)
  181. {
  182.         unsigned long j;
  183.         while(n--)
  184.         { j=15;
  185.           while(j--);
  186.         }
  187. }
  188. //延时n ms
  189. void delay_nms(unsigned long n)
  190. {
  191.         while(n--)
  192.            delay_nus(1075);
  193. }

  194. /********************************************************************
  195. *名   称: Change_Password
  196. *功   能:更改密码
  197. *说   明:直到新密码设定完成才退出此函数
  198. *********************************************************************/
  199. void Change_Password(void)
  200. {
  201.         uint16_t i,index=0;
  202.         uint16_t flag=0;
  203.         uint16_t passwordtmp2[21]={'

  204. [/color]};
  205.         LCD_Clear();
  206.         delay_nms(2);
  207.         for(i=0;i<21;i++)
  208.            passwordtmp[i] = '

  209. [/color];
  210.         LCD_Setpos_DispString(1,1,"请输入新密码:");
  211.         delay_nms(2);
  212.         LCD_Setpos(2,1);
  213.         delay_nms(1);
  214.         while(1)
  215.         {
  216.                 keyflag = 0;
  217.                 while(keyflag < 1)
  218.                 { }
  219.                 keyflag = 0;
  220.                 if(keyval<=9)
  221.                 {
  222.                   LCD_DispChar(keyval+'0');
  223.                   delay_nms(1);
  224.                   if(flag==0)
  225.                      passwordtmp[index++] = keyval;
  226.               else passwordtmp2[index++] = keyval;
  227.                 }
  228.                 else if((keyval == 'e')&&(flag == 0))
  229.                 {
  230.                     passwordtmp[index] = '

  231. [/color];
  232.                         LCD_Clear();
  233.                         delay_nms(1);
  234.                         LCD_Setpos_DispString(1,1,"请再次输入新密码");
  235.                         delay_nms(2);
  236.                         LCD_Setpos(2,1);
  237.                 delay_nms(1);
  238.                         flag  = 1;
  239.                         index = 0;
  240.                 }
  241.                 else if((keyval == 'e')&&(flag == 1))
  242.                 {
  243.                         for(i=0;passwordtmp[i]!='

  244. [/color];i++)
  245.                         {
  246.                                 if(passwordtmp[i] != passwordtmp2[i])
  247.                                 {
  248.                                         LCD_Clear();
  249.                                         delay_nms(1);
  250.                                         LCD_Setpos_DispString(1,1,"两次输入密码不同");
  251.                                         delay_nms(2);
  252.                                         LCD_Setpos_DispString(2,1,"请重新设定密码!");
  253.                                         delay_nms(1000);
  254.                                         LCD_Clear();
  255.                                         delay_nms(1);
  256.                                         LCD_Setpos_DispString(1,1,"请再次输入新密码");
  257.                                         delay_nms(2);
  258.                                         LCD_Setpos(2,1);
  259.                                 delay_nms(1);
  260.                                         flag  = 0;
  261.                                         index = 0;
  262.                                         break;
  263.                                 }
  264.                         }
  265.                         if(passwordtmp[i]=='

  266. [/color])
  267.                         {
  268.                                 for(i=0;passwordtmp[i]!='

  269. [/color];i++)
  270.                                 {
  271.                                         password[i] = passwordtmp[i];
  272.                                 }
  273.                                 password[i] = '

  274. [/color];
  275.                                 LCD_Clear();
  276.                                 delay_nms(1);
  277.                                 LCD_Setpos_DispString(2,1,"新密码设定成功!");
  278.                                 delay_nms(2);
  279.                                 LCD_Setpos_DispString(3,1,"请牢记新密码!");
  280.                                 delay_nms(1);
  281.                                 WritePasswordToBackupReg(password);        //保存新密码
  282.                                 delay_nms(3000);
  283.                                 break;
  284.                         }
  285.                 }
  286.         }
  287. }

  288. /********************************************************************
  289. *名   称: Input_Password()
  290. *功   能:输入密码
  291. *说   明:直到密码输入正确或新密码设定完成才退出此函数
  292. *********************************************************************/
  293. void Input_Password()
  294. {
  295.         __IO uint16_t i,index=0;
  296.         __IO uint16_t faultcount = 0;
  297.         LCD_Clear();
  298.         delay_nms(1);
  299.         LCD_Setpos_DispString(1,1,"请输入密码:");
  300.         delay_nms(2);
  301.         LCD_Setpos(2,1);
  302.         delay_nms(1);
  303.         while(1)
  304.         {
  305.                 keyflag = 0;
  306.                 while(keyflag < 1)
  307.                 { }
  308.                 keyflag = 0;
  309.                 if(keyval<=9)
  310.                 {
  311.                   LCD_DispChar(keyval+'0');
  312.                   delay_nms(1);
  313.                   passwordtmp[index++] = keyval;
  314.                 }
  315.                 else if(keyval == 'c')                   //按下取消键
  316.                 {
  317.                         index--;
  318.                         passwordtmp[index]='

  319. [/color];
  320.                         LCD_Clear();
  321.                         delay_nms(1);
  322.                         LCD_Setpos_DispString(1,1,"请输入密码:");
  323.                 delay_nms(2);
  324.                 LCD_Setpos(2,1);
  325.                 delay_nms(1);
  326.                         for(i=0;passwordtmp[i]!='

  327. [/color];i++)
  328.                         {
  329.                                 LCD_DispChar(passwordtmp[i]+'0');
  330.                         }
  331.                         delay_nms(1);
  332.                 }
  333.                 else if(keyval=='e')                   //按下确认键
  334.                 {
  335.                     passwordtmp[index] = '

  336. [/color];  //密码结束标记
  337.                         for(i=0;password[i]!='

  338. [/color];i++)
  339.                         {
  340.                                 if(passwordtmp[i] != password[i])
  341.                                 {
  342.                                         faultcount ++;
  343.                                         break;
  344.                                 }
  345.                         }
  346.                         if(faultcount == 3)
  347.                         {
  348.                                 faultcount = 0;
  349.                                 CLOSE_DOOR;
  350.                                 LCD_Clear();
  351.                                 delay_nms(1);
  352.                                 LCD_Setpos_DispString(2,1,"密码已经错误 3次");
  353.                                 delay_nms(2);
  354.                                 LCD_Setpos_DispString(3,1,"等待 1分钟后再试");
  355.                             delay_nms(60000); //密码错误3次以后,等待1分钟才可再次输入
  356.                                 LCD_Clear();
  357.                                 delay_nms(1);
  358.                                 LCD_Setpos_DispString(1,1,"请再次输入密码:");
  359.                     delay_nms(2);
  360.                                 LCD_Setpos(2,1);
  361.                     delay_nms(2);
  362.                                 index = 0;
  363.                         }
  364.                         else if((faultcount >0) && (password[i]!='

  365. [/color]))
  366.                         {
  367.                                 CLOSE_DOOR;
  368.                                 LCD_Clear();
  369.                                 delay_nms(2);
  370.                                 LCD_Setpos_DispString(2,2,"密码错误!");
  371.                                 delay_nms(1000);
  372.                                 LCD_Clear();
  373.                                 delay_nms(1);
  374.                                 LCD_Setpos_DispString(1,1,"请再次输入密码:");
  375.                     delay_nms(2);
  376.                                 LCD_Setpos(2,1);
  377.                     delay_nms(2);
  378.                                 index = 0;
  379.                         }
  380.                         if((password[i]=='

  381. [/color])&&(passwordtmp[i]=='

  382. [/color]))//输入密码正确
  383.                         {
  384.                           LCD_Clear();
  385.                           delay_nms(1);
  386.                           LCD_Setpos_DispString(2,3,"密码正确!");
  387.                           delay_nms(2);
  388.                           LCD_Setpos_DispString(3,3,"锁已打开!");


  389. …………限于本文篇幅 余下代码请从51黑下载附件…………

复制代码


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

使用道具 举报

沙发
ID:285821 发表于 2018-2-26 23:28 | 只看该作者
HAOLIHAO 牛人
回复

使用道具 举报

板凳
ID:285821 发表于 2018-2-27 21:28 | 只看该作者
有用的资料
回复

使用道具 举报

地板
ID:287002 发表于 2018-3-2 17:00 | 只看该作者
很好   学习了
回复

使用道具 举报

5#
ID:293829 发表于 2018-3-19 08:23 | 只看该作者
厉害了我的大佬
回复

使用道具 举报

6#
ID:293829 发表于 2018-3-19 15:36 | 只看该作者
积分被吞了,下载不了
回复

使用道具 举报

7#
ID:395465 发表于 2018-9-8 20:28 | 只看该作者
厉害啊  大佬
回复

使用道具 举报

8#
ID:293829 发表于 2018-9-27 17:37 | 只看该作者
下过的资料第二次下也要收黑币?
回复

使用道具 举报

9#
ID:421358 发表于 2018-11-6 11:15 | 只看该作者
有原理图嘛
回复

使用道具 举报

10#
ID:393816 发表于 2019-5-6 10:09 | 只看该作者
哇,好棒!
回复

使用道具 举报

11#
ID:528326 发表于 2019-5-6 11:02 | 只看该作者
感谢楼主分享,谢谢大佬
回复

使用道具 举报

12#
ID:574789 发表于 2019-12-23 07:48 | 只看该作者
用的什么板子
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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