0
点赞
收藏
分享

微信扫一扫

基于状态机STM32/51密码锁

1、状态机讲解

状态机其实在学习数字电路的接触过但是我已经忘得差不多了,由于我的毕业设计是关于FPGA的题目,状态机是重中之重。 刚才在贴吧有uu们问关于单片机之类的密码锁的问题,突然想到之前蓝桥杯当时也有类似的题目,我当时处理的不是特别好,所以现在想着用C去实现,本科毕设时我导师是一直让我使用三段状态机,模式固定,逻辑清晰,写起来也比较容易,说白了就是一个流程图。

基于状态机STM32/51密码锁_嵌入式

在FPGA里面由于我们都是在clk跳变时才会变化,但是单片机程序编写时没有这种拘束,所以第一段可以抛弃,保留第二段、第三段即可,第二段触发条件就是按键按下(描述状态切换),第三段主要根据当前状态去判断(根据状态进行响应输出)。

2、C/C++实现方式

代码我虽然用的是C++,但是基本参照C来。设置开门密码为 34688,这里我只给了大家理想的转换图(按照密码输入),也就是说当在TWO状态时我按下8,此时按键组合为348,完全不符合密码要求直接回到IDLE,如果按下3时按键组合为343回到ONE,因为现在第一位是3符合要求。 如果大家实在不理解状态机直接看我的流程图以及代码就可以,很好理解

#include <iostream>

using namespace std;

//开门密码为34668
//定义各状态,状态数=密码位数+空状态
#define  IDLE   0
#define	 ONE    1
#define  TWO    2
#define  THREE  3
#define  FOUR   4
#define  FIVE   5
//定义状态
int state = IDLE;
//函数声明
void Key_scan();
void Trans_state();
void Out_put();
//全局变量区
int  key_num=0;
bool key_flag=0;

void main()
{
	while (1)
	{
		Key_scan();//按键扫描函数
		Trans_state();//状态转换函数
		Out_put();//状态判断函数
	}
	

}


void Key_scan()
{

	cout << "请输入当前密码:" ;

	cin >> key_num;  //这里模仿我们日常的按键检测,实际操作时每次进入Key_Scan函数时初始化num数值为0,

	if (key_num == 0) //如果还是0的话表示无按键按下
		key_flag = 0;
	else
		key_flag = 1;//按键按下的标志位
}

/*实际操作
void Key_scan()
{
	key_num=-1;

	*按键检测执行*
	//在实际操作中按键是有0按键的,所以初始化为-1会更好 
	
	if (key_num == -1) //如果还是0的话表示无按键按下
		key_flag = 0;
	else
		key_flag = 1;//按键按下的标志位
}

*/

void Trans_state()
{
	if (key_flag )//按键按下标志位有效才会进行判断
	{
		switch (state)
		{
		case IDLE: 
			if (key_num == 3)
				state = ONE;
			else
				state = IDLE;
			break;

		case ONE:
			if (key_num == 4)
				state = TWO;
			else if (key_num == 3)
				state = ONE;
			else
				state = IDLE;
			break;

		case TWO:
			if (key_num == 6)
				state = THREE;
			else if (key_num == 3)
				state = ONE;
			else
				state = IDLE;
			break;

		case THREE:
			if (key_num == 6)
				state = FOUR;
			else if (key_num == 3)
				state = ONE;
			else
				state = IDLE;
			break;

		case FOUR:
			if (key_num == 8)
				state = FIVE;
			else if (key_num == 3)
				state = ONE;
			else
				state = IDLE;
			break;

		case FIVE:
			state = IDLE;
			break;

		default:
			state = IDLE;
			break;
		}
	}
}

void Out_put()
{
	if (state == FIVE)
	{
	  state = IDLE;
	  cout << "门锁打开" << endl;//实际操做可以利用LED表示
	}
		
}
/*实际操作
void Out_put()
{
	if (state == FIVE)
	{
	   state = IDLE;
	   LED0=1;
	}
	        
	else
		LED0=0;//不要忘记其他状态关闭哦
}
*/

基于状态机STM32/51密码锁_状态机_02

3、STM32F103ZET6最小系统板上板测试

由于按键原因,密码修改为12212

#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
 

//开门密码为12212
//定义各状态,状态数=密码位数+空状态
#define  IDLE   0
#define	 ONE    1
#define  TWO    2
#define  THREE  3
#define  FOUR   4
#define  FIVE   5
//定义状态
u8 state = IDLE;
//函数声明
void Key_scan();
void Trans_state();
void Out_put();
//全局变量区
u8  key_num=0;
u8  key_flag=0;
 int main(void)
 {
	delay_init();	    	 //延时函数初始化	  
	KEY_Init();          //初始化与按键连接的硬件接口
	uart_init(115200);
	while(1)
	{
		Key_scan();//按键扫描函数
		Trans_state();//状态转换函数
		Out_put();//状态判断函数
  }
}




void Key_scan()
{
	key_num= 0;
	//*按键检测执行*
	//在实际操作中按键是有0按键的,所以初始化为-1会更好
  if(!KEY0|!KEY1)
	{
		delay_ms(10);
		  if(!KEY0|!KEY1)
			{
				if(!KEY0)      key_num=1;
				else           key_num=2;
				while(!KEY0|!KEY1);//松手检测
				printf("当前按下的按键:%d\r\n",key_num);
			}
	}
	
	if (key_num == 0) //如果还是0的话表示无按键按下
		key_flag = 0;
	else
		key_flag = 1;//按键按下的标志位
}



void Trans_state()
{
	if (key_flag )//按键按下标志位有效才会进行判断
	{
		switch (state)
		{
		case IDLE: 
			if (key_num == 1)
				state = ONE;
			else
				state = IDLE;
			break;

		case ONE:
			if (key_num == 2)
				state = TWO;
			else if (key_num == 1)
				state = ONE;
			else
				state = IDLE;
			break;

		case TWO:
			if (key_num == 2)
				state = THREE;
			else if (key_num == 1)
				state = ONE;
			else
				state = IDLE;
			break;

		case THREE:
			if (key_num == 1)
				state = FOUR;
			else
				state = IDLE;
			break;

		case FOUR:
			if (key_num == 2)
				state = FIVE;
			else if (key_num == 1)
				state = ONE;
			else
				state = IDLE;
			break;

		case FIVE:
			state = IDLE;
			break;

		default:
			state = IDLE;
			break;
		}
	}
}

void Out_put()
{
	if (state == FIVE)
	{
	   state = IDLE;
	   printf("密码正确\r\n");
	}
	        
}

基于状态机STM32/51密码锁_状态机_03

解释一下为什么我不限制密码输入的位数(可以理解我们手机锁屏,只能输入4位),这样其实是很好的安全方式,假如有人在看我们输密码,只要我们输入的密码里含有正确密码即可,4412212与7612212都是正确密码。

举报

相关推荐

0 条评论