智能排队控制系统
1. 模块介绍
1.1 红外传感器【红外跟随避障模块】
📌注意:如果接收到信号,OUT引脚输出低电平,亮绿灯。【与震动传感器相似】
如果未接收到信号,OUT引脚一直高电平。
顺时针旋转,灵敏度变高,检测距离变长;逆时针,灵敏度变低,检测距离变短。
驱动代码:与【震动传感器】代码一样
1.2 LCD1602显示模块
一种常见的字符型液晶显示模块。
它能够显示16列2行,共32个字符,每个字符由5*8像素点阵构成,是一种专门用来显示字母、数字、符号等的液晶显示模块。
1.2.1 引脚介绍
引脚不能接错,否则可能会烧掉板子。
RS:1——数据寄存器;0——指令寄存器
R/W: 1——读;0——写
1.2.2 基本操作时序
读操作时序:
写操作时序:
1.2.3 LCD1602显示字符串
小实验:驱动LCD1602显示内容
实验目的:
- 使用LCD1602显示一个字符;
- 使用LCD1602显示一个字符串。
硬件清单:
- LCD1602
- 上官二号
- ST-Link
硬件接线
| STM32 | LCD1602 |
|---|---|
| GND | GND |
| 5V | VDD |
| GND | V0 |
| B1 | RS |
| B2 | RW |
| B10 | E |
| A0 | D0 |
| A1 | D1 |
| A2 | D2 |
| A3 | D3 |
| A4 | D4 |
| A5 | D5 |
| A6 | D6 |
| A7 | D7 |
| 3.3 | BLA |
| GND | BLK |
代码:
写代码前,要知道两个问题:
- 在哪里显示字符
- LCD知道显示什么内容
用下面这个知道在什么地方显示内容。
写指令代码:
lcd1602.c文件
#include"lcd1602.h"#include"delay.h"// RS引脚定义#defineRS_GPIO_PortGPIOB#defineRS_GPIO_PinGPIO_PIN_1#defineRS_HIGHHAL_GPIO_WritePin(RS_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_SET);#defineRS_LOWHAL_GPIO_WritePin(RS_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_RESET);// RW引脚定义#defineRW_GPIO_PortGPIOB#defineRW_GPIO_PinGPIO_PIN_2#defineRW_HIGHHAL_GPIO_WritePin(RW_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_SET);#defineRW_LOWHAL_GPIO_WritePin(RW_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_RESET);// EN引脚定义#defineEN_GPIO_PortGPIOB#defineEN_GPIO_PinGPIO_PIN_10#defineEN_HIGHHAL_GPIO_WritePin(EN_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_SET);#defineEN_LOWHAL_GPIO_WritePin(EN_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_RESET);voidlcd1602_init(void){// GPIO初始化lcd1602_gpio_init();// 上电初始化lcd1602_start();}// GPIO初始化voidlcd1602_gpio_init(void){GPIO_InitTypeDef gpio_initstruct;// 打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();// 使能GPIOA时钟__HAL_RCC_GPIOB_CLK_ENABLE();// 使能GPIOB时钟gpio_initstruct.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;// 对应的引脚gpio_initstruct.Mode=GPIO_MODE_OUTPUT_PP;// 推挽输出gpio_initstruct.Pull=GPIO_PULLUP;// 上拉gpio_initstruct.Speed=GPIO_SPEED_FREQ_HIGH;// 高速HAL_GPIO_Init(GPIOA,&gpio_initstruct);gpio_initstruct.Pin=GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10;// LED1对应的引脚gpio_initstruct.Mode=GPIO_MODE_OUTPUT_PP;// 推挽输出gpio_initstruct.Pull=GPIO_PULLUP;// 上拉gpio_initstruct.Speed=GPIO_SPEED_FREQ_HIGH;// 高速HAL_GPIO_Init(GPIOB,&gpio_initstruct);}// 上电初始化voidlcd1602_start(void){//(1)延时15msdelay_ms(15);//(2)写指令38H(不检测忙信号)lcd1602_write_cmd(0x38);//(3)延时5msdelay_ms(5);//(4)不检测忙信号//(5)写指令38H:显示模式设置lcd1602_write_cmd(0x38);//(6)写指令08H:显示关闭lcd1602_write_cmd(0x08);//(7)写指令01H:显示清屏lcd1602_write_cmd(0x01);//(8)写指令06H:显示光标移动设置lcd1602_write_cmd(0x06);//(9)写指令0CH:显示开及光标设置lcd1602_write_cmd(0x0C);}// 指令voidlcd1602_write_cmd(charcmd){RS_LOW;RW_LOW;EN_LOW;GPIOA->ODR=cmd;delay_ms(5);EN_HIGH;delay_ms(5);EN_LOW;}// 数据voidlcd1602_write_data(chardataShow){RS_HIGH;RW_LOW;EN_LOW;GPIOA->ODR=dataShow;delay_ms(5);EN_HIGH;delay_ms(5);EN_LOW;}// 显示一个字符voidlcd1602_show_data(void){// 在什么地方显示lcd1602_write_cmd(0x80+0x02);// 显示什么内容lcd1602_write_data('Z');}// 显示字符串voidlcd1602_show_line(charrow,charcol,char*string){switch(row){case1:lcd1602_write_cmd(0x80+col);while(*string){lcd1602_write_data(*string);string++;}break;case2:lcd1602_write_cmd(0x80+0x40+col);while(*string){lcd1602_write_data(*string);string++;}break;}}main.c中不要忘记调用lcd1602_show_line(char row, char col, char *string);
2. 智能排队控制系统
项目需求
- 红外传感器检测有人通过并计数
- 计数值显示在LCD1602
- 允许通过时,LED1闪烁,蜂鸣器不响,继电器不闭合;
- 不允许通过时,LED2闪烁,蜂鸣器响,继电器闭合。
- 每次允许通过5个人,之后转为不允许通过,3秒后再转为允许通过
硬件清单
- 继电器(模拟闸机)
- 蜂鸣器
- 红外避障模块
- LCD1602
- 上官二号
- ST-Link
硬件接线
| STM32 | LCD1602 | 继电器 | 蜂鸣器 | 红外 |
|---|---|---|---|---|
| GND | GND | |||
| 5V | VDD | |||
| GND | V0 | |||
| B1 | RS | |||
| B2 | RW | |||
| B10 | E | |||
| A0 | D0 | |||
| A1 | D1 | |||
| A2 | D2 | |||
| A3 | D3 | |||
| A4 | D4 | |||
| A5 | D5 | |||
| A6 | D6 | |||
| A7 | D7 | |||
| 3.3 | BLA | VCC | VCC | VCC |
| GND | BLK | GND | GND | GND |
| B4 | OUT | |||
| B5 | I/O | |||
| B6 | IN |
项目框图
2.1 搭建项目工程
基于SysTick模拟多线程实验上写
将之前所做的实验加进来:红外、LCD1602、继电器、蜂鸣器、LED。
分别调试这几个模块代码,验证硬件没问题,再进行下一步。
2.1.1 状态机
状态机(State Machine)是一种用于描述系统行为或功能行为的数学模型。它通常包含一组状态、一组转换条件以及动作执行。状态机通过在不同状态之间进行转换来模拟系统的行为。每个状态都代表系统的一个特定配置或情况,而转换规则则定义了从一个状态转换到另一个状态的条件和动作。
状态机广泛应用于多个领域包括但不限于计算机科学、电子工程、通信、自动化、机器人技术等。在计算机科学中,状态机常用于描述软件系统的行为,特别是在硬件设计、编译器设计、网络协议以及用户界面交互等方面。
状态机的主要特点包括:
- 有限状态:状态机通常具有有限数量的状态。这些状态可以是有序的、离散的或层次化的。
- 转换条件:状态之间的转换是基于特定条件触发的。当满足某个条件时,状态机会从当前状态转换到下一个状态。
- 动作执行:在状态转换过程中,状态机可能会执行某些动作或操作。这些动作可以包括计算、数据更新、输出信号等。
- 确定性和非确定性:状态机可以是确定性的(每个条件唯一对应一个转换)或非确定性(一个条件可能导致多个可能得转换)。
状态机的实现方式多种多样,可以使用编程语言中的条件语句、循环结构或专门的状态机库来实现。此外,硬件设计领域中的有限状态机(Finite State Machine,FSM)也是状态机的一种重要应用。
该项目的状态:
2.1.2 业务代码
状态代码写在tasks.c中
问题1:未检测到传感器,直接就通过。
解决:在传感器检测是否有人通过时,写成了用gate_state_get来获取了,应该是用红外传感器ia_flag_get函数检测是否有人通过。ia_flag_get() == TRUE && state == PASS_STATE。
问题2:当检测有人通过时,LCD并没有计数加1。
在中断函数中,设置的下降沿触发和GPIO_PIN_RESET 低电平触发
gpio_initstruct.Mode=GPIO_MODE_IT_FALLING;// 下降沿触发voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){// 消抖delay_ms(20);if(GPIO_Pin==GPIO_PIN_4){if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4)==GPIO_PIN_RESET)ia_flag=TRUE;}}但是,出现一个问题,传感器靠近和离开都加了一个人,说明传感器在靠近时也产生了一个短暂的下降沿,被误识别为一次有效信号。
解决:
HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET
引脚是B4,之前写成了A4。
总结:学会把项目步骤进行拆解,写业务代码前,一定要先把硬件设备连线并调试好,再接着写业务代码。
红外传感器【检测人数】→继电器【闸机】→蜂鸣器→LED1和LED2→LCD1602【显示通过人数】