标题: 电子密码锁设计 [打印本页]
作者: 星星小白 时间: 2018-4-25 09:06
标题: 电子密码锁设计
/*****************************************************************************
** 电子密码锁设计
**文件名称: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_InitTypeDefGPIO_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_InitTypeDefGPIO_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_InitTypeDefEXTI_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_InitTypeDefNVIC_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);
}
//延时nus
void delay_nus(unsigned long n)
{
unsigned longj;
while(n--)
{ j=15;
while(j--);
}
}
//延时nms
void delay_nms(unsigned long n)
{
while(n--)
delay_nus(1075);
}
/********************************************************************
*名 称: Change_Password
*功 能:更改密码
*说 明:直到新密码设定完成才退出此函数
*********************************************************************/
void Change_Password(void)
{
uint16_ti,index=0;
uint16_tflag=0;
uint16_tpasswordtmp2[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;
elsepasswordtmp2[index++] = keyval;
}
elseif((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;
}
elseif((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_ti,index=0;
__IO uint16_tfaultcount = 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;
}
elseif(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);
}
elseif(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,"锁已打开!");
…………限于本文篇幅 余下代码请从51黑下载附件…………
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |