希望这个实验能从一个实验由(一)到(二)到(三)到…等等,相关代码在文章结尾,虽然现在能力还不够,那就力所能及叭。
主要功能1、当输入代码正确时候,按下确定开锁按键,显示屏显示密码正确,锁打开 2、当输入代码不正确时候,按下确定开锁按键,显示屏显示密码错误,锁不能打开 3、实现再输入过程中密码由于不小心按错,将按下撤销按键实现密码重输 4、实现密码更改方便,并实现调电不丢失密码。
文章目录开头主要功能设计内容一、所需材料二、部分程序1.main.c2.key.c3.key.h三、有需要注意的地方总结相关程序全部资料 设计内容①开机:按下电源,电源指示灯点亮,OLED液晶显示:“Welecome my host”,按下输入密码按键后,液晶显示:“input:”,通过按键输入密码,若密码识别成功,继电器工作,开锁成功,OLED显示“OK”。若密码输入错误,则不会开锁,OLED显示“ERROR”。 ②设置模式:通过各个按下按键进入对应按键的模式。在模式下可以完成输入密码、撤销密码、和更改密码的功能。进入输入密码模式后,通过按键#选择哪一位密码需要更改,通过按键D将密码修改,若密码修改完成后通过按键0将密码导入,OLED显示“SUCCESS”,且此时密码修改后下一次打开保存的还是修改的密码,调电不丢失自己修改的密码。 **若是重新将代码烧入芯片中,首先需要按下0键将密码导入存储空间中,否则不能进行正常的输入密码比较
一、所需材料主要采用的是stm32f103zet6的开发板、正点原子的OLED显示屏、一个矩阵按键,一个继电器、一个电磁锁模块。
二、部分程序 1.main.c代码如下(示例):
#include "stm32f10x.h"#include "sys.h"#include "delay.h"#include "oled.h"#include "KEY1.h"#include "usart.h"#include "flash.h"unsigned char Password2[7]={1,1,1,1,1,1,0};//修改后的新密码存储在这个数组中,密码长度为6位,数组最后一位为更改后密码标志位unsigned char Password[6]={0,0,0,0,0,0};#define SIZE sizeof(Password2)//数组长度#define FLASH_SAVE_ADDR 0X08070000//存储密码地址#define FLASH_SAVE_ADDR1 0X08020000u8 flag=0;unsigned char Password1[7]={1,2,3,4,5,6,0};;unsigned char Password_count=0; unsigned int a_c,b_c,c_c,d_c;unsigned char key_back;unsigned char flag_key_back=0,flag_key_back1=0;u16 flag_key_data=0;u16* flag_key=&flag_key_data;/*修改密码并进行密码导入函数*/void change_key(){static unsigned int i_c=0;unsigned char a;if((key_back=='#')&&(flag_key_back1==1))//选择密码修改是哪一位{a_c=Password[i_c];i_c++;if(i_c==7){i_c=1;}OLED_ShowChar(50+i_c*8,8,13+' ',16,1); OLED_Refresh_Gram();if(i_c>1){OLED_ShowChar(50+(i_c-1)*8,8,10+' ',16,1);OLED_Refresh_Gram();}flag_key_back=1;}if((key_back=='D')&&(flag_key_back==1))//由上面选择是哪一位要修改的密码,在对这一位密码进行递增的方式进行修改,累加到9后回到0{a_c++; if(a_c>9)a_c=0;Password2[i_c-1]=a_c;OLED_ShowChar(50+i_c*8,8,Password2[i_c-1]+'0',16,1);OLED_Refresh_Gram();}if(key_back==0)//修改密码后按下0键确认导入 { Password2[6]=1; delay_ms(10);STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)Password2,SIZE);OLED_Clear();OLED_ShowString(0,0,">",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>>>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>>>>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>>>>>",24);OLED_Refresh_Gram();delay_ms(100);OLED_ShowString(0,0,">>>>>>>>",24);OLED_Refresh_Gram();delay_ms(100); OLED_Refresh_Gram(); delay_ms(100);STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)Password1,SIZE);OLED_Clear(); OLED_ShowString(25,25,"Suscess!",12); OLED_Refresh_Gram(); delay_ms(50); OLED_ShowString(25,25,"Suscess!",16); OLED_Refresh_Gram();delay_ms(50); OLED_ShowString(25,25,"Suscess!",24); OLED_Refresh_Gram();delay_ms(50);}}/*按键处理函数,对输入密码进行比较看密码是否输入正确*/void data_key(){ unsigned char i; unsigned char flag_data_key1=0;i=' ';//因为采用的ASCII码数组来显示OLED所以需要先转换成ASCII码if(key_back=='C'){OLED_Clear();OLED_ShowString(0,8,"input:",16);flag=1;Password_count=0;flag_key_back=0;flag_key_back1=1;flag_data_key1=1;GPIO_SetBits(GPIOF,GPIO_Pin_13);}if(flag==1){if(key_back>0&&key_backPassword[Password_count]=key_back;Password_count++; if(Password_count==1) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_Refresh_Gram(); OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_Refresh_Gram(); } if(Password_count==2) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_Refresh_Gram(); } if(Password_count==3) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_Refresh_Gram(); } if(Password_count==4) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_Refresh_Gram(); } if(Password_count==5) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_Refresh_Gram(); } if(Password_count==6) { OLED_ShowChar(50+Password_count*8,8,10+i,16,1); OLED_Refresh_Gram(); } } }else if((key_back=='A')) //撤销按键 {if(Password_count>0) Password_count--; if(Password_count==0) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } if(Password_count==1) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } if(Password_count==2) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } if(Password_count==3) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } if(Password_count==4) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } if(Password_count==5) { OLED_ShowChar(58+Password_count*8,8,13+i,16,1); OLED_ShowChar(58+(Password_count+1)*8,8,i,16,1); OLED_Refresh_Gram(); } }else if((key_back=='B')&&(Password1[6]==0)) //确认按键 { if((Password[0]==1&&Password[1]==2&&Password[2]==3&&Password[3]==4&&Password[4]==5&&Password[5]==6)||(Password[0]==Password1[0]&&Password[1]==Password1[1]&&Password[2]==Password1[2]&&Password[3]==Password1[3]&&Password[4]==Password1[4]&&Password[5]==Password1[5])){ OLED_Clear();OLED_ShowString(20,20,"OK",24); OLED_Refresh_Gram();flag_key_back1=0;flag_data_key1=0;GPIO_SetBits(GPIOF,GPIO_Pin_13); //继电器的引脚PF13}else { OLED_Clear(); OLED_ShowString(20,20,"ERROR",24); OLED_Refresh_Gram(); flag_key_back1=0; flag_data_key1=0; GPIO_ResetBits(GPIOF,GPIO_Pin_13); } } else if((key_back=='B')&&(Password1[6]==1)) //确认按键 { if(Password[0]==Password1[0]&&Password[1]==Password1[1]&&Password[2]==Password1[2]&&Password[3]==Password1[3]&&Password[4]==Password1[4]&&Password[5]==Password1[5]){ OLED_Clear();OLED_ShowString(60,30,"OK",24); OLED_Refresh_Gram(); //¼ÌµçÆ÷Òý½Åpf13GPIO_ResetBits(GPIOF,GPIO_Pin_13);}else { OLED_Clear(); OLED_ShowString(40,30,"ERROR",24); OLED_Refresh_Gram(); GPIO_SetBits(GPIOF,GPIO_Pin_13); } } OLED_Refresh_Gram(); }}/*主函数,来调用子函数的内容*/ int main(void) { delay_init(); //延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断优先级分组2,2位抢占优先级,2位响应优先级OLED_Init();//初始化OLED Matrix_Key_Init();OLED_ShowString(0,0," --------------- ",16);OLED_ShowString(20,16, "Welecome",24);OLED_ShowString(25,46,"MY HOST",16); OLED_Refresh_Gram();//更新显示到OLEDdelay_ms(1000); GPIO_SetBits(GPIOF,GPIO_Pin_13); delay_ms(1000);STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)Password1,SIZE);while(1) {key_back=Matrix_Key_Scan();data_key();change_key();}} 2.key.c(有较强的可移植性,之前根据五一单片机的那种矩阵按键格式写的,但后来在网上进行翻阅的时候发现下面这种代码有很强的移植性,要是要更改只需更改.h文件中引脚就可以,所以网友们还是万能的)
代码如下(示例):
#include "KEY1.h"#include "delay.h"#include "sys.h"unsigned char Y1,Y2,Y3,Y4;void Matrix_Key_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(X1_RCC|X2_RCC|X3_RCC|X4_RCC|Y1_RCC|Y2_RCC|Y3_RCC|Y4_RCC|RCC_APB2Periph_AFIO, ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); GPIO_InitStructure.GPIO_Pin = X1_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(X1_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = X2_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(X2_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = X3_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(X3_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = X4_GPIO_PIN ;GPIO_Init(X4_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = Y1_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(Y1_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = Y2_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(Y2_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = Y3_GPIO_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(Y3_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = Y4_GPIO_PIN; GPIO_Init(Y4_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOF, &GPIO_InitStructure);}int Matrix_Key_Scan(void){static char key_down = 0;uchar KeyVal = KEY_ERR;GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN); GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN); GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN); GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN); if ((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y2_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y3_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y4_GPIO_PIN)==1)){delay_ms(10);if ((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y2_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y3_GPIO_PIN)==1) || (GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y4_GPIO_PIN)==1)){if (key_down == 0){key_down = 1;GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN);GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN); Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);if(Y1==1&&Y2==0&&Y3==0&&Y4==0)KeyVal='A';if(Y1==0&&Y2==1&&Y3==0&&Y4==0)KeyVal='B';if(Y1==0&&Y2==0&&Y3==1&&Y4==0)KeyVal='C';if(Y1==0&&Y2==0&&Y3==0&&Y4==1)KeyVal='D';/**************************************************/GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN);GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);if(Y1==1&&Y2==0&&Y3==0&&Y4==0)KeyVal=3;if(Y1==0&&Y2==1&&Y3==0&&Y4==0)KeyVal=6;if(Y1==0&&Y2==0&&Y3==1&&Y4==0)KeyVal=9;if(Y1==0&&Y2==0&&Y3==0&&Y4==1)KeyVal='#';/**************************************************/GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN);GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);if(Y1==1&&Y2==0&&Y3==0&&Y4==0)KeyVal=2;if(Y1==0&&Y2==1&&Y3==0&&Y4==0)KeyVal=5;if(Y1==0&&Y2==0&&Y3==1&&Y4==0)KeyVal=8;if(Y1==0&&Y2==0&&Y3==0&&Y4==1)KeyVal=0;/**************************************************/GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN); GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN); GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN); Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);if(Y1==1&&Y2==0&&Y3==0&&Y4==0)KeyVal=1;if(Y1==0&&Y2==1&&Y3==0&&Y4==0)KeyVal=4;if(Y1==0&&Y2==0&&Y3==1&&Y4==0)KeyVal=7;if(Y1==0&&Y2==0&&Y3==0&&Y4==1)KeyVal='*';}}}else{key_down = 0;KeyVal = KEY_ERR;}return KeyVal;} 3.key.h #ifndef _KEY1_H#define _KEY1_H #include #include "usart.h"#include "sys.h"#define uint unsigned int #define uchar unsigned char#define X1_GPIO_PORT GPIOF#define X2_GPIO_PORT GPIOF#define X3_GPIO_PORT GPIOF#define X4_GPIO_PORT GPIOF #define Y1_GPIO_PORT GPIOF #define Y2_GPIO_PORT GPIOF#define Y3_GPIO_PORT GPIOF#define Y4_GPIO_PORT GPIOF #define X1_GPIO_PIN GPIO_Pin_7#define X2_GPIO_PIN GPIO_Pin_6#define X3_GPIO_PIN GPIO_Pin_5#define X4_GPIO_PIN GPIO_Pin_4#define Y1_GPIO_PIN GPIO_Pin_0#define Y2_GPIO_PIN GPIO_Pin_1#define Y3_GPIO_PIN GPIO_Pin_2#define Y4_GPIO_PIN GPIO_Pin_3#define X1_RCC RCC_APB2Periph_GPIOF#define X2_RCC RCC_APB2Periph_GPIOF#define X3_RCC RCC_APB2Periph_GPIOF#define X4_RCC RCC_APB2Periph_GPIOF#define Y1_RCC RCC_APB2Periph_GPIOF#define Y2_RCC RCC_APB2Periph_GPIOF#define Y3_RCC RCC_APB2Periph_GPIOF#define Y4_RCC RCC_APB2Periph_GPIOF#define KEY_ERR 255void Matrix_Key_Init(void);int Matrix_Key_Scan(void);void Matrix_Key_Test(void) ;#endif三、有需要注意的地方①如果大家用的是开发板的引脚输出来的高低电平作为5v继电器开与关的状态,这样电压是不够的,,因为引脚输出的电压是3.3v,而继电器需要的是5v的电压,所以需要在作为连接继电器的输出引脚再连接一个放大电路3.3v转5v,我也是焊接了一个这样的电路,只需要两个电阻和一个三极管组成就可以了,不懂的可以在网上搜关于这个电路 ②如果对于功能不能正常实现可以慢慢找到相对应的错误所在,如何找到对应代码,可以用串口助手进行调试也可以用OLED调试,因为这个实验用到了OLED,所以直接用OLED调试也蛮方便,在认为错误的代码上下加上OLED显示函数,看看经过了这个代码能不能实现OLED对应的显示,如果不能说明这段代码确实有问题。
总结这段程序也经过我自己操作实现了功能,只有通过实践操作才能让自己的能力一步一步上涨,虽然途中会遇到很多问题和一些错误,一个一个解决就好了,经验也是慢慢堆起来的,从简单到复杂,希望接下来我能继续对简易密码锁改善成(二),循循渐进。 整体轮廓
相关程序全部资料