我将针对光锤60手电筒项目,从需求分析、架构设计到C代码实现,详细阐述一个可靠、高效、可扩展的嵌入式系统开发流程。
关注微信公众号,提前获取相关推文

1. 需求分析
根据项目描述,光锤60手电筒的核心需求如下:
- 功能需求:
- 照明: 提供不同功率档位的照明输出,包括60W (10000lm)、30W和3W。
- 调光: 支持档位切换,并且能记忆上次使用的档位。
- 恒流: 在不同功率下实现恒流输出,保证亮度稳定。
- 散热: 主动散热系统,确保60W档位不降档不烫手。
- 充电: 支持Type-C 45W快充,充满时间约1小时。
- 放电: 支持Type-C放电功能。
- 电池管理: 准确检测电池电量,并进行低电量保护。
- 状态指示: 通过LED指示灯显示电量、充电状态和档位。
- 保护: 过充、过放、过热、短路保护。
- 性能需求:
- 高效率: 高功率输出下的效率,保证续航时间。
- 快速响应: 按键操作快速响应,档位切换流畅。
- 稳定可靠: 系统运行稳定可靠,避免死机或异常。
- 功耗控制: 低功耗待机模式,延长电池寿命。
- 成本需求:
- 可扩展性:
2. 架构设计
针对以上需求,我将采用以下分层架构,保证代码的可读性、可维护性和可扩展性:
- 硬件抽象层 (HAL):
- 直接与硬件交互的底层驱动,包括GPIO、ADC、PWM、I2C、Timer、USB PD控制器、LED驱动等。
- 提供统一的接口,屏蔽不同硬件细节。
- 中间层 (MID):
- 对HAL层功能进行封装,提供更加抽象的功能接口,例如LED控制、按键扫描、电池管理、散热控制等。
- 实现一些算法,例如PID温控、电量估算等。
- 应用层 (APP):
- 实现手电筒的业务逻辑,例如档位控制、充电管理、状态显示等。
- 处理用户输入和系统事件。
- 系统层 (SYS):
- 提供系统初始化、任务调度、电源管理、错误处理等功能。
- 为其他层提供基础服务。
3. 软件模块划分
根据架构设计,软件模块划分如下:
- HAL层模块:
hal_gpio.c/h
: GPIO控制。
hal_adc.c/h
: ADC读取。
hal_pwm.c/h
: PWM控制。
hal_i2c.c/h
: I2C通信。
hal_timer.c/h
: 定时器控制。
hal_usbd.c/h
: USB设备控制器。
hal_led.c/h
: LED驱动。
hal_fan.c/h
: 风扇驱动。
hal_battery.c/h
: 电池管理芯片驱动(例如BQ25792).
hal_usbpd.c/h
:USB PD控制器驱动。
- MID层模块:
mid_led.c/h
: LED控制模块。
mid_key.c/h
: 按键扫描模块。
mid_battery.c/h
: 电池管理模块。
mid_temp.c/h
: 温度管理模块。
mid_fan.c/h
:散热控制模块。
mid_power.c/h
:电源控制模块。
mid_charging.c/h
:充电管理模块。
mid_light.c/h
: 照明控制模块,负责档位切换和恒流控制。
- APP层模块:
app_main.c
: 主应用程序入口。
app_ui.c/h
: UI管理模块,负责状态显示。
app_power.c/h
: 电源管理模块,处理充电放电逻辑。
app_lighting.c/h
:照明模块,负责档位逻辑控制。
- SYS层模块:
sys_init.c
: 系统初始化模块。
sys_task.c
: 任务调度模块。
sys_power.c
: 电源管理模块。
sys_error.c
: 错误处理模块。
sys_config.c
:配置信息模块。
4. C 代码实现
接下来,我将给出关键模块的C代码实现,并附有详细注释。为了代码简洁,我将采用简化版代码,实际开发中需要根据硬件选型进行调整。
(1) HAL层实现 (hal_gpio.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #ifndef HAL_GPIO_H #define HAL_GPIO_H
#include <stdint.h> #include <stdbool.h>
typedef enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_ANALOG } gpio_mode_t;
typedef enum { GPIO_PIN_LOW, GPIO_PIN_HIGH } gpio_pin_state_t;
typedef enum { GPIO_PIN_1 = 1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_MAX } gpio_pin_t;
void hal_gpio_init(gpio_pin_t pin, gpio_mode_t mode);
void hal_gpio_write(gpio_pin_t pin, gpio_pin_state_t state);
gpio_pin_state_t hal_gpio_read(gpio_pin_t pin);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include "hal_gpio.h"
void hal_gpio_init(gpio_pin_t pin, gpio_mode_t mode) { if (mode == GPIO_MODE_OUTPUT) { } else if (mode == GPIO_MODE_INPUT) { }
}
void hal_gpio_write(gpio_pin_t pin, gpio_pin_state_t state) { if (state == GPIO_PIN_HIGH) { } else { }
}
gpio_pin_state_t hal_gpio_read(gpio_pin_t pin) { return GPIO_PIN_LOW; }
|
(2) HAL层实现 (hal_adc.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #ifndef HAL_ADC_H #define HAL_ADC_H
#include <stdint.h>
typedef enum { ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_MAX } adc_channel_t;
void hal_adc_init(adc_channel_t channel);
uint16_t hal_adc_read(adc_channel_t channel);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include "hal_adc.h"
void hal_adc_init(adc_channel_t channel) { }
uint16_t hal_adc_read(adc_channel_t channel) { return 1024; }
|
(3) MID层实现 (mid_led.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #ifndef MID_LED_H #define MID_LED_H
#include <stdint.h> #include <stdbool.h>
typedef enum { LED_RED, LED_GREEN, LED_BLUE, LED_MAX } led_id_t;
void mid_led_init(led_id_t id);
void mid_led_set_state(led_id_t id, bool on);
void mid_led_blink(led_id_t id, uint32_t on_time_ms, uint32_t off_time_ms);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include "mid_led.h" #include "hal_gpio.h" #include "hal_timer.h"
static gpio_pin_t led_gpio_pins[LED_MAX] = { GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3 };
void mid_led_init(led_id_t id) { if(id >= LED_MAX ) return; hal_gpio_init(led_gpio_pins[id], GPIO_MODE_OUTPUT); }
void mid_led_set_state(led_id_t id, bool on) { if(id >= LED_MAX ) return;
hal_gpio_write(led_gpio_pins[id], on ? GPIO_PIN_HIGH : GPIO_PIN_LOW); }
void mid_led_blink(led_id_t id, uint32_t on_time_ms, uint32_t off_time_ms) { if(id >= LED_MAX ) return; static bool led_state = false; static uint32_t last_toggle_time = 0;
uint32_t current_time = hal_timer_get_ms();
if (current_time - last_toggle_time >= (led_state ? on_time_ms : off_time_ms)) { led_state = !led_state; mid_led_set_state(id,led_state); last_toggle_time = current_time; } }
|
(4) MID层实现 (mid_key.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #ifndef MID_KEY_H #define MID_KEY_H
#include <stdint.h> #include <stdbool.h>
typedef enum { KEY_1, KEY_2, KEY_MAX } key_id_t;
typedef enum{ KEY_STATE_NONE, KEY_STATE_DOWN, KEY_STATE_HOLD, KEY_STATE_UP }key_state_t;
void mid_key_init(key_id_t id);
key_state_t mid_key_get_state(key_id_t id);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include "mid_key.h" #include "hal_gpio.h" #include "hal_timer.h"
static gpio_pin_t key_gpio_pins[KEY_MAX] = { GPIO_PIN_4, GPIO_PIN_5 };
#define KEY_DEBOUNCE_TIME_MS 10 #define KEY_HOLD_TIME_MS 1000
static key_state_t key_states[KEY_MAX];
static uint32_t key_press_time[KEY_MAX];
void mid_key_init(key_id_t id) { if(id >= KEY_MAX) return; hal_gpio_init(key_gpio_pins[id], GPIO_MODE_INPUT); key_states[id] = KEY_STATE_NONE; key_press_time[id] = 0;
}
key_state_t mid_key_get_state(key_id_t id) { if(id >= KEY_MAX) return KEY_STATE_NONE; gpio_pin_state_t current_state = hal_gpio_read(key_gpio_pins[id]); uint32_t current_time = hal_timer_get_ms(); if (current_state == GPIO_PIN_LOW) { if(key_states[id] == KEY_STATE_NONE) { key_press_time[id] = current_time; key_states[id] = KEY_STATE_DOWN;
} else if (key_states[id] == KEY_STATE_DOWN) { if (current_time - key_press_time[id] > KEY_DEBOUNCE_TIME_MS) { key_states[id] = KEY_STATE_HOLD; } } else if (key_states[id] == KEY_STATE_HOLD){
if (current_time - key_press_time[id] > KEY_HOLD_TIME_MS) {
}
} } else { if(key_states[id] == KEY_STATE_DOWN || key_states[id] == KEY_STATE_HOLD){ key_states[id] = KEY_STATE_UP; } else key_states[id] = KEY_STATE_NONE; } return key_states[id]; }
|
(5) APP层实现 (app_main.c
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include "mid_led.h" #include "mid_key.h" #include "mid_battery.h" #include "mid_light.h" #include "mid_temp.h" #include "mid_fan.h" #include "mid_charging.h" #include "sys_init.h" #include "sys_task.h" #include "app_ui.h" #include "app_power.h" #include "app_lighting.h" #include "hal_timer.h"
void app_main(void) { sys_init(); mid_led_init(LED_RED); mid_led_init(LED_GREEN); mid_led_init(LED_BLUE); mid_key_init(KEY_1); mid_key_init(KEY_2); mid_battery_init(); mid_temp_init(); mid_fan_init(); mid_charging_init(); mid_light_init(); app_ui_init(); app_power_init(); app_lighting_init();
while (1) { sys_task_run(); app_power_task(); app_lighting_task(); } }
|
(6) APP层实现 (app_lighting.c/h
)
1 2 3 4 5 6 7 8 9
| #ifndef APP_LIGHTING_H #define APP_LIGHTING_H #include <stdint.h>
void app_lighting_init(void); void app_lighting_task(void);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include "app_lighting.h" #include "mid_light.h" #include "mid_key.h" #include "mid_led.h" #include "sys_config.h" #include "mid_power.h"
typedef enum { LIGHTING_MODE_OFF, LIGHTING_MODE_3W, LIGHTING_MODE_30W, LIGHTING_MODE_60W, LIGHTING_MODE_MAX }lighting_mode_t;
static lighting_mode_t current_mode;
static void change_mode(void);
void app_lighting_init(void) { current_mode = sys_config_get_last_lighting_mode(); mid_light_set_mode(current_mode);
if (current_mode == LIGHTING_MODE_OFF) { mid_led_set_state(LED_GREEN,false); mid_led_set_state(LED_RED,true); }else{ mid_led_set_state(LED_RED,false); mid_led_set_state(LED_GREEN,true); } }
void app_lighting_task(void) { key_state_t key_1_state = mid_key_get_state(KEY_1); if (key_1_state == KEY_STATE_UP) { change_mode(); } }
static void change_mode(void){ current_mode++; if (current_mode >= LIGHTING_MODE_MAX) { current_mode = LIGHTING_MODE_OFF; } mid_light_set_mode(current_mode); sys_config_set_last_lighting_mode(current_mode);
if (current_mode == LIGHTING_MODE_OFF) { mid_led_set_state(LED_GREEN,false); mid_led_set_state(LED_RED,true); }else{ mid_led_set_state(LED_RED,false); mid_led_set_state(LED_GREEN,true); } }
|
(7) MID层实现 (mid_light.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #ifndef MID_LIGHT_H #define MID_LIGHT_H
#include <stdint.h>
typedef enum { LIGHTING_MODE_OFF, LIGHTING_MODE_3W, LIGHTING_MODE_30W, LIGHTING_MODE_60W, LIGHTING_MODE_MAX }lighting_mode_t;
void mid_light_init(void);
void mid_light_set_mode(lighting_mode_t mode);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include "mid_light.h" #include "hal_pwm.h" #include "mid_temp.h" #include "mid_power.h" #define LED_PWM_CHANNEL PWM_CHANNEL_1
typedef struct { lighting_mode_t mode; uint16_t pwm_duty; uint16_t current_ma; } light_mode_config_t;
static const light_mode_config_t light_modes[] = { {LIGHTING_MODE_OFF, 0, 0}, {LIGHTING_MODE_3W, 1000, 500}, {LIGHTING_MODE_30W, 4000, 3000}, {LIGHTING_MODE_60W, 9999, 6000}, };
static light_mode_config_t current_mode_config;
void mid_light_init(void) { hal_pwm_init(LED_PWM_CHANNEL,10000); current_mode_config = light_modes[0]; }
void mid_light_set_mode(lighting_mode_t mode) { if( mode >= LIGHTING_MODE_MAX ) return; current_mode_config = light_modes[mode]; hal_pwm_set_duty(LED_PWM_CHANNEL,current_mode_config.pwm_duty); mid_power_set_led_current(current_mode_config.current_ma);
}
|
(8) SYS层实现 (sys_init.c
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include "sys_init.h" #include "hal_gpio.h" #include "hal_adc.h" #include "hal_pwm.h" #include "hal_i2c.h" #include "hal_timer.h" #include "hal_usbd.h" #include "hal_usbpd.h" #include "sys_config.h"
void sys_init(void) { hal_gpio_init(GPIO_PIN_1, GPIO_MODE_OUTPUT); hal_gpio_init(GPIO_PIN_2, GPIO_MODE_OUTPUT); hal_gpio_init(GPIO_PIN_3, GPIO_MODE_OUTPUT); hal_gpio_init(GPIO_PIN_4, GPIO_MODE_INPUT); hal_gpio_init(GPIO_PIN_5, GPIO_MODE_INPUT); hal_adc_init(ADC_CHANNEL_1); hal_adc_init(ADC_CHANNEL_2); hal_pwm_init(PWM_CHANNEL_1,10000); hal_i2c_init(I2C_PORT_1); hal_timer_init(); hal_usbpd_init(); hal_usbd_init();
sys_config_init();
}
|
(9) SYS层实现 (sys_config.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #ifndef SYS_CONFIG_H #define SYS_CONFIG_H
#include <stdint.h>
typedef enum { LIGHTING_MODE_OFF, LIGHTING_MODE_3W, LIGHTING_MODE_30W, LIGHTING_MODE_60W, LIGHTING_MODE_MAX }lighting_mode_t;
void sys_config_init(void); lighting_mode_t sys_config_get_last_lighting_mode(void); void sys_config_set_last_lighting_mode(lighting_mode_t mode);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include "sys_config.h"
#define CONFIG_ADDR 0x10000000 typedef struct{ uint8_t lighting_mode; }sys_config_data_t; static sys_config_data_t* config_data = (sys_config_data_t*)CONFIG_ADDR;
void sys_config_init(void) { if(config_data->lighting_mode > (LIGHTING_MODE_MAX - 1)){ config_data->lighting_mode = LIGHTING_MODE_OFF; } }
lighting_mode_t sys_config_get_last_lighting_mode(void) { return (lighting_mode_t)config_data->lighting_mode; }
void sys_config_set_last_lighting_mode(lighting_mode_t mode) { config_data->lighting_mode = mode; }
|
(10) MID层实现 (mid_battery.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #ifndef MID_BATTERY_H #define MID_BATTERY_H
#include <stdint.h> #include <stdbool.h>
void mid_battery_init(void);
float mid_battery_get_voltage(void);
uint8_t mid_battery_get_percentage(void);
bool mid_battery_is_low(void);
bool mid_battery_is_full(void);
float mid_battery_get_charging_current(void);
float mid_battery_get_discharging_current(void); #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include "mid_battery.h" #include "hal_adc.h" #include "hal_i2c.h" #include "hal_battery.h" #include "hal_timer.h" #include <math.h>
#define BATTERY_VOLTAGE_ADC_CHANNEL ADC_CHANNEL_1 #define BATTERY_CURRENT_ADC_CHANNEL ADC_CHANNEL_2 #define BATTERY_LOW_VOLTAGE 3.0f #define BATTERY_FULL_VOLTAGE 4.2f #define BATTERY_VOLTAGE_SCALE ((1.0/1024.0)*5.0*(11.0/1.0)) #define BATTERY_CURRENT_SCALE ((1.0/1024.0)*5.0*(1.0/0.01)) #define BATTERY_AVG_TIMES 5
static float battery_voltage_history[BATTERY_AVG_TIMES]; static uint8_t current_index = 0; static float current_voltage = 0.0f;
void mid_battery_init(void) { hal_adc_init(BATTERY_VOLTAGE_ADC_CHANNEL); hal_adc_init(BATTERY_CURRENT_ADC_CHANNEL);
for (int i = 0; i < BATTERY_AVG_TIMES; i++) { battery_voltage_history[i] = 0; } }
float mid_battery_get_voltage(void) { uint16_t adc_value = hal_adc_read(BATTERY_VOLTAGE_ADC_CHANNEL); float voltage = adc_value * BATTERY_VOLTAGE_SCALE; battery_voltage_history[current_index++] = voltage; if(current_index >= BATTERY_AVG_TIMES) current_index = 0; float sum = 0; for (int i = 0; i < BATTERY_AVG_TIMES; i++) { sum += battery_voltage_history[i]; } current_voltage = sum/BATTERY_AVG_TIMES; return current_voltage; }
uint8_t mid_battery_get_percentage(void) { float voltage = mid_battery_get_voltage(); if(voltage <= BATTERY_LOW_VOLTAGE) return 0; if(voltage >= BATTERY_FULL_VOLTAGE) return 100; return (uint8_t)((voltage - BATTERY_LOW_VOLTAGE) / (BATTERY_FULL_VOLTAGE - BATTERY_LOW_VOLTAGE) * 100.0f); }
bool mid_battery_is_low(void) { float voltage = mid_battery_get_voltage(); return voltage <= BATTERY_LOW_VOLTAGE; }
bool mid_battery_is_full(void){ float voltage = mid_battery_get_voltage(); return voltage >= BATTERY_FULL_VOLTAGE; }
float mid_battery_get_charging_current(void){ float current = hal_battery_get_charging_current(); return current; }
float mid_battery_get_discharging_current(void){ float current = hal_battery_get_discharging_current(); return current; }
|
(11) MID层实现 (mid_temp.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #ifndef MID_TEMP_H #define MID_TEMP_H
#include <stdint.h> #include <stdbool.h>
void mid_temp_init(void);
float mid_temp_get_temperature(void);
bool mid_temp_is_overheat(void); #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include "mid_temp.h" #include "hal_adc.h" #include "hal_timer.h" #define TEMP_ADC_CHANNEL ADC_CHANNEL_2 #define TEMP_OVER_THRESHOLD 70.0f #define TEMP_SCALE ((1.0/1024.0)*5.0*1.0/0.01) static float temperature;
void mid_temp_init(void){ hal_adc_init(TEMP_ADC_CHANNEL); }
float mid_temp_get_temperature(void){ uint16_t adc_value = hal_adc_read(TEMP_ADC_CHANNEL); temperature = (float)adc_value * TEMP_SCALE; return temperature; }
bool mid_temp_is_overheat(void){ float temp = mid_temp_get_temperature(); return temp > TEMP_OVER_THRESHOLD; }
|
(12) MID层实现 (mid_fan.c/h
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #ifndef MID_FAN_H #define MID_FAN_H
#include <stdint.h> #include <stdbool.h>
void mid_fan_init(void);
void mid_fan_set_speed(uint8_t speed_percentage);
void mid_fan_enable(bool enable); #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include "mid_fan.h" #include "hal_pwm.h" #define FAN_PWM_CHANNEL PWM_CHANNEL_2 #define FAN_OFF_DUTY 0 static bool is_fan_enable;
void mid_fan_init(void){ hal_pwm_init(FAN_PWM_CHANNEL,10000); is_fan_enable = false; }
void mid_fan_set_speed(uint8_t speed_percentage) { if(!is_fan_enable){ hal_pwm_set_duty(FAN_PWM_CHANNEL,FAN_OFF_DUTY); return; } if(speed_percentage > 100) speed_percentage = 100; uint16_t duty = (uint16_t)(speed_percentage * 100);
hal_pwm_set_duty(FAN_PWM_CHANNEL,duty); }
void mid_fan_enable(bool enable){ is_fan_enable = enable; if(!is_fan_enable){ hal_pwm_set_duty(FAN_PWM_CHANNEL,FAN_OFF_DUTY); return; } }
|