基于STM32的智能防疫门禁系统设计
一、引言
新冠疫情的全球蔓延对公共卫生和社会管理带来了巨大挑战。为了有效控制疫情传播,各种智能防疫措施应运而生。其中,智能门禁系统因其高效、便捷的特点,在各类公共场所如办公楼、学校、医院等得到了广泛应用。这些系统不仅能够实现无接触测温,还能记录人员进出信息,为疫情防控提供数据支持。
STM32F103C8T6是一款高性能、低功耗的32位ARM Cortex-M3微控制器,具有丰富的外设资源和灵活的编程环境,非常适合用于开发复杂的嵌入式系统。本项目旨在利用STM32F103C8T6为核心控制器,设计并实现一款智能防疫门禁系统,以提高公共场所的安全性和管理效率。
二、系统总体设计
设计中用到的指定厂商元器件及介绍:
1.STM32F103C8T6来自ST公司主控芯片,一款基于ARM Cortex-M3内核的32位微控制器。
2.本项目的1K、10K等电阻来自 Rohm Semiconductor(罗姆ROHM)。
系统组成框图如下:
三、硬件设计
3.1 主控模块
STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,具有以下特点:
- **高性能**:最高工作频率72MHz,内置128KB Flash和20KB SRAM。
- **低功耗**:多种低功耗模式,适用于电池供电的应用。
- **丰富的外设**:包括USART、SPI、I2C、ADC、TIM等,满足多种通信和控制需求。
3.2 温度传感器
LU90614是一款红外测温模块,它采用红外热辐射测温原理,可以测量物体的温度并输出相应的温度值。该模块具有高精度、高稳定性、低功耗、易于集成等优点,适用于各种需要测量温度的场合。
LU90614模块的主要特点包括:
1. 高精度:测量范围为-50℃至80℃,精度可达±1℃。
2. 高稳定性:长期使用不易受环境温度变化和器件老化等因素的影响,具有较好的稳定性。
3. 低功耗:采用低功耗设计,适合在电池供电的设备中使用。
4. 易于集成:模块体积小巧,接口简单,易于集成到各种设备中。
5. 支持多种输出方式:支持模拟输出和数字输出两种方式,方便用户根据需求选择。
LU90614模块通常与微控制器或其他控制单元配合使用,通过采集红外传感器数据并进行分析处理,最终输出物体的温度值。该模块通常适用于需要非接触式温度测量的场合,如工业生产、医疗诊断、智能家居等。
在使用LU90614模块时,需要注意以下几点:
1. 确保设备的红外窗口干净、无遮挡,以保证测温准确。
2. 根据设备的要求和环境条件,合理设置微控制器的输入参数和输出方式。
3. 注意模块的工作电压和电流要求,确保设备供电稳定,以免影响模块的正常工作。
4. 定期对模块进行校准和维护,以保证其性能的稳定性和准确性。
3.3 显示模块
1.8寸TFT液晶显示屏的控制器是ST7735S 为 262 k 色, 图形型 TFT 液晶显示器。
TFT-LCD,全称Thin Film Transistor Liquid Crystal Display,即薄膜晶体管液晶显示器,是多数液晶显示器的一种,使用薄膜晶体管技术改善影象品质。它在液晶显示屏的每一个像素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD 也被叫做真彩液晶显示器。
以下是TFT-LCD显示屏模块的参数:
尺寸 | 1.8寸 |
模块电压 | DC:3.3V |
模块电流 | 30mA |
分辨率 | 128×160 |
驱动 | ST7735 |
管脚数 | 8针 |
接口 | 4线SPI接口 |
工作温度 | -20℃~70℃ |
采用1.8寸TFT液晶显示屏:
- 采用128x160点阵的TFT液晶屏。
- 通过SPI接口与STM32F103C8T6通信。
3.4 语音模块
JQ8900-16P选用的是SOC方案,集成了一个16位的MCU,以及一个专门针对音频解码的ADSP(ADSP(Audio Digital Signal Processing)解码器是指音频数字信号处理解码器,它通常用于处理音频数据,将其从压缩格式解码成原始音频数据,以便播放。ADSP 解码器可以是硬件实现的,也可以是软件实现的。),采用硬解码的方式,更加保证了系统的稳定性和音质。小巧尺寸更加满足嵌入其它产品的需求。
且模块内部含有一个FLASH存储器,用于对语音音频进行存储。
JQ8900语音模块:
- 采用JQ8900语音芯片,支持MP3和播放功能。
- 通过GPIO接口与STM32F103C8T6通信。
3.5 通信模块
ESP-01S是由安信可科技开发的一款Wi-Fi模块。其核心处理器是ESP8266,该处理器在较小尺寸的封装中集成了业界领先的Tensilica L106超低功耗32位微型MCU,带有16位精简模式,主频支持80MHz和160MHz,并集成了Wi-Fi MAC/BB/RF/PA/LNA。
ESP-01S具有多种特性和功能:
尺寸小巧,设计紧凑,适用于空间有限的应用。
支持标准的IEEE802.11 b/g/n协议和完整的TCP/IP协议栈,可以方便地与其他设备或网络进行通信。
可以通过路由器连接到互联网,使手机或电脑能够实现对设备的远程控制(STA模式)。
也可以作为热点,使其他设备能够连接到它(AP模式)。
提供了多个可编程的GPIO引脚,可以用于控制外部设备,如传感器和执行器等。
在硬件连接方面,ESP-01S模块需要与主控制器(如Arduino、STM32等)进行连接,通过串行UART接口与主控制器进行数据传输。同时,该模块通常工作在3.3V的电压下,建议使用2节干电池或经过LDO转换后的3.3V进行供电,而不应使用USB转TTL的3.3V或5V进行供电。
在软件方面,初始情况下,ESP-01S通常预装了Espressif提供的AT指令固件,这意味着可以通过发送简单的AT指令来控制模块的Wi-Fi连接和数据传输。此外,用户还可以根据需要进行固件烧录和配置,以满足特定的应用需求。
总的来说,ESP-01S是一款功能强大、易于使用的Wi-Fi模块,适用于各种物联网和智能家居应用,为设备添加联网功能或构建独立的网络控制器提供了方便和灵活的选择。
**Wi-Fi模块**:
- 采用ESP01S Wi-Fi模块,支持802.11 b/g/n协议。
- 通过UART接口与STM32F103C8T6通信。
3.6 电源管理模块
- 采用锂电池供电,配备充电电路。
- 通过DC-DC转换器提供稳定的3.3V电源。
- 通过ADC采集电池电压通过屏幕显示出来。
3.7 蜂鸣器报警模块
蜂鸣器是一种能够将电信号转换为声音信号的电子设备。它通常用于各种电子设备和仪器中,用于发出警告、提示或警报声。蜂鸣器的工作原理是通过电流的变化来产生声音。当电流通过蜂鸣器内部的振动片时,振动片会快速振动,进而产生声音。蜂鸣器的音量和音调的不同,主要取决于电流的强弱和振动片的振动频率.
有源蜂鸣器:内置了振荡器和放大器,可以直接从低电平的数字信号产生声音,将正负极接上直流电压即可持续发声,频率固定。
- 用于发出警报声音。
- 通过GPIO接口与STM32F103C8T6通信。
3.8 门禁开关模块
采用SG90舵机模块模拟门禁开关状态:
- 用于人员通行。
- 通过PWM接口与STM32F103C8T6通信。
四、软件设计
3.1 温度传感器
温度模块采用LU90416,测温模块通过串口输出测量数据, 通过STM32F103C8T6的USART1串口(PA11、PA12)读取测温数据。
主要配置一个串口收发即可实现体温的测量,串口的配置我就不写了,代码资料里面会有完整项目。
#include "sys.h"
#include "lu90614.h"
u8 WENDU_H,WENDU_L;
float TEMP;
void USART1_SendData(u8 data)
{
while((USART1->SR&0X40)==0);
USART1->DR = data;
}
#if EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记
u16 USART_RX_LEN=0;
u16 USART_STA=0;
void uart1_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(Res==0XFE)//接收到命令头
{
USART_STA=1;
USART_RX_LEN=0;
}
if(USART_STA)
{
USART_RX_BUF[USART_RX_LEN]=Res;
USART_RX_LEN++;
if(USART_RX_LEN>8)//接收8位数据接收完毕
{
USART_STA=0;
USART_RX_STA|=0x8000;//接收已完成
}
}
}
}
}
void LU90614_Init(void)
{
//发送体温模式指令 0XFA 0XC5 0XBF
USART1_SendData(0XFA);
USART1_SendData(0XC5);
USART1_SendData(0XBF);
}
//发送测温指令 0XFA 0XCA 0XC4
void LU90614_Send(void)
{
USART1_SendData(0XFA);
USART1_SendData(0XCA);
USART1_SendData(0XC4);
}
void LU90614_Read(void)
{
if(USART_RX_STA&0X8000)//接收到一次数据
{
WENDU_H=USART_RX_BUF[2];
WENDU_L=USART_RX_BUF[3]/10;
TEMP =USART_RX_BUF[2]+USART_RX_BUF[3]*0.01;
//WENDU_H=WENDU_H&0X00FF;
USART_RX_STA=0;//启动下次接收
}
}
3.2 显示模块
板子与1.8寸TFT彩屏用杜邦线连接:
板子GND-----彩屏GND
板子3V3-----彩屏VCC
板子PA1-----彩屏SCL
板子PA2-----彩屏SDA
板子PA6-----彩屏RES
板子PA3-----彩屏DC
板子PA4-----彩屏CS
板子PA5-----彩屏BL
1.8寸TFT LCD彩屏是128x160像素的分辨率,我们可以理解为:水平方向分布了128个像素点,垂直方向分布了160个像素点。我们在画点的时候坐标Y的取值为0-159,坐标X的取值为0-127。
下图红色箭头的方向就是坐标递增的方向。
//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//SCL=SCLK
#define LCD_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)
#define LCD_MOSI_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//SDA=MOSI
#define LCD_MOSI_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)
#define LCD_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_6)//RES
#define LCD_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_6)
#define LCD_DC_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_8)//DC
#define LCD_DC_Set() GPIO_SetBits(GPIOA,GPIO_Pin_8)
#define LCD_CS_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_4)//CS
#define LCD_CS_Set() GPIO_SetBits(GPIOA,GPIO_Pin_4)
#define LCD_BLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_1)//BLK
#define LCD_BLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_1)
3.3 语音模块
JQ8900语音模块的引脚功能:
VPP: 单线串口(就是接收脉冲信号的引进)
BUSY: 播放指示灯
RX: 接收段
TX: 发送段
DC-5V: 5v供电
SPK-: 扬声器负极
SPK+: 扬声器正极
IO1~IO7是触发输入口,对地触发,DAC为音频输出(这里我们没用到)。用USB把模块连接到电脑,就会有一个盘,把需要的音频放入其中就可以使用。如果想使用IO口对地触发的方式必须按5位数字进行命名,如00001、00002。模块有7个触发IO口,最多支持19段录音。当然,这几个IO口也可以通过配置文件改变每个IO口的作用。
这里我不是用串口触发方式,我是用对地触发方式。我的接线方式为 SPK-、 SPK+、IO1~IO7、 DC-5V、 GND。
void JQ8900_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能B口时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB
IO1=1; IO2=1;IO3=1;IO4=1;IO5=1;IO6=1;IO7=1;
}
void ON_1 (void)
{
IO1=0;
}
void OFF_1 (void)
{
IO1=1;
}
void ON_2 (void)
{
IO2=0;
}
void OFF_2 (void)
{
IO2=1;
}
3.4 通信模块
AT指令:
AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的其对所传输的数据包大小有定义:即对于AT指令的发送,除AT两个字符外,最多可以接收1056个字符的长度(包括最后的空字符)
每个AT命令行中只能包含一条AT指令;对于由终端设备主动向PC端报告的URC指示或者response 响应,也要求一行最多有一个,不允许上报的一行中有多条指示或者响应。AT指令以回车作为结尾,响应或上报以回车换行为结尾
初始配置和验证
ESP-01s出厂波特率正常是115200,
注意:AT指令,控制类都要加回车,数据传输时不加回车
通过STM32F103C8T6的USART2串口(PA2、PA3)与ESP01S进行通信,通过MQTT协议和机智云进行通信上传数据到机智云平台APP。
void uart2_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART2,GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//USART1_TX GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
//USART1_RX GPIOA.3初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART2, ENABLE); //使能串口2
}
void USART2_IRQHandler(void) //串口2中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART2); //读取接收到的数据
gizPutData(&Res,1);
}
}
3.5电源管理模块
采用锂电池供电,配备充电电路。可以脱机运行系统,方便便捷。利用ADC采集电池电压,配合电源电路配带的4个LED指示灯来提示是否需要充电。ADC的引脚为PA0。ADC是模拟到数字转换器(Analog-to-Digital Converter)缩写,主要用于将连续传输的模拟信号转换为数字信号,便于数字系统(如中央处理器CPU、微控制器MCU等)对传输信息进行快速处理和分析。
stm32的ADC转换有两种通道,规则通道和注入通道,注入通道可以抢占式地打断规则通道的采样,执行注入通道采样后,再执行之前的规则通道采样,和中断类似。本例只使用规则通道实现独立模式的中断采样,这里不再赘述两种通道区别。
stm32的ADC可以由外部事件触发(例如定时器捕获,EXTI线)和软件触发(即在配置相关寄存器时,直接开启采样)。
STM32的ADC在单次转换模式下,只执行一次转换,该模式可以通过ADC_CR2 寄存器的ADON 位(只适用于规则通道)启动,也可以通过外部触发启动(适用于规则通道和注入通道),这是CONT 位为0 。 以规则通道为例,一旦所选择的通道转换完成,转换结果将被存在ADC_DR 寄存器,EOC (转换结束)标志将被置位,如果设置了EOCIE ,则会产生中断。然后ADC将停止,直到下次启动。
#include "adc.h"
#include "delay.h"
uint16_t ADvalue;
float Voltage;
/*
*==============================================================================
*函数名称:ADC1_Init
*函数功能:初始化ADCx
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void ADC1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //6分频 分频之后ADCCLK = 72MHz / 6 = 12MHz
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//在AIN模式下 GPIO口是无效的 断开GPIO口防止输入输出对模拟电压造成干扰 AIN模式算是ADC的专属模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//选择规则组的输入通道
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
//目前只有PA0一个通道 使用的是非扫描模式 所以指定的通道就放在序列1的位置
//需要快的转换就选择小的参数 需要稳定的选择大参数 没要求则任选 此时采样时间为55.5个ADCCLK的周期
//如果需要在序列2的位置写入其他通道 那就复制代码把序列数递增 每多一个序列数递增+1 并指定想要的通道
//ADC_RegularChannelConfig(ADC1,ADC_Channel_0,2,ADC_SampleTime_55Cycles5);
//每个通道可以选择不一样的采样时间 修改最后一个参数即可
//初始化ADC
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//选择连续转换or单次转换 enable是连续模式 disable是单次模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
//外部触发转换选择 这里不适用外部触发 none 使用软件触发
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//选择工作在独立模式还是双ADC模式
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数目 指定在扫描模式下会用到几个通道
//这个参数在扫描模式下需要用 非扫描模式下整个列表只有第一个序列有效 写多少都没用
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
//扫描模式or非扫描模式 enable是扫描模式 disable是非扫描模式
ADC_Init(ADC1,&ADC_InitStructure);
//开启ADC的电源
ADC_Cmd(ADC1,ENABLE);
//这里ADC_Cmd函数放在校准函数前面是对的,up给的数据手册是2010年翻译的,是错误的
// 2017年的数据手册已更正,实际上正确的表述应该是:ADC上电后最少两个周期才能校准
ADC_ResetCalibration(ADC1); //复位校准
while(ADC_GetResetCalibrationStatus(ADC1) == SET); //获取复位校准状态
//加上while循环 如果没有校准完成就在while空循环里等待
//一旦标志位被硬件清0 这个空循环会自动跳出
ADC_StartCalibration(ADC1); //开始校准
while(ADC_GetCalibrationStatus(ADC1) == SET); //获取开始校准状态
//这部分函数在ADC初始化完成之后依次调用即可
}
uint16_t ADC_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发转换函数
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//第二个参数 规则组转换完成标志位
//具体配置时间计算:通道的采样周期是55.5 转换周期是固定的12.5 加在一起是68个周期
//前面配置的ADCCLK是72MHz的6分频 就是12MHz 12MHz进行68个周期才能转换完成
//最终的时间是 1/12M * 68 = 5.6us 所以这个while循环大约会等待5.6us
return ADC_GetConversionValue(ADC1); //返回值是ADC1的转换结果
}
void ADC_Read(void)
{
ADvalue = ADC_GetValue(); //启动等待读取一次性完成 返回值直接就是结果
/* 强制转换为浮点型 */
Voltage = (float)ADvalue / 4095 *3.3*2;
}
3.6蜂鸣器报警模块
采用有源蜂鸣器和NPN三极管组成蜂鸣器报警模块,通过控制PB0引脚高低电平来控制蜂鸣器的导通与关闭。
void BUZZER_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能B口时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB
BUZZER=0;
}
3.7 门禁开关模块
舵机的工作原理比较简单。舵机内部有一个基准电压,单片机产生的PWM信号通过信号线进入舵机,与舵机内部的基准电压作比较,获得电压差输出。电压差的正负输出到电机驱动芯片上,从而决定正反转。开始旋转的时候,舵机内部通过级联减速齿轮带动电位器旋转,使得电压差为零,电机停止转动。
引脚连接:
sg90有三个引脚,分别是红线(VCC),棕线(GND)和橙线(信号线)。通常使用5V供电,信号线接单片机引脚,用老来接收单片机发送的PWM。
控制方法:
控制sg90舵机旋转也比较简单,只需要给它输出PWM波,修改占空比就可以调整角度。sg90的控制一般需要一个20ms 左右的时基脉冲,脉冲的高电平部分一般在0.5ms~2.5ms。高电平持续时间与旋转角度的对应关系如下:
高电平持续时间/ms 舵机角度/°
0.5 0
1.0 45
1.5 90
2.0 135
2.5 180
要使用sg90,首先要配置定时器,产生PWM。关于定时器和PWM相关知识,可以看博主STM32速成笔记定时器篇,这里就不再做详细介绍了。上面说,控制sg90需要一个20ms左右的脉冲,也就是说PWM的周期为20ms左右。计算一下可以知道,配置定时器时,预分频系数设置为7199,自动重装载值设置为200。我们初始化TIM3的通道1来控制sg90。PWM引输出脚映射到PB8。初始化程序如下:
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM4);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
TIM_Cmd(TIM4, ENABLE);
}
初始化时,程序如下:
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM4, Compare);
}
void Sg90_Init(void)
{
PWM_Init();
Sg90_SetAngle(180);//门禁关
}
void Sg90_Init(void)
{
PWM_Init();
Sg90_SetAngle(180);//门禁关
}
void Sg90_SetAngle(float Angle)
{
PWM_SetCompare3(Angle / 180 * 2000 + 500);
}
void Sg90_Read(void)
{
if(ACSA==1)
{
Sg90_SetAngle(0);//门禁关
}
else
{
Sg90_SetAngle(180);//门禁关
}
}
五、系统测试与调试
5.1 测试方案
- 单元测试:
- 对每个模块进行单独测试,确保其功能正常。
- 使用示波器和逻辑分析仪检查信号波形和时序。
- 集成测试:
- 将各个模块连接在一起,进行整体测试。
- 模拟实际使用场景,测试系统的稳定性和可靠性。
- 性能测试:
- 测试系统的响应时间、温度测量精度等性能指标。
- 通过压力测试验证系统的最大负载能力。
5.2 调试方法
- 硬件调试:
- 使用示波器和逻辑分析仪检查硬件信号。
- 通过万用表和电源测试仪器检查电源电压和电流。
- 软件调:
- 使用Keil MDK开发环境进行代码调试。
- 通过串口调试助手查看调试信息。
- 使用J-Link调试器进行在线调试。
六、PCB与实物展示
6.1 PCB设计
本项目使用立创EDA进行PCB设计,该软件具有强大的电路设计功能,能够确保PCB设计的高质量和高可靠性。
- 主控模块:
- STM32F103C8T6微控制器放置在PCB中心位置,以便于与其他模块的连接。
- 电源输入和稳压电路靠近电源接口,减少电源线的长度,提高电源稳定性。
- 温度传感器:
- LU90614非接触红外温度传感器放置在PCB左侧边缘,方便安装在门禁系统的前端,确保传感器能够准确检测进入者的体温。
- USART接口的信号线尽量短,减少干扰。
- 蜂鸣器模块:
- 蜂鸣器放置在PCB的右上角区域,确保不干扰。
- GPIO接口的信号线尽量短,减少信号损失。
- 显示模块:
- LCD显示屏放置在PCB的前端,方便用户查看信息。
- SPI接口的信号线尽量短,减少信号干扰。
- 语音模块:
- ISD1820语音芯片放置在PCB的后端,远离其他高频信号源,减少噪声干扰。
- GPIO接口的信号线尽量短,减少信号损失。
- 通信模块:
- ESP8266 Wi-Fi模块放置在PCB的右上角区域,靠近天线接口,确保无线信号的传输质量。
- UART接口的信号线尽量短,减少信号干扰。
- 电源管理模块:
- 锂电池和充电电路放置在PCB的下角区域,靠近电源接口,减少电源线的长度,提高电源稳定性。
- DC-DC转换器放置在电源输入附近,确保输出电压的稳定性。
- 门禁开关模块:
- SG90舵机模块放置在PCB的右端,靠近天线接口,确保无线信号的传输质量。
- UART接口的信号线尽量短,减少信号干扰。
原理图展示:
PCB展示:
6.2 实物展示
七、结论与展望
7.1 结论
本项目成功设计并实现了一款基于STM32F103C8T6的智能防疫门禁系统。该系统集成了非接触式体温传感器、门禁开关、液晶显示屏、语音模块和Wi-Fi通信模块,实现了无接触测温、数据显示、语音提示和数据上传等功能。系统具有响应速度快、测量精度高、验证准确率高、数据传输可靠等特点,适用于各类公共场所的防疫管理。
7.2 展望
未来,我们将继续优化和改进系统,增加更多实用功能,提高系统的稳定性和安全性。同时,我们还将探索更多的应用场景,如智能家居、智慧社区等,为用户提供更加全面和智能的服务。希望通过我们的努力,能够为疫情防控和社会管理做出更大的贡献。