**功能:支持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
单片机源码:
- /*****************************************************************************
- ** 电子密码锁设计
- **文件名称:main.c
- **by 追梦 2011-5-12
- **功能:支持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 连接继电器,低电平时合上,高电平时断开相当于开锁与上锁
- *****************************************************************************/
- #include "STM32f10x.h"
- #include "LCD12864.h"
- extern __IO uint16_t keyval;
- extern __IO uint16_t keyflag;
- uint16_t password[21]={1,2,3,4,5,6,'
- }; //初始密码为 123456
- uint16_t passwordtmp[21];
- #define OPEN_DOOR GPIOA->BRR = GPIO_Pin_1
- #define CLOSE_DOOR GPIOA->BSRR = GPIO_Pin_1
- //数组中存放各个备份数据寄存器基于BKP基地址的偏移地址,用于存储密码
- uint16_t BKPDataReg[21] =
- {
- BKP_DR2, BKP_DR3, BKP_DR4, BKP_DR5, BKP_DR6, BKP_DR7, BKP_DR8, BKP_DR9,
- BKP_DR10, BKP_DR11, BKP_DR12, BKP_DR13, BKP_DR14, BKP_DR15,BKP_DR16,BKP_DR17,
- BKP_DR18, BKP_DR19, BKP_DR20, BKP_DR21, BKP_DR22
- };
- /**
- * 写密码到备份寄存器,掉电不丢失,电源复位不丢失
- */
- void WritePasswordToBackupReg(uint16_t passwordarray[])
- {
- uint32_t index = 0;
- /* 使能写入BKP */
- PWR_BackupAccessCmd(ENABLE);
- /* 清除事件挂起位 pin Event(TE) */
- BKP_ClearFlag();
- for (index = 0; passwordarray[index]!='
- ; index++)
- { //偏移地址 和 数据
- BKP_WriteBackupRegister(BKPDataReg[index], passwordarray[index]);
- }
- BKP_WriteBackupRegister(BKPDataReg[index], passwordarray[index]); //写入密码结尾符
- }
- /**
- * 上电或复位后读出备份区里保存的密码
- */
- void Load_Password(void)
- {
- uint32_t index = 0;
- for(index = 0; BKP_ReadBackupRegister(BKPDataReg[index])!='
- ; index++)
- {
- password[index]=BKP_ReadBackupRegister(BKPDataReg[index]);
- }
- password[index]='
- ;
- }
- /*************************************************************
- **时钟配置函数 系统时钟为72MHz
- *************************************************************/
- void RCC_Configuration()
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC|
- RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE,ENABLE);//使能所有GPIO的时钟
- }
- //GPIO配置函数
- void GPIO_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO的模式设置结构体变量
- // PA1 接继电器 模拟开锁功能
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- CLOSE_DOOR; // 初始锁上
- }
- // 矩阵键盘接口配置
- void KeyBoard_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- // 行线上拉输入
- GPIO_InitStructure.GPIO_Pin = 0x000f;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- // 列线下拉输入
- GPIO_InitStructure.GPIO_Pin = 0x00f0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- }
- // 列线转换为浮空输入
- void KeyBoard_Conv(uint16_t GPIO_Pin)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- // 列线浮空输入
- GPIO_InitStructure.GPIO_Pin = 0x00f0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- }
- /********************************************************************
- *名 称: EXTI_Configuration
- *功 能:外部中断配置函数
- *说 明:PE.0~PE.3 键盘中断
- *********************************************************************/
- void EXTI_Configuration(void)
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用功能使能
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0);
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource1);
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);
- EXTI_ClearITPendingBit(EXTI_Line0); //清除挂起/请求标志
- EXTI_ClearITPendingBit(EXTI_Line1); //清除挂起/请求标志
- EXTI_ClearITPendingBit(EXTI_Line2);
- EXTI_ClearITPendingBit(EXTI_Line3);
- // PE.0
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_Line = EXTI_Line0;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- // PE.1
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_Line = EXTI_Line1;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- // PE.2
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_Line = EXTI_Line2;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- // PE.3
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_Line = EXTI_Line3;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- }
- /********************************************************************
- *名 称: NVIC_Configuration
- *功 能:中断配置
- *说 明:PE.0~PE.3 键盘中断,均为下降沿触发
- *********************************************************************/
- void NVIC_Configuration(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- // PE.0
- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_Init(&NVIC_InitStructure);
- // PE.1
- NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_Init(&NVIC_InitStructure);
- // PE.2
- NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
- NVIC_Init(&NVIC_InitStructure);
- // PE.3
- NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_Init(&NVIC_InitStructure);
- }
- //延时n us
- void delay_nus(unsigned long n)
- {
- unsigned long j;
- while(n--)
- { j=15;
- while(j--);
- }
- }
- //延时n ms
- void delay_nms(unsigned long n)
- {
- while(n--)
- delay_nus(1075);
- }
- /********************************************************************
- *名 称: Change_Password
- *功 能:更改密码
- *说 明:直到新密码设定完成才退出此函数
- *********************************************************************/
- void Change_Password(void)
- {
- uint16_t i,index=0;
- uint16_t flag=0;
- uint16_t passwordtmp2[21]={'
- };
- LCD_Clear();
- delay_nms(2);
- for(i=0;i<21;i++)
- passwordtmp = '
- ;
- LCD_Setpos_DispString(1,1,"请输入新密码:");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(1);
- while(1)
- {
- keyflag = 0;
- while(keyflag < 1)
- { }
- keyflag = 0;
- if(keyval<=9)
- {
- LCD_DispChar(keyval+'0');
- delay_nms(1);
- if(flag==0)
- passwordtmp[index++] = keyval;
- else passwordtmp2[index++] = keyval;
- }
- else if((keyval == 'e')&&(flag == 0))
- {
- passwordtmp[index] = '
- ;
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请再次输入新密码");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(1);
- flag = 1;
- index = 0;
- }
- else if((keyval == 'e')&&(flag == 1))
- {
- for(i=0;passwordtmp!='
- ;i++)
- {
- if(passwordtmp != passwordtmp2)
- {
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"两次输入密码不同");
- delay_nms(2);
- LCD_Setpos_DispString(2,1,"请重新设定密码!");
- delay_nms(1000);
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请再次输入新密码");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(1);
- flag = 0;
- index = 0;
- break;
- }
- }
- if(passwordtmp=='
- )
- {
- for(i=0;passwordtmp!='
- ;i++)
- {
- password = passwordtmp;
- }
- password = '
- ;
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(2,1,"新密码设定成功!");
- delay_nms(2);
- LCD_Setpos_DispString(3,1,"请牢记新密码!");
- delay_nms(1);
- WritePasswordToBackupReg(password); //保存新密码
- delay_nms(3000);
- break;
- }
- }
- }
- }
- /********************************************************************
- *名 称: Input_Password()
- *功 能:输入密码
- *说 明:直到密码输入正确或新密码设定完成才退出此函数
- *********************************************************************/
- void Input_Password()
- {
- __IO uint16_t i,index=0;
- __IO uint16_t faultcount = 0;
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请输入密码:");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(1);
- while(1)
- {
- keyflag = 0;
- while(keyflag < 1)
- { }
- keyflag = 0;
- if(keyval<=9)
- {
- LCD_DispChar(keyval+'0');
- delay_nms(1);
- passwordtmp[index++] = keyval;
- }
- else if(keyval == 'c') //按下取消键
- {
- index--;
- passwordtmp[index]='
- ;
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请输入密码:");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(1);
- for(i=0;passwordtmp!='
- ;i++)
- {
- LCD_DispChar(passwordtmp+'0');
- }
- delay_nms(1);
- }
- else if(keyval=='e') //按下确认键
- {
- passwordtmp[index] = '
- ; //密码结束标记
- for(i=0;password!='
- ;i++)
- {
- if(passwordtmp != password)
- {
- faultcount ++;
- break;
- }
- }
- if(faultcount == 3)
- {
- faultcount = 0;
- CLOSE_DOOR;
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(2,1,"密码已经错误 3次");
- delay_nms(2);
- LCD_Setpos_DispString(3,1,"等待 1分钟后再试");
- delay_nms(60000); //密码错误3次以后,等待1分钟才可再次输入
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请再次输入密码:");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(2);
- index = 0;
- }
- else if((faultcount >0) && (password!='
- ))
- {
- CLOSE_DOOR;
- LCD_Clear();
- delay_nms(2);
- LCD_Setpos_DispString(2,2,"密码错误!");
- delay_nms(1000);
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(1,1,"请再次输入密码:");
- delay_nms(2);
- LCD_Setpos(2,1);
- delay_nms(2);
- index = 0;
- }
- if((password=='
- )&&(passwordtmp=='
- ))//输入密码正确
- {
- LCD_Clear();
- delay_nms(1);
- LCD_Setpos_DispString(2,3,"密码正确!");
- delay_nms(2);
- LCD_Setpos_DispString(3,3,"锁已打开!");
- …………限于本文篇幅 余下代码请从电子发烧友下载附件…………
|
3
|
|
|
|