基于STM32 Nucleo-L476RG的智能灯设计(纯CubeMX开发)

一、系统概述与核心功能

1. 系统定位

基于STM32 Nucleo-L476RG开发板的智能灯系统,充分利用板载资源(LED、按钮、Arduino接口)和CubeMX图形化配置工具,实现一款低成本、低功耗、可扩展的智能照明系统。系统支持PWM调光、呼吸灯效、环境光自适应、人体感应等功能,通过板载按钮和扩展传感器实现智能控制。

2. 核心功能模块

模块 功能描述 技术指标
主控核心 STM32L476RG(Nucleo-L476RG),80MHz Cortex-M4,超低功耗,1MB Flash 动态功耗<100μA/MHz
灯光控制 板载绿色LED(LD2)PWM调光,支持0-100%亮度调节 PWM频率1kHz,分辨率12位
人机交互 板载蓝色用户按钮(B1)切换模式,LD2状态指示 按钮支持短按/长按识别
环境感知 扩展光敏电阻(Arduino A0)检测环境光,自动调节亮度 光敏电阻10kΩ,ADC 12位采样
人体感应 扩展HC-SR501 PIR传感器,实现人来灯亮、人走灯灭 探测距离7m,延时可调
低功耗设计 无操作时进入STOP2模式,功耗<5μA,按钮中断唤醒 电池供电续航>30天

二、硬件设计方案

1. Nucleo-L476RG资源分配

外设 引脚 功能 CubeMX配置
LED_LD2 PA5 板载绿色LED,PWM调光 TIM2_CH1,Alternate Function
按钮_B1 PC13 用户按钮,模式切换 GPIO_Input,Pull-up
光敏电阻 PA0 (A0) 环境光检测 ADC1_IN5,Analog mode
PIR传感器 PA1 (A1) 人体感应输入 GPIO_Input,External Interrupt
PWM输出 PA6 (D12) 扩展LED调光输出 TIM3_CH1,Alternate Function
I2C接口 PB8/PB9 扩展OLED显示 I2C1,Standard mode
UART通信 PA2/PA3 串口调试/蓝牙控制 USART2,Asynchronous

2. 扩展电路设计

复制代码
Nucleo-L476RG Arduino接口:
┌─────────────────────────────┐
│ A0 (PA0) ──[光敏电阻]── GND │ 环境光检测
│ A1 (PA1) ──[PIR OUT]────── │ 人体感应输入
│ D12 (PA6) ─[220Ω]──[LED+] │ 扩展LED调光
│ D13 (PA5) ──[板载LED]──── │ 板载LED控制
│ 5V ────────[PIR VCC]───── │ PIR供电
│ 3.3V ──────[OLED VCC]──── │ OLED供电
└─────────────────────────────┘

3. 电源与低功耗设计

  • 电源选择:USB供电(5V)或锂电池(3.7V)→ LDO稳压至3.3V
  • 低功耗策略:无操作时进入STOP2模式,按钮/PIR中断唤醒
  • 外设电源管理:不使用时关闭OLED、PIR传感器电源

三、CubeMX配置步骤

1. 工程创建与MCU选择

  1. 打开CubeMX → File → New Project → 搜索 Nucleo-L476RG
  2. Project Manager 选项卡:
    • Project Name:Nucleo_SmartLight
    • Toolchain/IDE:STM32CubeIDE
    • 勾选 Generate peripheral initialization as a pair of .c/.h files per peripheral

2. 时钟树配置(Clock Configuration)

  • HSE :选择 Crystal/Ceramic Resonator(Nucleo板载8MHz晶振)
  • PLL Source MuxHSE
  • PLLMulx20(8MHz × 20 = 160MHz)
  • System Clock MuxPLLCLK
  • SYSCLK:80MHz(分频器设置)
  • APB1/APB2 Prescaler/1(80MHz)

3. 外设参数配置(Pinout & Configuration)

3.1 TIM2 PWM配置(板载LED调光)
参数 设置值 说明
TIM2 Mode PWM Generation CH1 PA5 = TIM2_CH1
Prescaler (PSC) 79 80MHz/(79+1)=1MHz
Counter Period (ARR) 999 PWM周期1ms,频率1kHz
Pulse (CCR1) 0 初始占空比0%
CH Polarity High 高电平LED亮
3.2 ADC配置(光敏电阻)
参数 设置值 说明
ADC1 Mode Independent mode 独立模式
Resolution 12-bit 12位分辨率
Scan Conversion Mode Disabled 单次转换
Continuous Conversion Mode Enabled 连续转换
Sampling Time 15 Cycles 采样时间
3.3 GPIO配置
引脚 模式 Pull-up/Pull-down Label
PC13 Input mode Pull-up USER_BUTTON
PA1 Input mode No pull-up/pull-down PIR_INPUT
PB8/PB9 Alternate Function Open-drain I2C1_SCL/SDA
3.4 中断配置
中断源 优先级 触发方式
EXTI Line[1] (PA1) Priority 1 Rising edge
EXTI Line[13] (PC13) Priority 2 Falling edge

4. 低功耗配置

  • RCC:禁用HSE和LSI,使用HSI16(16MHz内部RC)
  • PWR:启用Ultra-low-power mode,选择STOP2模式
  • GPIO:未使用的引脚设置为Analog mode(最低功耗)

四、软件设计与核心代码

1. 系统架构(前后台系统)

  • 后台中断
    • EXTI1_IRQHandler:PIR传感器中断,唤醒系统并开启灯光
    • EXTI15_10_IRQHandler:用户按钮中断,切换工作模式
    • TIM2_IRQHandler:PWM更新中断,实现呼吸灯效果
  • 前台主循环
    • 读取光敏电阻值,计算环境光强度
    • 根据模式和光照自动调节LED亮度
    • 无操作时进入低功耗模式

2. 核心代码实现(基于HAL库)

2.1 系统状态定义(main.h)
c 复制代码
#ifndef __MAIN_H
#define __MAIN_H

#include "stm32l4xx_hal.h"

// 工作模式定义
typedef enum {
    MODE_OFF = 0,        // 关闭
    MODE_ON,             // 常亮
    MODE_BREATH,          // 呼吸灯
    MODE_AUTO,            // 自动感光
    MODE_PIR              // 人体感应
} WorkMode_t;

// 系统状态结构体
typedef struct {
    WorkMode_t current_mode;    // 当前模式
    uint8_t brightness;         // 亮度值(0-100)
    uint8_t target_brightness;  // 目标亮度
    uint8_t ambient_light;      // 环境光强度(0-100)
    uint8_t pir_detected;       // PIR检测标志
    uint32_t last_activity;      // 最后活动时间
} SystemState_t;

extern SystemState_t sys_state;

#endif
2.2 PWM调光控制(main.c)
c 复制代码
#include "main.h"

SystemState_t sys_state = {
    .current_mode = MODE_OFF,
    .brightness = 0,
    .target_brightness = 0,
    .ambient_light = 50,
    .pir_detected = 0,
    .last_activity = 0
};

// 设置LED亮度(0-100%)
void Set_LED_Brightness(uint8_t brightness) {
    if (brightness > 100) brightness = 100;
    
    // 计算PWM占空比(ARR=999,对应0-100%)
    uint32_t pulse = (brightness * 999) / 100;
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
    
    sys_state.brightness = brightness;
}

// 呼吸灯效果(在TIM2中断中调用)
void Breath_Effect(void) {
    static uint8_t breath_dir = 0;  // 0=渐亮,1=渐暗
    static uint8_t current_brightness = 0;
    
    if (breath_dir == 0) {
        current_brightness++;
        if (current_brightness >= 100) {
            breath_dir = 1;
        }
    } else {
        current_brightness--;
        if (current_brightness == 0) {
            breath_dir = 0;
        }
    }
    
    Set_LED_Brightness(current_brightness);
}

// TIM2中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        if (sys_state.current_mode == MODE_BREATH) {
            Breath_Effect();
        }
    }
}
2.3 光敏电阻采样与环境光计算
c 复制代码
// 读取光敏电阻值并计算环境光强度
void Update_Ambient_Light(void) {
    uint32_t adc_value;
    uint8_t light_intensity;
    
    // 启动ADC转换
    HAL_ADC_Start(&hadc1);
    if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
        adc_value = HAL_ADC_GetValue(&hadc1);
        
        // 转换为百分比(光敏电阻:光照越强,电阻越小,ADC值越小)
        // 假设:黑暗时ADC≈4000,强光时ADC≈500
        if (adc_value > 4000) adc_value = 4000;
        if (adc_value < 500) adc_value = 500;
        
        light_intensity = 100 - ((adc_value - 500) * 100) / 3500;
        sys_state.ambient_light = light_intensity;
    }
    HAL_ADC_Stop(&hadc1);
}
2.4 自动模式亮度调节
c 复制代码
// 自动模式:根据环境光调节亮度
void Auto_Brightness_Control(void) {
    uint8_t target_brightness;
    
    // 环境光越暗,LED亮度越高
    if (sys_state.ambient_light < 20) {
        target_brightness = 100;  // 黑暗环境,全亮
    } else if (sys_state.ambient_light < 50) {
        target_brightness = 70;   // 较暗环境,70%亮度
    } else if (sys_state.ambient_light < 80) {
        target_brightness = 40;   // 中等光照,40%亮度
    } else {
        target_brightness = 10;   // 明亮环境,10%亮度
    }
    
    // 平滑过渡
    if (sys_state.brightness < target_brightness) {
        sys_state.brightness++;
    } else if (sys_state.brightness > target_brightness) {
        sys_state.brightness--;
    }
    
    Set_LED_Brightness(sys_state.brightness);
}
2.5 按钮与PIR中断处理
c 复制代码
// 按钮中断回调
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_13) {  // 用户按钮PC13
        sys_state.last_activity = HAL_GetTick();
        
        // 切换模式
        sys_state.current_mode = (sys_state.current_mode + 1) % 5;
        
        // 模式切换反馈
        for (int i = 0; i <= sys_state.current_mode; i++) {
            Set_LED_Brightness(100);
            HAL_Delay(100);
            Set_LED_Brightness(0);
            HAL_Delay(100);
        }
    }
    
    if (GPIO_Pin == GPIO_PIN_1) {   // PIR传感器PA1
        sys_state.pir_detected = 1;
        sys_state.last_activity = HAL_GetTick();
        
        if (sys_state.current_mode == MODE_PIR) {
            Set_LED_Brightness(100);  // 检测到人体,全亮
        }
    }
}
2.6 低功耗管理
c 复制代码
// 进入低功耗模式
void Enter_LowPower_Mode(void) {
    // 关闭不必要的外设
    __HAL_TIM_DISABLE(&htim2);
    HAL_ADC_Stop(&hadc1);
    
    // 配置所有GPIO为模拟模式(最低功耗)
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    
    // 进入STOP2模式
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    // 唤醒后重新配置系统时钟
    SystemClock_Config();
    MX_TIM2_Init();
    MX_ADC1_Init();
}
2.7 主函数逻辑
c 复制代码
int main(void) {
    HAL_Init();
    SystemClock_Config();
    
    // CubeMX生成的初始化
    MX_GPIO_Init();
    MX_TIM2_Init();
    MX_ADC1_Init();
    MX_I2C1_Init();
    
    // 启动PWM
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
    
    // 初始化OLED显示(如果连接)
    OLED_Init();
    OLED_ShowString(0, 0, "Smart Light");
    OLED_ShowString(0, 2, "Mode: OFF");
    
    while (1) {
        // 更新环境光数据
        Update_Ambient_Light();
        
        // 根据当前模式执行相应控制
        switch (sys_state.current_mode) {
            case MODE_OFF:
                Set_LED_Brightness(0);
                break;
                
            case MODE_ON:
                Set_LED_Brightness(80);  // 常亮80%
                break;
                
            case MODE_BREATH:
                // 呼吸灯效果在TIM2中断中处理
                break;
                
            case MODE_AUTO:
                Auto_Brightness_Control();
                break;
                
            case MODE_PIR:
                if (sys_state.pir_detected) {
                    // 检测到人体,保持亮灯30秒
                    if (HAL_GetTick() - sys_state.last_activity > 30000) {
                        sys_state.pir_detected = 0;
                        Set_LED_Brightness(0);
                    }
                }
                break;
        }
        
        // 更新OLED显示
        char display_str[20];
        sprintf(display_str, "Mode: %d", sys_state.current_mode);
        OLED_ShowString(0, 2, display_str);
        sprintf(display_str, "Light: %d%%", sys_state.brightness);
        OLED_ShowString(0, 4, display_str);
        sprintf(display_str, "Ambient: %d%%", sys_state.ambient_light);
        OLED_ShowString(0, 6, display_str);
        
        // 检查是否需要进入低功耗模式
        if (HAL_GetTick() - sys_state.last_activity > 60000) {  // 1分钟无活动
            OLED_Clear();
            Enter_LowPower_Mode();
            sys_state.last_activity = HAL_GetTick();  // 唤醒后重置活动时间
        }
        
        HAL_Delay(100);  // 100ms主循环
    }
}

参考代码 基于stm32 nucleo_L476的智能灯(操作说明+源码) www.youwenfan.com/contentcst/123463.html

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具 预期结果
硬件检查 测量3.3V供电,检查LED是否正常点亮 万用表 电压稳定在3.3V
PWM验证 用示波器观察PA5引脚波形 示波器 1kHz PWM,占空比可调
按钮测试 短按/长按按钮,观察LED反馈 肉眼观察 模式正确切换
光敏测试 用手遮挡/移开,观察亮度变化 OLED显示 亮度随环境光变化
低功耗测试 测量STOP模式电流消耗 万用表(串联) 电流<10μA

2. 扩展功能(CubeMX新增配置)

扩展功能 CubeMX配置 实现效果
OLED显示 I2C1启用,PB8/PB9 实时显示模式、亮度、环境光
蓝牙控制 USART1启用,PA9/PA10 手机APP远程控制开关/调光
温湿度监测 I2C1添加SHT30 显示环境温湿度信息
多LED控制 TIM3_CH2/3/4启用 RGB全彩灯光效果

3. 性能优化建议

  • PWM频率优化:将PWM频率提高到20kHz以上,避免LED可见闪烁
  • ADC采样优化:使用DMA传输ADC数据,减少CPU干预
  • 低功耗优化:使用RTC定时唤醒,实现定时开关灯功能
  • 抗干扰优化:在光敏电阻电路中加入RC滤波,减少环境光波动影响

六、总结

基于STM32 Nucleo-L476RG的智能灯系统充分利用了CubeMX图形化配置的优势,实现了从简单到复杂的智能照明功能。系统具有以下特点:

核心优势

  1. 低成本:利用Nucleo板载资源,无需额外购买主控板
  2. 低功耗:STOP2模式下功耗<5μA,电池供电可使用数月
  3. 易扩展:Arduino接口方便添加各种传感器模块
  4. 开发快捷:CubeMX自动生成初始化代码,专注应用逻辑开发

应用场景

  • 智能家居夜灯、走廊灯
  • 书桌护眼灯、阅读灯
  • 仓库/车库人体感应灯
  • 教学实验平台、创客项目
相关推荐
芯片和软件研究所10 小时前
【tinyGTC】北斗授时授频 GPSDO 驯服钟的PPS和10M时钟测量
单片机·嵌入式硬件·北斗·时间同步·时频技术·授时·信号测量
Escene202110 小时前
Realtek HoneyGUI (1)
单片机·嵌入式硬件·物联网
波特率11520012 小时前
FreeRTOS当中的Mail Queue使用教程(CMSIS_v1)
单片机·操作系统·freertos
潜创微科技13 小时前
4K 转 MIPI 硬核方案|ITE IT6616 HDMI1.4 转 MIPI CSI/DSI 转换芯片解析
嵌入式硬件·音视频
三佛科技-1341638421214 小时前
FT32F103系列与APM32F103,STM32F103之间的对比,能否替换?
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
李永奉14 小时前
杰理可视化SDK开发-蓝牙的可发现可连接和回连
单片机·嵌入式硬件·物联网·语音识别
【ql君】qlexcel15 小时前
Visual Studio Code开发STM32设置头文件宏定义uint32_t报错
vscode·stm32·vs code·头文件宏定义·uint32_t报错·uint8_t报错·uint16_t报错
振浩微433射频芯片16 小时前
标签界的“千里眼”:VRT5312,150cm超远读写距离,重新定义RFID新可能!
科技·单片机·嵌入式硬件·物联网
andylauren16 小时前
论单点接地的重要性——从MP3模块噪声问题看接地设计的关键
嵌入式硬件