红外遥控门禁系统设计(C语言实现)
一、系统概述
基于STM32F103C8T6微控制器,通过红外遥控(NEC协议) 实现门禁控制,支持用户身份验证、门锁驱动、状态显示、非法入侵报警功能。系统采用低功耗设计,支持多用户管理(存储10组合法红外编码),适用于家庭、办公室、小型仓库等场景,具备易用性、高可靠性、低成本特点。
二、系统架构与硬件设计
1. 系统架构
graph TD
A[红外遥控器] -->|NEC协议红外信号| B[红外接收头 HS0038]
B -->|解码后编码| C[STM32F103C8T6主控]
C -->|GPIO| D[电磁锁 12V]
C -->|GPIO| E[蜂鸣器 报警]
C -->|I2C| F[OLED显示 128×64]
C -->|I2C| G[EEPROM AT24C02, 存储合法编码]
H[电源 12V转3.3V] -->|供电| C
H -->|供电| D
H -->|供电| E
H -->|供电| F
H -->|供电| G
2. 关键硬件组件
| 模块 | 型号/参数 | 功能 |
|---|---|---|
| 主控 | STM32F103C8T6(72MHz,64KB Flash,20KB RAM) | 红外解码、身份验证、门锁控制、状态管理 |
| 红外接收 | HS0038(38kHz,NEC协议) | 接收红外遥控信号,输出解调后脉冲 |
| 门锁驱动 | 电磁锁(12V/200mA)+ 继电器(5V) | 控制门锁开关(吸合=开门,释放=关门) |
| 显示 | 0.96寸OLED(I2C,SSD1306) | 显示门禁状态、用户ID、时间 |
| 存储 | AT24C02(I2C,2KB EEPROM) | 存储10组合法红外编码(用户ID+键值) |
| 报警 | 有源蜂鸣器(5V)+ 红色LED | 非法入侵时声光报警 |
| 电源 | 12V/2A适配器 + LM2596(12V→5V/3.3V) | 系统供电(电磁锁12V,其他3.3V) |
3. 核心电路设计
(1)红外接收电路
- HS0038连接:OUT引脚接STM32的PA0(外部中断0,下降沿触发),VCC接3.3V,GND接地,需加104瓷片电容滤波。
- NEC协议时序:引导码(9ms低+4.5ms高)+ 32位数据(地址码16位+命令码16位,含反码校验)。
(2)门锁驱动电路
- 继电器控制:STM32的PB0接继电器线圈(5V),线圈两端并联1N4148续流二极管,继电器触点接电磁锁(12V),通过三极管(S8050)驱动(基极串1kΩ电阻)。
(3)存储电路
- AT24C02连接:SCL接PB6(I2C1_SCL),SDA接PB7(I2C1_SDA),VCC接3.3V,A0-A2接地(地址0x50)。
三、软件设计(C语言实现)
1. 开发环境
- IDE:STM32CubeIDE(V1.13.0)
- 库:STM32 HAL库(V1.11.0)、I2C EEPROM驱动(AT24C02)、OLED驱动(SSD1306)
- 协议:NEC红外解码(外部中断+定时器计时)
2. 主程序流程
#include "stm32f1xx_hal.h"
#include "ir_receiver.h"
#include "eeprom.h"
#include "oled.h"
#include "lock_control.h"
#include "alarm.h"
// 系统状态
typedef struct {
uint8_t valid_user; // 合法用户标志
uint8_t user_id; // 用户ID(0-9)
uint8_t key_value; // 按键值(0-255)
uint8_t door_status; // 0:关, 1:开
} SystemState;
int main(void) {
// 1. 初始化硬件
HAL_Init();
SystemClock_Config(); // 72MHz主频
IR_Receiver_Init(); // 红外接收初始化(PA0,外部中断0)
EEPROM_Init(); // I2C EEPROM初始化(AT24C02)
OLED_Init(); // OLED显示初始化
Lock_Init(); // 门锁控制初始化(PB0,继电器)
Alarm_Init(); // 报警模块初始化(蜂鸣器+LED)
SystemState sys_state = {0};
OLED_ShowString(0, 0, "Door Access System");
OLED_Update();
// 2. 主循环
while (1) {
if (ir_received_flag) { // 红外信号接收完成
// 2.1 解码红外信号(NEC协议)
IR_Decode(&sys_state.user_id, &sys_state.key_value);
ir_received_flag = 0;
// 2.2 验证用户合法性(查EEPROM)
sys_state.valid_user = EEPROM_VerifyUser(sys_state.user_id, sys_state.key_value);
// 2.3 控制门锁与状态显示
if (sys_state.valid_user) {
OLED_ShowString(0, 2, "Valid User: ");
OLED_ShowNum(12, 2, sys_state.user_id, 1);
Lock_Open(5000); // 开门5秒
OLED_ShowString(0, 4, "Door Opened");
} else {
OLED_ShowString(0, 2, "Invalid User!");
Alarm_Trigger(1000); // 报警1秒
}
OLED_Update();
}
HAL_Delay(10); // 主循环延时
}
}
3. 关键模块实现
(1)红外接收与NEC解码(C语言)
通过外部中断+定时器捕获红外信号,解码NEC协议:
// 红外接收相关变量
volatile uint32_t ir_last_time = 0; // 上次下降沿时间
volatile uint8_t ir_bit_count = 0; // 数据位计数
volatile uint32_t ir_data = 0; // 解码数据(32位)
volatile uint8_t ir_received_flag = 0; // 接收完成标志
// 外部中断0服务函数(PA0,红外接收OUT)
void EXTI0_IRQHandler(void) {
if (EXTI->PR & EXTI_PR_PR0) {
uint32_t current_time = HAL_GetTick();
uint32_t pulse_width = current_time - ir_last_time;
ir_last_time = current_time;
// 下降沿触发,判断脉冲宽度(NEC协议)
if (pulse_width > 13500 && pulse_width < 14500) { // 9ms低电平(引导码)
ir_bit_count = 0;
ir_data = 0;
} else if (pulse_width > 2000 && pulse_width < 3000) { // 560us低+1.68ms高(数据1)
ir_data |= (1 << ir_bit_count);
ir_bit_count++;
} else if (pulse_width > 1000 && pulse_width < 2000) { // 560us低+560us高(数据0)
ir_bit_count++;
}
// 32位数据接收完成(地址16位+命令16位)
if (ir_bit_count >= 32) {
ir_received_flag = 1;
}
EXTI->PR |= EXTI_PR_PR0; // 清除中断标志
}
}
// NEC解码(提取用户ID和键值)
void IR_Decode(uint8_t* user_id, uint8_t* key_value) {
// 32位数据格式:地址码H(8) + 地址码L(8) + 命令码H(8) + 命令码L(8)
*user_id = (ir_data >> 24) & 0xFF; // 地址码作为用户ID
*key_value = (ir_data >> 8) & 0xFF; // 命令码作为按键值
ir_data = 0; // 清除数据
}
(2)EEPROM用户验证(C语言)
存储10组合法用户编码(用户ID+键值),验证接收的编码是否合法:
// EEPROM存储结构(10组用户,每组2字节:ID+键值)
#define USER_NUM 10
#define EEPROM_USER_BASE 0x00 // 存储起始地址
// 验证用户合法性(返回1:合法,0:非法)
uint8_t EEPROM_VerifyUser(uint8_t user_id, uint8_t key_value) {
uint8_t stored_id, stored_key;
for (int i=0; i<USER_NUM; i++) {
// 从EEPROM读取用户ID和键值
EEPROM_Read(EEPROM_USER_BASE + i*2, &stored_id, 1);
EEPROM_Read(EEPROM_USER_BASE + i*2 + 1, &stored_key, 1);
if (stored_id == user_id && stored_key == key_value) {
return 1; // 找到合法用户
}
}
return 0; // 无合法用户
}
// EEPROM读函数(I2C)
void EEPROM_Read(uint16_t addr, uint8_t* data, uint8_t len) {
HAL_I2C_Mem_Read(&hi2c1, 0xA0, addr, I2C_MEMADD_SIZE_8BIT, data, len, 100);
}
// EEPROM写函数(I2C)
void EEPROM_Write(uint16_t addr, uint8_t* data, uint8_t len) {
HAL_I2C_Mem_Write(&hi2c1, 0xA0, addr, I2C_MEMADD_SIZE_8BIT, data, len, 100);
HAL_Delay(5); // 等待EEPROM写入完成
}
(3)门锁控制与报警(C语言)
通过继电器控制电磁锁,非法入侵时触发声光报警:
// 门锁控制(开门时间ms)
void Lock_Open(uint32_t open_time) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // 继电器吸合(开门)
sys_state.door_status = 1;
HAL_Delay(open_time);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // 继电器释放(关门)
sys_state.door_status = 0;
}
// 报警触发(持续时间ms)
void Alarm_Trigger(uint32_t duration) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // 蜂鸣器响+LED亮
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_Delay(duration);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); // 关闭报警
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
}
参考代码 红外遥控的门禁系统设计 www.youwenfan.com/contentcss/160984.html
四、系统测试与优化
1. 测试指标
| 参数 | 指标 | 测试方法 |
|---|---|---|
| 红外解码成功率 | ≥99%(2米内) | 用不同遥控器发送信号,统计解码正确率 |
| 用户验证时间 | <100ms | 从接收信号到开门的延迟 |
| 门锁驱动能力 | 12V/200mA电磁锁正常吸合 | 用万用表测量继电器触点电压 |
| 存储容量 | 10组用户编码(永久保存) | 写入10组编码后断电重启,验证读取正确性 |
2. 优化方向
- 抗干扰:红外接收头加金属屏蔽罩,软件增加重发码处理(NEC协议重发码为9ms低+2.25ms高);
- 低功耗:待机时STM32进入Stop模式(电流<10μA),通过红外信号中断唤醒;
- 多用户管理:添加按键设置(如通过矩阵键盘添加/删除用户),动态更新EEPROM;
- 远程控制:集成Wi-Fi模块(ESP8266),通过手机APP远程授权临时用户。
五、总结
本设计基于STM32实现了红外遥控门禁系统,通过NEC协议解码、EEPROM用户验证、继电器驱动门锁,完成了身份验证与门禁控制功能。