一、项目需求
-
红外传感器检测有人通过并计数;
-
计数值显示在LCD1602
-
允许通过时,LED1闪烁,蜂鸣器不响,继电器不闭合;
-
不允许通过时,LED2闪烁,蜂鸣器响,继电器闭合;
-
每次允许通过5个人,之后转为不允许通过,3秒后再转为允许通过
二、硬件清单
继电器(模拟匣机)
蜂鸣器
红外避障模块
LCD1602
上官二号
ST-Link
三、硬件接线
四、项目框图
五、项目搭建
复制项目文件夹12-SysTick模拟多线程流水灯,重命名为15-排队系统项目架构搭建
打开项目,加载以上文件
挨个在main函数中调用一下,看看是否可以正常执行出结果,单个试验
六、项目完结
复制项目文件夹15-排队系统项目架构搭建,重命名为16-排队系统项目完结
sprintf
sprintf指的是字符串格式化命令.
函数声明为 int sprintf(char *string, char *format [,argument,...]);,
主要功能是把格式化的数据写入某个字符串中,即发送格式化输出到 string 所指向的字符串。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。解决这个问题,可以考虑使用 snprintf函数,该函数可对写入字符数做出限制。
这里使用sprintf的连接字符串功能
sprintf 的格式控制串中既然可以插入各种东西,并最终把它们"连成一串",自然也就能够连接字符串,从而在许多场合可以替代strcat,但sprintf 能够一次连接多个字符串(自然也可以同时在它们中间插入别的内容,总之非常灵活)。比如:
char buf[60]={0};
char*who="I";
char*whom="CSDN";
sprintf(buf,"%slove%s.",who,whom);
printf("%s",buf);
//输出结果:"IloveCSDN."
uint32_t passenger = 0;//用于计数char message[16] = {0};
//计数加1
passenger++;
//LCD显示状态
sprintf(message,"PASS...%02d/05",passenger);
//%02d:这里的02中的0是补位0(在LCD中显示出来的0),2是取两位;
由上面组合而成:PASS...00/05,存放在message字符串数组中
lcd1602_show_line(1,1,message);
展现在上面LCD1602的显示屏上,再每一次passager数目加1之后,sprintf都会重新组合字符串,然后执行lcd1602的显示代码,显示再屏幕上。
代码:
main.c
cpp
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "tasks.h"
#include "gate.h"
#include "beep.h"
#include "exti.h"
#include "LCD1602.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
gate_init();
beep_init();
exti_init();
lcd1602_init();
lcd1602_show_line(1, 1, "PASS...");
while(1)
{
//一直在while循环中不断的重复执行task()函数
//task()函数只有在满足对应条件的时候才会点灯,否则不点灯,白执行
led1_task1();
led2_task2();
sensor_task();
}
}
tasks.c
cpp
#include "tasks.h"
#include "led.h"
#include "beep.h"
#include "exti.h"
#include "LCD1602.h"
#include "gate.h"
#include "stdio.h"
#include "delay.h"
//使用枚举的方式把状态的两种情况列举出来,允许通行,不允许通行
enum
{
PASS_STATE,
WAIT_STATE
};
uint32_t led1_task1_cnt = 0; //定义一个变量用来计数
uint32_t led2_task2_cnt = 0; //定义一个变量用来计数
uint32_t wait_cnt = 0; //计数器
uint32_t passenger = 0;
uint8_t led1_task1_flag = 0;
uint8_t led2_task2_flag = 0;
uint8_t state = PASS_STATE;//默认是通行状态
char message[16] = {0};
//SysTick回调函数
void sysTick_isr(void)
{
//如果处于允许通行的状态
if(state == PASS_STATE)
{
// LED1以1秒的频率闪烁
if(led1_task1_cnt <1000)
led1_task1_cnt++;
else
{
led1_task1_flag = 1;
led1_task1_cnt = 0;
}
// LED2不闪烁
led2_off();
// 蜂鸣器不响
beep_off();
// 开门
gate_off();
}
//如果处于不允许通行的状态
else if(state == WAIT_STATE)
{
// LED1不闪
led1_off();
// LED2以200ms的频率闪烁
if(led2_task2_cnt <200)
led2_task2_cnt++;
else
{
led2_task2_flag = 1;
led2_task2_cnt = 0;
}
// 蜂鸣器响
beep_on();
// 关门
gate_on();
// 计时3秒,之后
if(wait_cnt < 3000)
wait_cnt++;
else
{
wait_cnt=0;
//进入允许通行状态
state = PASS_STATE;
//LCD显示状态
lcd1602_show_line(1,1,"PASS...");
}
}
}
void led1_task1(void)
{
if(led1_task1_flag == 0)
return;
led1_task1_flag = 0;//置位
led1_toggle();
}
void led2_task2(void)
{
if(led2_task2_flag == 0)
return;
led2_task2_flag = 0;
led2_toggle();
}
void sensor_task(void)
{
//如果检测到有人通过
if(ia_flag_get() == TRUE && state == PASS_STATE)
{
//计数加1
passenger++;
//LCD显示状态
sprintf(message,"PASS...%02d/05",passenger);//%02d/05:这里的02中的0是补位0,2是取两位;/05中的05是固定的
lcd1602_show_line(1,1,message);
//如果通过的人数超过五个人
}
if(passenger >= 5)
{
//计数清零
passenger = 0;
//进入不允许通行状态
state = WAIT_STATE;
//LCD显示状态
lcd1602_show_line(1,1,"WAIT...00/05");
}
}