红外遥控门禁系统设计

红外遥控门禁系统设计(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)红外接收电路

(2)门锁驱动电路

(3)存储电路

三、软件设计(C语言实现)

1. 开发环境

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. 优化方向

五、总结

本设计基于STM32实现了红外遥控门禁系统,通过NEC协议解码、EEPROM用户验证、继电器驱动门锁,完成了身份验证与门禁控制功能。

专注于matlab/simulink,电子电路,编程