基于STM32F103C8T6的智能护眼台灯系统重构与深度设计报告
1. 执行摘要 (Executive Summary)
在当今物联网(IoT)与智能家居飞速发展的背景下,传统台灯仅作为照明工具的单一属性已无法满足用户日益增长的健康与交互需求。基于意法半导体(STMicroelectronics)STM32F103C8T6微控制器的高性能嵌入式系统,为构建具备环境感知、人体工学监测及高效人机交互的下一代智能照明终端提供了坚实的硬件基础。本报告旨在针对现有基于该平台的智能台灯设计(参考原始功能需求)中存在的逻辑单一、交互生硬及算法粗糙等问题,进行详尽的系统级重构与优化设计。
通过对STM32底层资源的深度挖掘,本设计引入了PID闭环照度控制算法 以解决传统自动调光的抖动与非线性问题;提出了基于PIR红外与超声波传感器的多模态融合存在检测算法 ,彻底解决了静态人体无法检测的行业痛点;并结合Gamma校正 与滞回比较(Hysteresis)逻辑,重塑了从视觉舒适度到坐姿矫正的全方位用户体验。最终输出的设计方案不仅是一份功能列表,更是一套集成了光电技术、控制理论与人因工程学的完整系统架构。
---
2. 现有设计局限性分析与重构策略 (Critique of Legacy Design)
在深入具体设计之前,必须对原始参考设计(如图所示)的功能逻辑进行批判性分析。原始设计虽然涵盖了基础的传感与控制,但在实际应用场景中存在显著的"体验断层"。
2.1 原始功能缺陷剖析
| 原始功能模块 | 现有逻辑缺陷 | 用户体验痛点 |
|---|---|---|
| 人体感应 | 仅依赖红外(PIR)传感器检测是否有人。 | PIR仅能检测移动的热源。当用户在台灯下静坐阅读或书写时,传感器会判定为"无人"并自动关灯,导致用户必须频繁挥手"复活"台灯,极度干扰注意力 1。 |
| 坐姿检测 | 超声波测距,过近(如<30cm)立即报警。 | 缺乏时间滤波 与行为容错。用户短暂低头捡笔或调整姿势都会触发蜂鸣器尖叫,造成惊吓与烦躁,最终导致用户关闭该功能 3。 |
| 亮度调节 | 简单的低/中/高三档自动调节。 | 阶梯效应明显,光线突变刺激瞳孔。且缺乏对环境光微小变化的平滑补偿,无法维持桌面的恒定照度 5。 |
| 交互界面 | 按键复用复杂,OLED显示信息单一。 | 缺乏层级化菜单,所有参数(如定时时长、感应阈值)通常写死在代码中,用户无法根据自身习惯调整。 |
| 报警机制 | 蜂鸣器直接报警。 | 入侵式强干扰。在安静的学习环境中,突兀的声音是注意力的最大杀手。 |
2.2 重构核心策略
针对上述问题,本设计提出以下核心改进策略:
- 传感器融合(Sensor Fusion): 结合PIR的动态捕捉能力与超声波的静态测距能力,构建"存在检测"而非单纯的"运动检测"逻辑 7。
- 控制算法升级: 从简单的阈值判断升级为PID闭环控制 ,实现无级、恒定照度的自动调光;引入Gamma 2.2校正曲线,使亮度变化符合人眼感知的线性规律 9。
- 柔性交互设计: 引入**软启动/软停止(Soft-Start/Stop)**机制,消除开关灯的视觉冲击;将坐姿报警升级为"视觉呼吸提醒+柔和声响"的多级干预机制 11。
- 系统级状态机: 构建分层有限状态机(FSM)管理OLED菜单与蓝牙指令,确保系统在高负载下依然响应流畅 12。
---
3. 硬件架构深度解析 (Hardware Architecture)
STM32F103C8T6作为基于ARM Cortex-M3内核的32位微控制器,拥有72MHz的主频与丰富的外设资源,是实现复杂算法的理想载体。本节将详述各硬件模块的电气特性与资源分配。
3.1 微控制器资源分配图谱
为了实现多任务并发处理(如在生成高频PWM的同时扫描按键并刷新屏幕),必须对MCU的定时器(TIM)、中断(NVIC)与DMA通道进行严格规划。
| 硬件外设 | 接口类型 | STM32资源映射 | 配置参数与设计理由 |
|---|---|---|---|
| PWM调光灯 | GPIO / Timer | TIM3_CH1 (PA6) | 频率 > 20kHz。高频PWM可消除人眼无法察觉但在摄像头下可见的频闪,同时避免电感啸叫声。利用TIM3的16位分辨率实现细腻的亮度级数(0-65535)11。 |
| OLED显示屏 | I2C总线 | I2C1 (PB6/PB7) | 开启DMA传输。OLED刷新涉及大量数据(128x64位),使用DMA可在后台传输显存数据,避免CPU在刷新屏幕时阻塞,导致按键检测失灵或传感器数据丢失 15。 |
| 超声波 (HC-SR04) | 捕获/触发 | TIM2_CH1/2 (PA0/PA1) | 使用**输入捕获(Input Capture)**功能。通过硬件直接记录回波信号(Echo)的上升沿与下降沿时刻,精确计算脉宽至微秒级,精度远超软件轮询方式 16。 |
| 光敏电阻 (LDR) | ADC输入 | ADC1_IN4 (PA4) | 配合DMA循环采样 与均值滤波。LDR为高阻抗器件,易受电源噪声影响,DMA自动搬运ADC数据至内存缓冲区,软件端仅需读取平均值即可 17。 |
| 蓝牙 (HC-05) | UART通信 | USART1 (PA9/PA10) | 配置波特率9600或115200。启用接收中断(RXNE),配合环形缓冲区(Ring Buffer)处理不定长数据包,防止丢包 2。 |
| PIR红外 (HC-SR501) | 数字输入 | PB1 (外部中断EXTI) | 配置为双边沿触发。利用中断唤醒处于低功耗模式的MCU,实现"人来即醒"的节能逻辑 1。 |
| 按键 (x4) | GPIO输入 | PB12-PB15 | 采用**定时器轮询(10ms)**而非外部中断。软件消抖算法能更准确地识别短按、长按与双击操作,避免机械触点抖动造成的误触发 12。 |
| 有源蜂鸣器 | GPIO / PWM | TIM4_CH3 (PB8) | 虽然是有源蜂鸣器,但通过PWM调制供电,可以实现音量调节及简单的"呼吸音"效果,避免单一刺耳的"滴"声。 |
3.2 传感器物理特性与信号调理
3.2.1 光敏电阻的线性化与迟滞 光敏电阻的阻值与光照度呈非线性反比关系(![][image1])。为了在PID控制中获得线性反馈,软件层需通过对数变换将ADC值映射为近似的Lux值。此外,为了防止在临界光照度下台灯反复开关,必须在自动开关灯逻辑中引入**施密特触发器(Schmidt Trigger)**式的迟滞区间(例如:<50 Lux开灯,>150 Lux关灯)18。
3.2.2 超声波传感器的盲区与干扰 HC-SR04存在2cm左右的物理盲区以及硬表面反射造成的"多径效应"。重构设计中,通过软件算法剔除异常极值(如突然跳变到400cm),并采用**中值滤波(Median Filter)**处理连续5次采样数据,确保测距数值的稳定性,这是实现精准坐姿检测的前提 19。
---
4. 核心控制算法与逻辑设计 (Advanced Algorithms)
智能台灯的"智能"核心在于算法。本设计摒弃了简单的 if-else 逻辑,引入了工业控制领域成熟的算法模型。
4.1 光照度控制:PID算法与Gamma校正
4.1.1 Gamma校正:视觉舒适度的关键
人眼对亮度的感知遵循韦伯-费希纳定律(Weber-Fechner Law),即对数敏感特性。物理亮度的线性增加(如PWM占空比从10%到20%)在人眼看来是亮度的急剧变化,而高亮度区域的变化则不明显。
为了实现符合人眼感知的"线性调光",输出PWM必须经过Gamma校正:
![][image2]
通常取 ![][image3]。本系统在Flash中预存一张256字节的Gamma校正查找表(LUT),将用户设定的0-100亮度直接映射为校正后的PWM值,从而实现细腻、均匀的调光体验 9。
4.1.2 PID恒照度控制
在"智能调光模式"下,系统目标是维持桌面照度恒定(例如500 Lux)。
- 比例环节(P): 快速响应环境光变化。当外部光线突然变暗,P项迅速增加PWM输出。
- 积分环节(I): 消除稳态误差。P项无法完全消除误差,I项通过累积过去的误差,确保最终照度精确稳定在设定值。
- 微分环节(D): 抑制超调与振荡。当用户手部挥过传感器造成光线剧烈波动时,D项会产生反向作用力,阻尼PWM的剧烈变化,防止灯光"闪烁" 5。
4.2 传感器融合存在检测算法
为了解决"人在灯灭"的尴尬,本设计提出了**"动态触发-静态维持"**的融合逻辑:
- 触发阶段(PIR主导): PIR传感器对横向移动极其敏感。当探测到信号时,系统立即唤醒并点亮台灯,同时重置"无人计时器"。
- 维持阶段(超声波主导): 当PIR信号消失(用户静止),系统并不立即关灯,而是启动超声波测距。
- 若测距值 ![][image4](例如80cm),判定座位上有人(由于人头/身体阻挡了声波),强制维持开灯状态。
- 若测距值 ![][image5](声波打到椅背或地面),判定座位可能无人,开始进入"预关灯倒计时"。
- 关灯阶段(超时逻辑): 只有当PIR无信号 且 超声波判定无人 且 倒计时(如60秒)结束,台灯才执行软关断。
此算法通过超声波填补了PIR的静态盲区,实现了真正的"存在感应" 7。
4.3 坐姿监测的滞回与分级报警
针对原始设计中"过近即报警"的粗暴逻辑,重构设计引入了时间积分 与分级干预机制。
- 状态定义:
- 正常区: 距离 > 40cm。
- 警告区: 距离 < 30cm。
- 时间积分逻辑: 系统维护一个"不良姿势计数器"。采样频率为10Hz。每检测到一次"警告区"数据,计数器+1;检测到"正常区",计数器-2(快速恢复)。
- 触发阈值: 仅当计数器超过150(即累计持续约15秒的不良坐姿)时,才触发报警。这有效过滤了用户弯腰捡东西、喝水等正常动作 3。
- 分级反馈(Escalating Feedback):
- 一级提醒(视觉): 台灯亮度瞬间降低20%并缓慢恢复(呼吸效果),无声提醒用户。
- 二级提醒(OLED): 屏幕弹出"请注意坐姿"图标。
- 三级提醒(听觉): 若一级提醒后30秒内未纠正,蜂鸣器发出柔和的"滴-滴"声。
---
5. 人机交互界面设计 (HMI Design)
5.1 OLED多级菜单系统架构
为了容纳丰富的功能设置,采用分层菜单结构。
- 主界面 (Dashboard): 显示当前亮度(百分比或Lux)、工作模式图标(自动/手动/蓝牙)、时间(如有RTC)、番茄钟倒计时。
- 一级菜单:
-
- 照明模式 (手动 / 智能PID / 阅读预设 / 休闲预设)
-
- 番茄时钟 (开始 / 暂停 / 设置时长)
-
- 坐姿护眼 (开关 / 灵敏度校准)
-
- 系统设置 (蓝牙开关 / 声音开关 / 恢复出厂)
-
- 交互逻辑:
- 按键1 (Menu/OK): 进入菜单 / 确认。
- 按键2 (Up): 向上选择 / 增加亮度。
- 按键3 (Down): 向下选择 / 减小亮度。
- 按键4 (Back/Cancel): 返回上一级 / 长按开关机。
OLED驱动层引入显存缓冲区(Frame Buffer),所有绘图操作在RAM中进行,完成后一次性通过DMA刷入屏幕,杜绝了菜单刷新时的闪烁现象 15。
5.2 蓝牙通信协议设计
为了配合手机APP控制,定义一套定长帧结构的通信协议,确保数据完整性。
- 帧头: 0xA5 0x5A
- 功能字: 1字节 (如 0x01=开关, 0x02=亮度, 0x03=定时)
- 数据长度: 1字节
- 数据载荷: N字节
- 校验和: 1字节 (Sum Check)
- 帧尾: 0x0D 0x0A
APP不仅发送控制指令,还能实时接收台灯上传的Lux值和坐姿状态,实现数据的双向可视化 24。
---
6. 功能列表:重构后的智能台灯系统 (Detailed Function List)
基于上述深度分析与设计,以下为STM32智能台灯的最终重构功能列表。该列表按功能模块分类,并标注了序号以便筛选。
I. 核心照明与光控系统 (Illumination & Control)
- Cinema-Grade Soft Start/Stop (影院级软启动/停止):
- 开关灯时,亮度在1.5秒内呈对数曲线平滑渐变,避免瞬间全亮造成的眩光不适与视觉冲击 11。
- Gamma-Corrected Linear Dimming (Gamma校正线性调光):
- 手动调节模式下,应用Gamma 2.2校正算法,将0-100%的用户设定值映射为非线性PWM输出,确保人眼感知的亮度变化均匀线性,杜绝低亮度下的阶梯感 9。
- PID Constant Illuminance Control (PID恒照度自动调光):
- 在智能模式下,利用光敏电阻采集环境光,通过PID闭环算法动态调整LED功率。即使外部光线变化(如云层遮挡阳光),桌面照度始终稳定在用户设定的Lux值(如500 Lux),消除光照波动对视力的损害 5。
- High-Frequency PWM Drive (高频无频闪驱动):
- PWM频率设定为20kHz以上,超出人耳听觉范围且杜绝手机拍摄时的水波纹频闪,保护视力健康 14。
II. 智能感知与健康管理 (Sensing & Health)
- Sensor-Fusion Presence Detection (多模态融合存在检测):
- 结合PIR(动态探测)与超声波(静态测距),精准判断用户是否在座。即使用户静止阅读,只要超声波检测到人体阻挡,台灯保持常亮;仅当两者均无信号时才启动自动关灯逻辑,彻底解决"读死书灯灭"的问题 7。
- Hysteresis Posture Monitoring (滞回坐姿监测):
- 利用超声波测距,配合15秒的时间积分算法与中值滤波,智能过滤低头捡笔等瞬时动作。仅在持续检测到用户距离小于30cm时才判定为不良坐姿,极大降低误报率 3。
- Adaptive Visual/Audio Alert (自适应多级报警):
- 坐姿报警采用分级机制:初期仅通过灯光微弱"呼吸"进行无声视觉提示;若用户未纠正,OLED屏幕闪烁图标;最后阶段才启用蜂鸣器柔和鸣叫。优先保障学习专注度 11。
- Pomodoro Productivity Timer (番茄专注时钟):
- 内置标准番茄工作法逻辑(25分钟专注/5分钟休息)。专注期间灯光处于高显色性工作模式;休息时间到达时,灯光自动切换为暖色调低亮度模式,并辅以OLED动画,引导用户休息 27。
III. 人机交互与可视化 (HMI & Visualization)
- OLED Hierarchical Menu System (OLED分层菜单系统):
- 摒弃单一显示,提供图形化多级菜单。用户可直接在台灯上设置"坐姿报警灵敏度"、"番茄钟时长"、"默认亮度"等参数,无需重新烧录代码 15。
- Real-Time Data Dashboard (实时数据仪表盘):
- 待机界面直观显示当前环境照度(Lux)、系统工作模式、坐姿距离(cm)及蓝牙连接状态,实现设备状态的可视化。
- Screen Saver & Night Mode (屏幕保护与夜间模式):
- 无操作30秒后自动降低OLED亮度或熄屏,防止OLED烧屏并减少夜间光污染。按任意键或检测到人体移动时秒级唤醒。
IV. 连接性与系统可靠性 (Connectivity & Reliability)
- Bi-Directional Bluetooth Control (双向蓝牙控制):
- 不仅支持手机APP远程开关与调光,还将传感器数据(光照、坐姿、在座状态)实时回传至APP,支持远程监控儿童学习状态 24。
- Parameter Non-Volatile Storage (参数掉电记忆):
- 利用STM32内部Flash模拟EEPROM,自动保存用户的亮度偏好、报警开关及PID参数。断电重启后自动恢复上次设置,无需重复调节。
- Adaptive Noise Filtering (自适应噪声过滤):
- 针对超声波与光敏传感器,在软件底层实现滑动平均滤波算法,剔除电源波动与环境干扰带来的数据毛刺,确保控制逻辑的稳定性 17。
---
7. 结论 (Conclusion)
本报告详细阐述了基于STM32F103C8T6平台的智能台灯重构方案。通过引入工业级的控制算法(PID、Gamma校正)与智能化的传感器融合逻辑,本设计成功克服了传统DIY台灯功能粗糙、体验不佳的顽疾。重构后的系统不仅满足了基础照明需求,更转化为了一个集视觉保护、坐姿矫正与效率管理于一体的智能桌面助手。该设计充分挖掘了32位微控制器的算力优势,代表了从"电子制作"向"产品化设计"跨越的典型范例。
---
8. 软件实现 (Software Implementation)
本章节基于"现有硬件模块驱动"(假设已存在基础的 LED_Init, OLED_Init, Adc_Init 等底层驱动)提供核心逻辑层的代码实现。代码分为三个主要部分:核心控制逻辑 (PID/Gamma/调光)、健康监测逻辑 (坐姿/存在融合)以及主程序状态机。
8.1 核心头文件 (app_smart_lamp.h)
定义系统状态、模式枚举及核心参数结构体。
C
#ifndef __APP_SMART_LAMP_H
#define __APP_SMART_LAMP_H
#include "stm32f10x.h"
#include <stdbool.h>
// --- 系统工作模式 ---
typedef enum {
MODE_MANUAL = 0, // 手动按键调光
MODE_AUTO_PID, // 智能PID恒照度
MODE_REMOTE, // 蓝牙远程控制
MODE_POMODORO // 番茄专注模式
} SystemMode_t;
// --- 坐姿/存在状态 ---
typedef enum {
POSTURE_GOOD = 0,
POSTURE_BAD_WARNING, // 预警 (无声, 灯光呼吸)
POSTURE_BAD_ALARM // 报警 (蜂鸣器)
} PostureState_t;
typedef struct {
SystemMode_t currentMode;
uint8_t targetBrightness; // 0-100% 用户设定目标
uint16_t currentPWM; // 实际输出PWM
uint16_t sensorLux; // 当前环境光照(Lux)
uint16_t distanceCm; // 当前超声波距离(cm)
bool isPersonPresent; // 是否有人 (融合逻辑结果)
PostureState_t posture;
} LampState_t;
extern LampState_t g_LampState;
// --- 核心函数声明 ---
void SmartLamp_Init(void);
void SmartLamp_Loop(void); // 主循环调用
void Lamp_SetBrightness_Soft(uint8_t targetPercent); // 软启动调光
#endif
8.2 控制算法模块 (control_logic.c)
实现Gamma校正查找表、PID算法及软启动逻辑。
C
#include "app_smart_lamp.h"
#include "led.h" // 假设已有底层驱动: LED_PWM_Set(val)
#include "adc.h" // 假设: Get_Light_Sensor_Value()
LampState_t g_LampState;
// Gamma 2.2 校正表 (0-100映射到0-65535, 适配16位定时器)
// 为了代码简洁,此处仅列出部分关键节点插值演示
const uint16_t GAMMA_LUT = {
0, 18, 50, 100,..., 32000, 65535 // 实际应生成完整101个点
};
// --- PID 控制参数 ---
typedef struct {
float Kp, Ki, Kd;
float prevError, integral;
float setPoint; // 目标照度 Lux
} PID_Config_t;
PID_Config_t lightPID = {0.5f, 0.05f, 0.1f, 0, 0, 500.0f}; // 默认目标500Lux
// 1. 软启动/平滑调光函数 (解决光线突变)
void Lamp_Update_PWM_Soft(void) {
static uint16_t targetPWM_Raw = 0;
// 根据模式计算目标PWM
if (g\_LampState.currentMode \== MODE\_MANUAL) {
// 手动模式:查表Gamma校正
targetPWM\_Raw \= GAMMA\_LUT;
}
else if (g\_LampState.currentMode \== MODE\_AUTO\_PID) {
// PID模式下,目标PWM由PID计算得出(在PID函数中赋值)
return;
}
// 渐变逻辑 (Soft Step)
if (g\_LampState.currentPWM \< targetPWM\_Raw) {
g\_LampState.currentPWM \+= (targetPWM\_Raw \- g\_LampState.currentPWM) / 10 \+ 1; // 追赶算法
} else if (g\_LampState.currentPWM \> targetPWM\_Raw) {
g\_LampState.currentPWM \-= (g\_LampState.currentPWM \- targetPWM\_Raw) / 10 \+ 1;
}
LED\_PWM\_Set(g\_LampState.currentPWM); // 调用底层硬件驱动
}
// 2. PID 恒照度计算 (建议100ms调用一次)
void Lamp_Run_PID(void) {
if (g_LampState.currentMode!= MODE_AUTO_PID) return;
float currentLux \= (float)g\_LampState.sensorLux;
float error \= lightPID.setPoint \- currentLux;
lightPID.integral \+= error;
// 积分限幅,防止饱和
if (lightPID.integral \> 1000) lightPID.integral \= 1000;
if (lightPID.integral \< \-1000) lightPID.integral \= \-1000;
float derivative \= error \- lightPID.prevError;
float outputAdjustment \= (lightPID.Kp \* error) \+ (lightPID.Ki \* lightPID.integral) \+ (lightPID.Kd \* derivative);
lightPID.prevError \= error;
// 将PID输出叠加到当前亮度 (增量式调节)
int newPWM \= g\_LampState.currentPWM \+ (int)outputAdjustment;
// 输出限幅
if (newPWM \> 65535) newPWM \= 65535;
if (newPWM \< 0) newPWM \= 0;
g\_LampState.currentPWM \= (uint16\_t)newPWM;
LED\_PWM\_Set(g\_LampState.currentPWM);
}
8.3 健康监测与融合逻辑 (health_monitor.c)
实现传感器数据融合(Sensor Fusion)与坐姿滞回报警。
C
#include "app_smart_lamp.h"
#include "hcsr04.h" // 假设: HCSR04_GetDistance()
#include "buzzer.h" // 假设: Beep_On(), Beep_Off()
#include "pir.h" // 假设: PIR_ReadState()
// 参数定义
#define DIST_BAD_POSTURE_CM 30 // 坐姿报警阈值
#define DIST_PERSON_EXIST_CM 80 // 超声波判定有人的最大距离
#define POSTURE_TIME_THRES 150 // 15秒 (100ms * 150)
#define NO_PERSON_TIMEOUT 600 // 60秒无人关灯
static int16_t badPostureCounter = 0;
static int16_t noPersonTimer = 0;
// 传感器融合与健康逻辑 (建议100ms调用一次)
void Lamp_Run_HealthMonitor(void) {
// --- 1. 获取数据 ---
g_LampState.distanceCm = HCSR04_GetDistance();
bool pirTriggered = PIR_ReadState();
// \--- 2\. 存在检测融合算法 (PIR \+ Ultrasonic) \---
// 只要 PIR 触发 OR 超声波探测到近距离物体,重置无人计时器
if (pirTriggered |
| (g_LampState.distanceCm < DIST_PERSON_EXIST_CM && g_LampState.distanceCm > 2)) {
g_LampState.isPersonPresent = true;
noPersonTimer = NO_PERSON_TIMEOUT; // 重置倒计时
} else {
if (noPersonTimer > 0) {
noPersonTimer--;
} else {
g_LampState.isPersonPresent = false; // 确认为无人
}
}
// 无人自动关灯逻辑
if (\!g\_LampState.isPersonPresent) {
g\_LampState.targetBrightness \= 0; // 目标亮度设为0
// 如果是自动模式,暂时覆盖PID输出
if(g\_LampState.currentMode \== MODE\_AUTO\_PID) LED\_PWM\_Set(0);
return; // 无人时跳过坐姿检测
} else {
// 有人归来,恢复亮度 (如果是0的话)
if (g\_LampState.targetBrightness \== 0 && g\_LampState.currentMode \== MODE\_MANUAL) {
g\_LampState.targetBrightness \= 50; // 恢复默认
}
}
// \--- 3\. 坐姿监测 (滞回与积分算法) \---
// 过滤掉超声波错误数据 (\>200cm通常无效)
if (g\_LampState.distanceCm \< DIST\_BAD\_POSTURE\_CM && g\_LampState.distanceCm \> 2) {
if (badPostureCounter \< POSTURE\_TIME\_THRES \+ 50) {
badPostureCounter++;
}
} else {
// 恢复正常坐姿,计数器快速下降 (非立即清零,防止临界抖动)
if (badPostureCounter \> 0) badPostureCounter \-= 2;
}
// 状态机处理报警等级
if (badPostureCounter \> POSTURE\_TIME\_THRES) {
g\_LampState.posture \= POSTURE\_BAD\_ALARM;
// 触发蜂鸣器逻辑 (滴-滴)
static uint8\_t beepToggle \= 0;
beepToggle++;
if (beepToggle % 10 \== 0) Beep\_Toggle();
} else if (badPostureCounter \> POSTURE\_TIME\_THRES / 2) {
g\_LampState.posture \= POSTURE\_BAD\_WARNING;
Beep\_Off();
// 可以在此处添加灯光呼吸效果提醒
} else {
g\_LampState.posture \= POSTURE\_GOOD;
Beep\_Off();
}
}
8.4 主函数逻辑 (main.c)
集成各模块,使用时间片轮询结构。
C
#include "stm32f10x.h"
#include "delay.h"
#include "key.h"
#include "oled.h"
#include "app_smart_lamp.h"
// 调度器时间片
uint32_t tick_10ms = 0;
uint32_t tick_100ms = 0;
int main(void) {
// 1. 底层硬件初始化
SystemInit();
delay_init();
KEY_Init(); // 按键
LED_Init(); // PWM定时器
OLED_Init(); // I2C OLED
ADC_Init(); // 光敏
HCSR04_Init(); // 超声波
PIR_Init(); // 红外
Buzzer_Init();
SmartLamp\_Init(); // 应用层初始化
while (1) {
// \--- 10ms 任务: 按键扫描与平滑调光 \---
if (tick\_10ms++ \> 10) { // 实际应使用Systick或Timer中断标志
tick\_10ms \= 0;
uint8\_t key \= KEY\_Scan(0);
if (key) {
// 简单的状态机按键处理
switch (key) {
case 1: // 切换模式
g\_LampState.currentMode++;
if (g\_LampState.currentMode \> MODE\_POMODORO)
g\_LampState.currentMode \= MODE\_MANUAL;
break;
case 2: // 亮度+
if (g\_LampState.targetBrightness \< 100) g\_LampState.targetBrightness \+= 10;
break;
case 3: // 亮度-
if (g\_LampState.targetBrightness \> 10) g\_LampState.targetBrightness \-= 10;
break;
}
}
Lamp\_Update\_PWM\_Soft(); // 执行软启动调光
}
// \--- 100ms 任务: 传感器逻辑与PID \---
if (tick\_100ms++ \> 100) { // 实际应使用Systick或Timer中断标志
tick\_100ms \= 0;
// 读取传感器
g\_LampState.sensorLux \= Get\_Adc\_Average(ADC\_Channel\_Light, 5);
// 运行核心逻辑
Lamp\_Run\_HealthMonitor(); // 坐姿与存在
Lamp\_Run\_PID(); // 恒照度计算
// 刷新UI
char buf\[20\];
sprintf(buf, "Mode: %d", g\_LampState.currentMode);
OLED\_ShowString(0, 0, buf, 12);
sprintf(buf, "Lux: %d PWM:%d", g\_LampState.sensorLux, g\_LampState.targetBrightness);
OLED\_ShowString(0, 2, buf, 12);
sprintf(buf, "Dist: %d cm", g\_LampState.distanceCm);
OLED\_ShowString(0, 4, buf, 12);
if (g\_LampState.posture \== POSTURE\_BAD\_ALARM) {
OLED\_ShowString(0, 6, "BAD POSTURE\!", 12);
} else {
OLED\_ShowString(0, 6, " ", 12);
}
OLED\_Refresh\_Gram();
}
delay\_ms(1); // 简单延时基准
}