开头
希望这个实验能从一个实验由(一)到(二)到(三)到…等等,相关代码在文章结尾,虽然现在能力还不够,那就力所能及叭。
主要功能
1、当输入代码正确时候,按下确定开锁按键,显示屏显示密码正确,锁打开
2、当输入代码不正确时候,按下确定开锁按键,显示屏显示密码错误,锁不能打开
3、实现再输入过程中密码由于不小心按错,将按下撤销按键实现密码重输
4、实现密码更改方便,并实现调电不丢失密码。
设计内容
①开机:按下电源,电源指示灯点亮,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 0X08020000
u8 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_back<=9) //输入密码0-9
{
if(Password_count<6)
{
Password[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();
//¼ÌµçÆ÷Òý½Åpf13
GPIO_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(); //更新显示到OLED
delay_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 <stm32f10x.h>
#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 255
void 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对应的显示,如果不能说明这段代码确实有问题。
总结
这段程序也经过我自己操作实现了功能,只有通过实践操作才能让自己的能力一步一步上涨,虽然途中会遇到很多问题和一些错误,一个一个解决就好了,经验也是慢慢堆起来的,从简单到复杂,希望接下来我能继续对简易密码锁改善成(二),循循渐进。
整体轮廓
相关程序全部资料
链接:https://pan.baidu.com/s/1xcOLsRNtreshgxoWN3JBYw
提取码:like
学习从零开始,到无穷结束
版权声明:本文为CSDN博主「Justin-Wei」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46285130/article/details/118435145
开头
希望这个实验能从一个实验由(一)到(二)到(三)到…等等,相关代码在文章结尾,虽然现在能力还不够,那就力所能及叭。
主要功能
1、当输入代码正确时候,按下确定开锁按键,显示屏显示密码正确,锁打开
2、当输入代码不正确时候,按下确定开锁按键,显示屏显示密码错误,锁不能打开
3、实现再输入过程中密码由于不小心按错,将按下撤销按键实现密码重输
4、实现密码更改方便,并实现调电不丢失密码。
设计内容
①开机:按下电源,电源指示灯点亮,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 0X08020000
u8 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_back<=9) //输入密码0-9
{
if(Password_count<6)
{
Password[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();
//¼ÌµçÆ÷Òý½Åpf13
GPIO_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(); //更新显示到OLED
delay_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 <stm32f10x.h>
#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 255
void 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对应的显示,如果不能说明这段代码确实有问题。
总结
这段程序也经过我自己操作实现了功能,只有通过实践操作才能让自己的能力一步一步上涨,虽然途中会遇到很多问题和一些错误,一个一个解决就好了,经验也是慢慢堆起来的,从简单到复杂,希望接下来我能继续对简易密码锁改善成(二),循循渐进。
整体轮廓
相关程序全部资料
链接:https://pan.baidu.com/s/1xcOLsRNtreshgxoWN3JBYw
提取码:like
学习从零开始,到无穷结束
版权声明:本文为CSDN博主「Justin-Wei」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46285130/article/details/118435145
暂无评论