/***************************************************************************** ** 電子密碼鎖設計 **文件名稱: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黑下載附件…………
|