1、状态机讲解
状态机其实在学习数字电路的接触过但是我已经忘得差不多了,由于我的毕业设计是关于FPGA的题目,状态机是重中之重。 刚才在贴吧有uu们问关于单片机之类的密码锁的问题,突然想到之前蓝桥杯当时也有类似的题目,我当时处理的不是特别好,所以现在想着用C去实现,本科毕设时我导师是一直让我使用三段状态机,模式固定,逻辑清晰,写起来也比较容易,说白了就是一个流程图。
在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;//不要忘记其他状态关闭哦
}
*/
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");
}
}
解释一下为什么我不限制密码输入的位数(可以理解我们手机锁屏,只能输入4位),这样其实是很好的安全方式,假如有人在看我们输密码,只要我们输入的密码里含有正确密码即可,4412212与7612212都是正确密码。
标签:STM32,IDLE,else,状态机,state,num,key,按键,密码锁 From: https://blog.51cto.com/u_16086695/6317615