/***************************************************************************** ** 电子密码锁设计 **文件名称: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黑下载附件…………
|