一、项目需求
- 使用红外传感器来检测是否有人通过
- 使用LCD1602来显示通过的人,也就是计数值
- 允许通过时,LED1(绿灯)闪烁,蜂鸣器不响,继电器不闭合(类似闸门打开)
- 不允许通过时,LED2(红灯)闪烁,蜂鸣器响,继电器闭合
- 每次允许通过5个人,通过5个人后,转变为不允许通过状态,等待3秒后再转为允许通过。(一下子过去太多人怕堵了)
二、硬件清单
- 继电器(模拟闸机)
- 蜂鸣器
- 红外避障模块
- LCD1602(也可以换成OLED显示屏)
- STM32F103C8T6芯片
- ST-Link
三、项目流程
1.项目框图
这就是我整个的一个硬件概况,下面说一下我的硬件接线,大家也可以自行根据需要更改:
上面就是芯片和各个模块之间的连线了,引脚各自对应起来就可以啦
2.状态机
相信大家都有听说过状态机吧,我们程序设计中很常用的一种方法。
状态机(State Machine)是一种用于描述系统行为或功能行为的数学模型。它通常包含一组状态、一组转换条件以及动作执行。状态机通过在不同状态之间进行转换来模拟系统的行为。每个状态都代表系统的一个特定配置或情况,而转换规则则定义了从一个状态转换到另一个状态的条件和动作。
官方语言,有点干涩,咱可以简单理解为,一个状态对应一个事,然后每个状态之间有相互触发的条件。就比如:
你开心,就会去撸串;(状态)
你郁闷,就会去打游戏;(状态)
你开心的时候女朋友提分手了,变郁闷了;(状态转换)
你郁闷了时候刮彩票中了,变开心了;(状态转换)
四、主要代码
了解了状态机之后我们就可以设计程序了:
那么我们就可以编写代码了,这段是主要代码,在这里的延时我用的是SysTick时钟做的延时代码,
#include "Tasks.h"
#include "Led.h"
#include "Beep.h"
#include "Sensor.h"
#include "LCD1602.h"
//定义通过的人数
uint8_t char Number = 0;
enum
{
PASS_STATE,
WAIT_STATE
}; //枚举两个状态,就是上面说的状态机
//分别表示三个时间,Led1闪烁时间,Led2闪烁时间,等待时间
uint32_t Led1_task_cnt = 0;
uint32_t Led2_task_cnt = 0;
uint32_t Wait_cnt = 0;
//定义标志位,来判断什么时候灯闪烁和处于什么状态
uint8_t Led1_task_flag = 0;
uint8_t Led2_task_flag = 0;
uint8_t state = PASS_STATE;
void Systick_isr(void)
{
//通行状态
if(state == PASS_STATE)
{
//LED1一秒闪烁
if(Led1_task_cnt < 1000)
Led1_task_cnt++;
else
{
Led1_task_flag = 1;
Led1_task_cnt = 0;
}
//led2不闪
Led2_OFF();
//蜂鸣器不响
Beep_OFF();
//打开闸门
Door_Open();
}
//禁止状态
else if(state == WAIT_STATE)
{
if(Led2_task_cnt < 250)
Led2_task_cnt++;
else
{
Led2_task_flag = 1;
Led2_task_cnt = 0;
}
Led1_OFF();
Beep_ON();
Door_Close();
//等待三秒,再变为允许通行状态
if(Wait_cnt < 3000)
Wait_cnt++;
else
{
Wait_cnt = 0;
state = PASS_STATE;
}
}
}
//线程1,led1的闪烁
void task1(void)
{
//判断标志位
if(Led1_task_flag == 1)
{
//标志位清零,便于下次闪烁
Led1_task_flag = 0;
//led1对应的io口电平翻转,实现闪烁
Led1_Toggle();
return;
}
}
//线程2,led2的闪烁
void task2(void)
{
if(Led2_task_flag == 1)
{
Led2_task_flag = 0;
Led2_Toggle();
return;
}
}
//线程3,红外传感判断
void Sensor_task(void)
{
//如果检测到有人经过,红外传感器收到有人,1表示传感器感应到有人通过,0表示没有
if(Sensor_State == 1)
{
//计数加一
Number++;
//LCD1602显示状态
LCD1602_Showstring(1, 1, 'passing');
}
//如果超过5
if(Number > 5)
{
//计数清零
Number = 0;
//不允许通过
state == WAIT_STATE;
//显示状态
LCD1602_Showstring(1, 1, 'waiting');
}
}
那么我们在主函数中,只要不断调用这三个模拟的线程就实现这智能排队控制系统的功能啦
#include "sys.h"
#include "delay.h"
#include "Tasks.h"
#include "Exit.h"
#include "Sensor.h"
int main(void)
{
HAL_Init();
stm32_clock_init(RCC_PLL_MUL9);
Led_Init();
Beep_Init();
LCD1602_Init();
Sensor_Init();
Exit_Init();
while(1)
{
//不断调用这个三个线程
task1();
task2();
Sensor_task();
}
}
代码不全,其他模块的大家也可以找我要(主要是自己懒)
剩下的就是其他模块的初始化和配置了,相信各位强大的点灯大师是没有问题的,像
Led,蜂鸣器,这三个主要是配置端口的输出输入电平高低就可以了;
继电器,红外传感模块,可以去查找一下资料了解一下原理,重点也是端口电平高低;
LCD1602的配置,对于没接触过的小白来说可能有点不知道怎么配置,最简单的方法就是直接网上找资料,拿过来改改端口就可以了,里面的时序图啊什么的看不懂也可以来问我。(不一定教的会,嘿嘿)
写的不是很好,这也是记录一下自己的一个项目学习过程,项目有点简单,里面哪些内容不好的,有更好建议的欢迎大家指教。