编程技术分享

分享编程知识,探讨技术创新

0%

简介:手电筒的名字是光锤60,支持45w type c充放电,充满约一小时,60w 10000lm档位不降档不烫手,60w续航约27分钟,30w续航54分钟,3w续航8小时,复刻物料成本约110元

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

1. 需求分析

根据项目描述,光锤60手电筒的核心需求如下:

  • 功能需求:
    • 照明: 提供不同功率档位的照明输出,包括60W (10000lm)、30W和3W。
    • 调光: 支持档位切换,并且能记忆上次使用的档位。
    • 恒流: 在不同功率下实现恒流输出,保证亮度稳定。
    • 散热: 主动散热系统,确保60W档位不降档不烫手。
    • 充电: 支持Type-C 45W快充,充满时间约1小时。
    • 放电: 支持Type-C放电功能。
    • 电池管理: 准确检测电池电量,并进行低电量保护。
    • 状态指示: 通过LED指示灯显示电量、充电状态和档位。
    • 保护: 过充、过放、过热、短路保护。
  • 性能需求:
    • 高效率: 高功率输出下的效率,保证续航时间。
    • 快速响应: 按键操作快速响应,档位切换流畅。
    • 稳定可靠: 系统运行稳定可靠,避免死机或异常。
    • 功耗控制: 低功耗待机模式,延长电池寿命。
  • 成本需求:
    • BOM成本控制: 物料成本控制在110元左右。
  • 可扩展性:
    • 软件升级: 支持固件升级,方便后续功能扩展。

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
// hal_gpio.h
#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;


// 初始化GPIO
void hal_gpio_init(gpio_pin_t pin, gpio_mode_t mode);

// 设置GPIO输出状态
void hal_gpio_write(gpio_pin_t pin, gpio_pin_state_t state);

// 读取GPIO输入状态
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
// hal_gpio.c
#include "hal_gpio.h"

// 模拟GPIO初始化,实际需要根据芯片进行修改
void hal_gpio_init(gpio_pin_t pin, gpio_mode_t mode) {
// 模拟初始化
// 根据模式初始化寄存器
if (mode == GPIO_MODE_OUTPUT) {
//配置输出
// 例如: 设置方向寄存器为输出
// * (volatile uint32_t*)(0x40000000) |= (1 << pin);
} else if (mode == GPIO_MODE_INPUT) {
//配置输入
}

}

// 模拟GPIO输出,实际需要根据芯片进行修改
void hal_gpio_write(gpio_pin_t pin, gpio_pin_state_t state) {
// 模拟输出
// 根据state设置寄存器
if (state == GPIO_PIN_HIGH) {
// *(volatile uint32_t*)(0x40000004) |= (1 << pin);
} else {
// *(volatile uint32_t*)(0x40000004) &= ~(1 << pin);
}

}

// 模拟GPIO读取,实际需要根据芯片进行修改
gpio_pin_state_t hal_gpio_read(gpio_pin_t pin) {
// 模拟读取
// 读取寄存器
// if( (*(volatile uint32_t*)(0x40000008) & (1 << pin) )!= 0 )
return GPIO_PIN_LOW; //返回实际读取的IO口状态,这里模拟返回低电平
//else
//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
// hal_adc.h
#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;

// 初始化ADC
void hal_adc_init(adc_channel_t channel);

// 读取ADC值
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
// hal_adc.c
#include "hal_adc.h"

// 模拟ADC初始化
void hal_adc_init(adc_channel_t channel) {
// 模拟初始化
// 根据通道初始化ADC寄存器
}

// 模拟ADC读取
uint16_t hal_adc_read(adc_channel_t channel) {
// 模拟读取
// 读取ADC寄存器
// 实际读取需要进行校准,计算等等
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
// mid_led.h
#ifndef MID_LED_H
#define MID_LED_H

#include <stdint.h>
#include <stdbool.h>

typedef enum {
LED_RED,
LED_GREEN,
LED_BLUE,
//定义其他的LED
LED_MAX
} led_id_t;

// 初始化LED
void mid_led_init(led_id_t id);

// 控制LED状态
void mid_led_set_state(led_id_t id, bool on);

// 闪烁LED
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
// mid_led.c
#include "mid_led.h"
#include "hal_gpio.h"
#include "hal_timer.h"

// 定义LED对应的GPIO
static gpio_pin_t led_gpio_pins[LED_MAX] = {
GPIO_PIN_1, // LED_RED
GPIO_PIN_2, // LED_GREEN
GPIO_PIN_3 // LED_BLUE
};


// 初始化LED
void mid_led_init(led_id_t id) {
if(id >= LED_MAX )
return;

hal_gpio_init(led_gpio_pins[id], GPIO_MODE_OUTPUT);
}

// 控制LED状态
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);
}

// 闪烁LED
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
// mid_key.h
#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
// mid_key.c
#include "mid_key.h"
#include "hal_gpio.h"
#include "hal_timer.h"

// 定义按键对应的GPIO
static gpio_pin_t key_gpio_pins[KEY_MAX] = {
GPIO_PIN_4, // KEY_1
GPIO_PIN_5 // KEY_2
};
//防抖时间,这里定义成10ms
#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
// app_main.c
#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(); // 系统初始化

// 中断必须开启
// EnableInterrupts();

// 初始化模块
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();
//app_ui_update(); //更新ui显示
}
}

(6) APP层实现 (app_lighting.c/h)

1
2
3
4
5
6
7
8
9
// app_lighting.h
#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
// app_lighting.c
#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
// mid_light.h
#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
// mid_light.c
#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; // PWM占空比,根据实际情况调整
uint16_t current_ma; // 恒流电流
} light_mode_config_t;


// 根据实际情况定义不同档位的PWM占空比和电流
static const light_mode_config_t light_modes[] = {
{LIGHTING_MODE_OFF, 0, 0}, // 关闭
{LIGHTING_MODE_3W, 1000, 500}, // 3W,模拟电流500mA
{LIGHTING_MODE_30W, 4000, 3000},// 30W,模拟电流3000mA
{LIGHTING_MODE_60W, 9999, 6000},// 60W,模拟电流6000mA
};

static light_mode_config_t current_mode_config;

void mid_light_init(void) {
hal_pwm_init(LED_PWM_CHANNEL,10000); // 初始化PWM,频率10kHz
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
// sys_init.c
#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) {
// 1. 初始化硬件
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);
// 初始化 ADC,这里初始化2个通道
hal_adc_init(ADC_CHANNEL_1);
hal_adc_init(ADC_CHANNEL_2);
// 初始化 PWM, 这里初始化一个通道
hal_pwm_init(PWM_CHANNEL_1,10000);
// 初始化 i2c, 必须先初始化i2c,才能初始化其他的i2c芯片
hal_i2c_init(I2C_PORT_1);
//初始化定时器
hal_timer_init();
//初始化 USB PD控制器
hal_usbpd_init();
// 初始化 USB 设备
hal_usbd_init();

// 2. 读取配置信息
sys_config_init();

//3. 初始化其他的系统模块

}

(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
// sys_config.h
#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
// sys_config.c
#include "sys_config.h"
// 这里模拟使用内存存储配置,实际使用需要使用Flash或者EEPROM
#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
// mid_battery.h
#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
// mid_battery.c
#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 // 电池电压ADC通道
#define BATTERY_CURRENT_ADC_CHANNEL ADC_CHANNEL_2
#define BATTERY_LOW_VOLTAGE 3.0f // 假设低电量电压为3.0V
#define BATTERY_FULL_VOLTAGE 4.2f //假设电池充满电压为4.2V
#define BATTERY_VOLTAGE_SCALE ((1.0/1024.0)*5.0*(11.0/1.0))// 根据实际的ADC分压电路计算
#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) {
// 初始化ADC通道
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
// mid_temp.h
#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
// mid_temp.c
#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
// mid_fan.h
#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
// mid_fan.c
#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;
}
}

欢迎关注我的其它发布渠道