编程技术分享

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

0%

简介:基于富满FM8118芯片制作的加湿器、雾化器模块,配合小黄人节日造型,平添更多乐趣。祝大家新年快乐!

好的,作为一名高级嵌入式软件开发工程师,我将针对您提供的基于富满FM8118芯片的加湿器/雾化器项目,详细阐述最适合的代码设计架构,并提供具体的C代码实现。这个项目旨在创建一个可靠、高效、可扩展的嵌入式系统平台,涵盖从需求分析到系统实现、测试验证以及维护升级的完整开发流程。
关注微信公众号,提前获取相关推文

项目背景与需求分析

项目背景:

本项目基于富满FM8118芯片,旨在开发一款嵌入式加湿器/雾化器模块。该模块以小黄人节日造型为设计灵感,旨在为用户带来乐趣的同时,提供加湿和雾化功能。项目需体现完整的嵌入式系统开发流程,并采用经过实践验证的技术和方法,确保系统的可靠性、高效性和可扩展性。

需求分析:

  1. 核心功能需求:

    • 加湿/雾化功能: 控制FM8118芯片,驱动雾化片产生水雾,实现加湿或雾化效果。
    • 模式控制: 支持多种工作模式,例如:
      • 连续雾化模式: 持续产生雾化效果。
      • 间歇雾化模式: 间歇性产生雾化效果,可设置工作和停止时间。
      • 智能雾化模式: 根据环境湿度自动调节雾化强度(如果硬件支持湿度传感器,本项目示例简化,暂不包含)。
    • 雾量调节: 能够调节雾量大小,通常通过PWM控制FM8118芯片的驱动强度实现。
    • 定时功能: 支持定时工作,例如设定工作时长后自动停止。
    • 缺水检测与保护: 检测水箱水位,当水位过低时,停止雾化并进行提示(如果硬件支持水位传感器,本项目示例简化,暂不包含)。
    • 指示功能: 通过LED指示灯或其他方式显示设备的工作状态、模式等。
    • 按键/触摸控制: 通过按键或触摸方式进行模式切换、雾量调节、定时设置等操作。
    • 节日氛围灯效(可选): 配合小黄人造型,增加节日氛围灯效,例如RGB LED控制(本项目示例简化,暂不包含)。
  2. 非功能需求:

    • 可靠性: 系统运行稳定可靠,不易出现故障。
    • 高效性: 代码执行效率高,资源占用率低,响应速度快。
    • 可扩展性: 代码架构设计应具备良好的可扩展性,方便后续添加新功能或修改现有功能。
    • 可维护性: 代码结构清晰,注释完善,易于理解和维护。
    • 安全性: 系统运行安全,避免出现意外情况,例如过热、短路等(硬件层面安全设计为主,软件配合)。
    • 低功耗: 在满足功能需求的前提下,尽量降低功耗,延长设备使用时间。
  3. 硬件平台:

    • 主控芯片: 选择合适的MCU,例如STM32、ESP32等,根据项目需求选择性能和资源匹配的型号。
    • 雾化驱动芯片: 富满FM8118。
    • 外围器件: 按键、LED指示灯、电源模块、雾化片、水箱、水位传感器(可选)、湿度传感器(可选)、RGB LED(可选)等。

代码设计架构

为了实现可靠、高效、可扩展的系统平台,并满足上述需求,我推荐采用分层架构的代码设计模式。分层架构能够将系统划分为多个独立的层次,每个层次负责不同的功能,层与层之间通过明确的接口进行通信。这种架构具有以下优点:

  • 模块化: 每个层次都是一个独立的模块,易于理解、开发、测试和维护。
  • 高内聚、低耦合: 每个模块内部功能内聚,模块之间耦合度低,降低了模块之间的依赖性,提高了代码的灵活性和可维护性。
  • 可重用性: 底层模块可以被多个上层模块复用,提高了代码的重用率。
  • 可扩展性: 可以方便地添加新的层次或模块,扩展系统功能。
  • 易于测试: 可以对每个层次进行独立的单元测试,提高了代码的质量。

本项目采用的分层架构如下:

  1. 硬件抽象层 (HAL - Hardware Abstraction Layer):

    • 负责直接与硬件交互,提供统一的硬件操作接口,屏蔽底层硬件的差异。
    • 包括GPIO、定时器、PWM、ADC、UART、SPI、I2C等底层硬件驱动。
    • 目标是使上层应用代码无需关心具体的硬件细节,只需调用HAL层提供的接口即可操作硬件。
  2. 设备驱动层 (Device Driver Layer):

    • 基于HAL层提供的接口,实现对具体硬件设备的驱动。
    • 例如:FM8118芯片驱动、按键驱动、LED驱动、传感器驱动等。
    • 驱动层负责设备的初始化、配置、数据读写等操作,向上层提供设备的功能接口。
  3. 服务层 (Service Layer):

    • 在设备驱动层之上,提供更高级别的业务服务,封装复杂的业务逻辑。
    • 例如:雾化控制服务、模式管理服务、定时服务、指示灯控制服务、按键处理服务等。
    • 服务层负责组合和协调底层驱动,实现特定的业务功能。
  4. 应用层 (Application Layer):

    • 最上层,负责实现具体的应用逻辑,调用服务层提供的接口,完成用户的功能需求。
    • 例如:主循环、用户交互逻辑、模式切换、参数设置等。
    • 应用层是整个系统的核心,直接面向用户,实现系统的最终功能。

代码实现 (C语言)

以下是基于上述分层架构的C代码实现,代码量超过3000行,包含详细的注释和说明,力求清晰易懂,并体现嵌入式系统开发的最佳实践。

1. 硬件抽象层 (HAL)

hal_gpio.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
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
#ifndef HAL_GPIO_H
#define HAL_GPIO_H

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

// GPIO 端口定义 (根据实际MCU芯片修改)
typedef enum {
GPIO_PORT_A,
GPIO_PORT_B,
GPIO_PORT_C,
// ... 其他端口
GPIO_PORT_MAX
} GPIO_Port;

// GPIO 引脚定义 (根据实际MCU芯片修改)
typedef enum {
GPIO_PIN_0 = (1 << 0),
GPIO_PIN_1 = (1 << 1),
GPIO_PIN_2 = (1 << 2),
GPIO_PIN_3 = (1 << 3),
GPIO_PIN_4 = (1 << 4),
GPIO_PIN_5 = (1 << 5),
GPIO_PIN_6 = (1 << 6),
GPIO_PIN_7 = (1 << 7),
GPIO_PIN_8 = (1 << 8),
GPIO_PIN_9 = (1 << 9),
GPIO_PIN_10 = (1 << 10),
GPIO_PIN_11 = (1 << 11),
GPIO_PIN_12 = (1 << 12),
GPIO_PIN_13 = (1 << 13),
GPIO_PIN_14 = (1 << 14),
GPIO_PIN_15 = (1 << 15),
GPIO_PIN_ALL = 0xFFFF
} GPIO_Pin;

// GPIO 工作模式定义
typedef enum {
GPIO_MODE_INPUT, // 输入模式
GPIO_MODE_OUTPUT, // 输出模式
GPIO_MODE_INPUT_PULLUP, // 输入上拉
GPIO_MODE_INPUT_PULLDOWN // 输入下拉
} GPIO_Mode;

// GPIO 输出类型定义
typedef enum {
GPIO_OUTPUT_TYPE_PP, // 推挽输出
GPIO_OUTPUT_TYPE_OD // 开漏输出
} GPIO_OutputType;

// GPIO 速度定义 (根据实际MCU芯片修改)
typedef enum {
GPIO_SPEED_LOW,
GPIO_SPEED_MEDIUM,
GPIO_SPEED_HIGH,
GPIO_SPEED_VERY_HIGH
} GPIO_Speed;

// GPIO 初始化结构体
typedef struct {
GPIO_Port Port; // GPIO 端口
GPIO_Pin Pin; // GPIO 引脚
GPIO_Mode Mode; // GPIO 模式
GPIO_OutputType OutputType; // GPIO 输出类型 (仅输出模式有效)
GPIO_Speed Speed; // GPIO 速度 (仅输出模式有效)
} GPIO_InitTypeDef;

// 初始化 GPIO
void HAL_GPIO_Init(GPIO_InitTypeDef *GPIO_InitStruct);

// 设置 GPIO 输出电平
void HAL_GPIO_WritePin(GPIO_Port Port, GPIO_Pin Pin, bool PinState);

// 读取 GPIO 输入电平
bool HAL_GPIO_ReadPin(GPIO_Port Port, GPIO_Pin Pin);

// 切换 GPIO 输出电平
void HAL_GPIO_TogglePin(GPIO_Port Port, GPIO_Pin Pin);

#endif // HAL_GPIO_H

hal_gpio.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
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
83
#include "hal_gpio.h"

// 初始化 GPIO
void HAL_GPIO_Init(GPIO_InitTypeDef *GPIO_InitStruct) {
// *** 硬件相关代码 ***
// 根据 GPIO_InitStruct 中的配置,初始化 GPIO 寄存器
// 例如:使能时钟、配置模式、输出类型、速度等

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
if (GPIO_InitStruct->Port == GPIO_PORT_A) {
// 使能 GPIOA 时钟
// ...
} else if (GPIO_InitStruct->Port == GPIO_PORT_B) {
// 使能 GPIOB 时钟
// ...
}
// ... 其他端口

// 配置 GPIO 引脚模式
// ...

// 配置 GPIO 输出类型和速度 (仅输出模式)
if (GPIO_InitStruct->Mode == GPIO_MODE_OUTPUT) {
// ...
if (GPIO_InitStruct->OutputType == GPIO_OUTPUT_TYPE_PP) {
// 配置推挽输出
// ...
} else if (GPIO_InitStruct->OutputType == GPIO_OUTPUT_TYPE_OD) {
// 配置开漏输出
// ...
}
// 配置 GPIO 速度
// ...
}

// 配置 GPIO 上下拉 (仅输入模式)
if (GPIO_InitStruct->Mode == GPIO_MODE_INPUT_PULLUP) {
// 配置上拉
// ...
} else if (GPIO_InitStruct->Mode == GPIO_MODE_INPUT_PULLDOWN) {
// 配置下拉
// ...
}
}

// 设置 GPIO 输出电平
void HAL_GPIO_WritePin(GPIO_Port Port, GPIO_Pin Pin, bool PinState) {
// *** 硬件相关代码 ***
// 根据 PinState 设置 GPIO 引脚的输出电平 (高或低)

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
if (PinState == true) {
// 设置 GPIO 引脚为高电平
// ...
} else {
// 设置 GPIO 引脚为低电平
// ...
}
}

// 读取 GPIO 输入电平
bool HAL_GPIO_ReadPin(GPIO_Port Port, GPIO_Pin Pin) {
// *** 硬件相关代码 ***
// 读取 GPIO 引脚的输入电平,并返回 true (高电平) 或 false (低电平)

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 读取 GPIO 引脚状态寄存器
// ...
// 返回读取到的电平状态
return false; // 示例返回,需要根据实际情况修改
}

// 切换 GPIO 输出电平
void HAL_GPIO_TogglePin(GPIO_Port Port, GPIO_Pin Pin) {
// *** 硬件相关代码 ***
// 切换 GPIO 引脚的输出电平 (高低电平翻转)

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 读取当前 GPIO 引脚状态
bool current_state = HAL_GPIO_ReadPin(Port, Pin);
// 设置相反的状态
HAL_GPIO_WritePin(Port, Pin, !current_state);
}

hal_timer.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
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
#ifndef HAL_TIMER_H
#define HAL_TIMER_H

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

// 定时器通道定义 (根据实际MCU芯片修改)
typedef enum {
TIMER_CHANNEL_1,
TIMER_CHANNEL_2,
TIMER_CHANNEL_3,
TIMER_CHANNEL_4,
// ... 其他通道
TIMER_CHANNEL_MAX
} Timer_Channel;

// 定时器模式定义
typedef enum {
TIMER_MODE_TIMEBASE, // 基本定时器模式
TIMER_MODE_PWM_OUTPUT // PWM 输出模式
} Timer_Mode;

// 定时器 PWM 输出极性定义
typedef enum {
TIMER_PWM_POLARITY_HIGH, // 高电平有效
TIMER_PWM_POLARITY_LOW // 低电平有效
} Timer_PWM_Polarity;

// 定时器初始化结构体
typedef struct {
uint32_t TimerInstance; // 定时器实例 (例如 TIM1, TIM2, ...)
Timer_Mode Mode; // 定时器模式
uint32_t Prescaler; // 预分频值
uint32_t Period; // 计数周期 (ARR)
Timer_Channel Channel; // PWM 输出通道 (仅 PWM 模式有效)
Timer_PWM_Polarity PWM_Polarity; // PWM 输出极性 (仅 PWM 模式有效)
} TIMER_InitTypeDef;

// 初始化定时器
void HAL_TIM_Init(TIMER_InitTypeDef *TIMER_InitStruct);

// 启动定时器
void HAL_TIM_Start(uint32_t TimerInstance);

// 停止定时器
void HAL_TIM_Stop(uint32_t TimerInstance);

// 设置 PWM 占空比 (百分比,0-100)
void HAL_TIM_PWM_SetDutyCycle(uint32_t TimerInstance, Timer_Channel Channel, uint8_t DutyCycle);

// 启动 PWM 输出
void HAL_TIM_PWM_Start(uint32_t TimerInstance, Timer_Channel Channel);

// 停止 PWM 输出
void HAL_TIM_PWM_Stop(uint32_t TimerInstance, Timer_Channel Channel);

// 获取当前定时器计数值
uint32_t HAL_TIM_GetCounter(uint32_t TimerInstance);

// 设置定时器计数值
void HAL_TIM_SetCounter(uint32_t TimerInstance, uint32_t Counter);

// 延时函数 (基于定时器,单位:毫秒)
void HAL_Delay_ms(uint32_t Delay);

#endif // HAL_TIMER_H

hal_timer.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
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "hal_timer.h"
#include "system_clock.h" // 假设有系统时钟配置头文件

// 初始化定时器
void HAL_TIM_Init(TIMER_InitTypeDef *TIMER_InitStruct) {
// *** 硬件相关代码 ***
// 根据 TIMER_InitStruct 中的配置,初始化定时器寄存器
// 例如:使能时钟、配置预分频器、计数周期、模式等

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
if (TIMER_InitStruct->TimerInstance == TIM1) {
// 使能 TIM1 时钟
// ...
} else if (TIMER_InitStruct->TimerInstance == TIM2) {
// 使能 TIM2 时钟
// ...
}
// ... 其他定时器

// 配置预分频器
// ...
// 配置计数周期 (ARR)
// ...

if (TIMER_InitStruct->Mode == TIMER_MODE_PWM_OUTPUT) {
// 配置为 PWM 输出模式
// ...
// 选择 PWM 输出通道
// ...
// 配置 PWM 极性
// ...
} else if (TIMER_InitStruct->Mode == TIMER_MODE_TIMEBASE) {
// 配置为基本定时器模式
// ...
}
}

// 启动定时器
void HAL_TIM_Start(uint32_t TimerInstance) {
// *** 硬件相关代码 ***
// 启动定时器计数

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 设置定时器控制寄存器,启动计数
// ...
}

// 停止定时器
void HAL_TIM_Stop(uint32_t TimerInstance) {
// *** 硬件相关代码 ***
// 停止定时器计数

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 设置定时器控制寄存器,停止计数
// ...
}

// 设置 PWM 占空比 (百分比,0-100)
void HAL_TIM_PWM_SetDutyCycle(uint32_t TimerInstance, Timer_Channel Channel, uint8_t DutyCycle) {
// *** 硬件相关代码 ***
// 根据 DutyCycle 计算 PWM 占空比对应的 CCR 值,并设置 CCR 寄存器

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 获取定时器周期 (ARR)
uint32_t period = /* ... 获取 ARR 值 ... */;
// 计算 CCR 值
uint32_t ccr_value = (period * DutyCycle) / 100;
// 设置 CCR 寄存器 (例如 CCR1, CCR2, ...)
if (Channel == TIMER_CHANNEL_1) {
// 设置 CCR1
// ...
} else if (Channel == TIMER_CHANNEL_2) {
// 设置 CCR2
// ...
}
// ... 其他通道
}

// 启动 PWM 输出
void HAL_TIM_PWM_Start(uint32_t TimerInstance, Timer_Channel Channel) {
// *** 硬件相关代码 ***
// 启动 PWM 输出通道

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 使能 PWM 输出通道 (例如 CCER 寄存器)
// ...
// 启动定时器 (如果定时器未启动)
HAL_TIM_Start(TimerInstance);
}

// 停止 PWM 输出
void HAL_TIM_PWM_Stop(uint32_t TimerInstance, Timer_Channel Channel) {
// *** 硬件相关代码 ***
// 停止 PWM 输出通道

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 禁用 PWM 输出通道 (例如 CCER 寄存器)
// ...
}

// 获取当前定时器计数值
uint32_t HAL_TIM_GetCounter(uint32_t TimerInstance) {
// *** 硬件相关代码 ***
// 读取定时器计数器寄存器 (CNT) 并返回

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 读取 CNT 寄存器
// ...
return 0; // 示例返回,需要根据实际情况修改
}

// 设置定时器计数值
void HAL_TIM_SetCounter(uint32_t TimerInstance, uint32_t Counter) {
// *** 硬件相关代码 ***
// 设置定时器计数器寄存器 (CNT)

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 设置 CNT 寄存器
// ...
}

// 延时函数 (基于定时器,单位:毫秒)
void HAL_Delay_ms(uint32_t Delay) {
// 使用定时器实现精确延时

// 配置定时器为 TIMEBASE 模式,预分频器和周期根据系统时钟和延时时间计算
TIMER_InitTypeDef timer_init;
timer_init.TimerInstance = TIM6; // 选择一个通用定时器,例如 TIM6
timer_init.Mode = TIMER_MODE_TIMEBASE;
timer_init.Prescaler = SystemCoreClock / 1000000 - 1; // 假设系统时钟为 SystemCoreClock Hz,预分频到 1MHz (1us 计数)
timer_init.Period = Delay * 1000; // 延时 Delay 毫秒,计数 Delay * 1000 us

HAL_TIM_Init(&timer_init);
HAL_TIM_SetCounter(timer_init.TimerInstance, 0); // 清零计数器
HAL_TIM_Start(timer_init.TimerInstance); // 启动定时器

// 等待定时器计数达到 Period 值
while (HAL_TIM_GetCounter(timer_init.TimerInstance) < timer_init.Period);

HAL_TIM_Stop(timer_init.TimerInstance); // 停止定时器
}

2. 设备驱动层 (Device Driver Layer)

drv_fm8118.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
#ifndef DRV_FM8118_H
#define DRV_FM8118_H

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

// FM8118 控制引脚定义 (根据实际硬件连接修改)
#define FM8118_PWM_PORT GPIO_PORT_A
#define FM8118_PWM_PIN GPIO_PIN_0
#define FM8118_EN_PORT GPIO_PORT_A
#define FM8118_EN_PIN GPIO_PIN_1
#define FM8118_FAULT_PORT GPIO_PORT_A // 如果有故障检测引脚
#define FM8118_FAULT_PIN GPIO_PIN_2 // 如果有故障检测引脚

// FM8118 初始化
void DRV_FM8118_Init(void);

// 设置雾量等级 (0-100, 0: 关闭, 100: 最大雾量)
void DRV_FM8118_SetMistLevel(uint8_t level);

// 启动雾化
void DRV_FM8118_StartMist(void);

// 停止雾化
void DRV_FM8118_StopMist(void);

// 获取 FM8118 故障状态 (如果有故障检测引脚)
bool DRV_FM8118_GetFaultStatus(void);

#endif // DRV_FM8118_H

drv_fm8118.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
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
#include "drv_fm8118.h"
#include "hal_gpio.h"
#include "hal_timer.h"

// PWM 定时器配置 (根据实际硬件选择合适的定时器和通道)
#define FM8118_PWM_TIMER_INSTANCE TIM3
#define FM8118_PWM_TIMER_CHANNEL TIMER_CHANNEL_1

// FM8118 初始化
void DRV_FM8118_Init(void) {
// 初始化 FM8118 控制引脚

// 使能引脚配置为输出,并默认关闭 FM8118
GPIO_InitTypeDef gpio_init;
gpio_init.Port = FM8118_EN_PORT;
gpio_init.Pin = FM8118_EN_PIN;
gpio_init.Mode = GPIO_MODE_OUTPUT;
gpio_init.OutputType = GPIO_OUTPUT_TYPE_PP;
gpio_init.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(&gpio_init);
HAL_GPIO_WritePin(FM8118_EN_PORT, FM8118_EN_PIN, false); // 默认关闭

// PWM 引脚配置为复用功能,连接到 PWM 定时器输出
gpio_init.Port = FM8118_PWM_PORT;
gpio_init.Pin = FM8118_PWM_PIN;
gpio_init.Mode = GPIO_MODE_OUTPUT; // 根据 MCU 的 PWM 复用功能配置,可能需要配置为复用推挽输出
gpio_init.OutputType = GPIO_OUTPUT_TYPE_PP;
gpio_init.Speed = GPIO_SPEED_HIGH; // PWM 频率可能较高,选择高速
HAL_GPIO_Init(&gpio_init);

// 初始化 PWM 定时器
TIMER_InitTypeDef timer_init;
timer_init.TimerInstance = FM8118_PWM_TIMER_INSTANCE;
timer_init.Mode = TIMER_MODE_PWM_OUTPUT;
timer_init.Prescaler = /* ... 根据需要的 PWM 频率计算预分频值 ... */; // 例如,目标频率 20kHz
timer_init.Period = /* ... 根据需要的 PWM 分辨率计算周期值 ... */; // 例如,周期值 1000,分辨率 1000 级
timer_init.Channel = FM8118_PWM_TIMER_CHANNEL;
timer_init.PWM_Polarity = TIMER_PWM_POLARITY_HIGH; // 假设高电平有效
HAL_TIM_Init(&timer_init);

// 停止 PWM 输出,默认关闭雾化
DRV_FM8118_StopMist();
}

// 设置雾量等级 (0-100, 0: 关闭, 100: 最大雾量)
void DRV_FM8118_SetMistLevel(uint8_t level) {
if (level > 100) {
level = 100; // 限制最大值
}
HAL_TIM_PWM_SetDutyCycle(FM8118_PWM_TIMER_INSTANCE, FM8118_PWM_TIMER_CHANNEL, level);
}

// 启动雾化
void DRV_FM8118_StartMist(void) {
HAL_GPIO_WritePin(FM8118_EN_PORT, FM8118_EN_PIN, true); // 使能 FM8118
HAL_TIM_PWM_Start(FM8118_PWM_TIMER_INSTANCE, FM8118_PWM_TIMER_CHANNEL); // 启动 PWM 输出
}

// 停止雾化
void DRV_FM8118_StopMist(void) {
HAL_GPIO_WritePin(FM8118_EN_PORT, FM8118_EN_PIN, false); // 禁用 FM8118
HAL_TIM_PWM_Stop(FM8118_PWM_TIMER_INSTANCE, FM8118_PWM_TIMER_CHANNEL); // 停止 PWM 输出
DRV_FM8118_SetMistLevel(0); // 确保占空比为 0,完全关闭
}

// 获取 FM8118 故障状态 (如果有故障检测引脚)
bool DRV_FM8118_GetFaultStatus(void) {
// 如果 FM8118 有故障检测引脚,则读取该引脚电平
// 根据实际硬件连接和 FM8118 数据手册确定故障状态逻辑 (高电平/低电平表示故障)

// 示例 (假设低电平表示故障)
if (FM8118_FAULT_PORT != GPIO_PORT_MAX) { // 检查是否定义了故障检测引脚
return !HAL_GPIO_ReadPin(FM8118_FAULT_PORT, FM8118_FAULT_PIN); // 低电平返回 true (故障)
} else {
return false; // 没有故障检测引脚,默认返回 false (无故障)
}
}

drv_button.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
#ifndef DRV_BUTTON_H
#define DRV_BUTTON_H

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

// 按键定义 (根据实际硬件连接修改)
typedef enum {
BUTTON_MODE, // 模式切换按键
BUTTON_MIST_UP, // 雾量增加按键
BUTTON_MIST_DOWN, // 雾量减少按键
BUTTON_TIMER, // 定时按键
BUTTON_MAX
} Button_TypeDef;

// 按键初始化
void DRV_Button_Init(void);

// 获取按键状态 (按下返回 true, 释放返回 false)
bool DRV_Button_GetState(Button_TypeDef button);

// 按键事件处理函数类型定义
typedef void (*ButtonEventHandler)(Button_TypeDef button);

// 注册按键事件处理函数
void DRV_Button_RegisterEventHandler(ButtonEventHandler handler);

#endif // DRV_BUTTON_H

drv_button.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
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "drv_button.h"
#include "hal_gpio.h"
#include "hal_timer.h"

// 按键引脚定义 (根据实际硬件连接修改)
#define BUTTON_MODE_PORT GPIO_PORT_B
#define BUTTON_MODE_PIN GPIO_PIN_0
#define BUTTON_MIST_UP_PORT GPIO_PORT_B
#define BUTTON_MIST_UP_PIN GPIO_PIN_1
#define BUTTON_MIST_DOWN_PORT GPIO_PORT_B
#define BUTTON_MIST_DOWN_PIN GPIO_PIN_2
#define BUTTON_TIMER_PORT GPIO_PORT_B
#define BUTTON_TIMER_PIN GPIO_PIN_3

// 按键去抖动延时 (毫秒)
#define BUTTON_DEBOUNCE_DELAY_MS 20

// 按键状态变量
static bool button_state[BUTTON_MAX] = {false};
static ButtonEventHandler button_event_handler = NULL; // 按键事件处理函数指针

// 按键初始化
void DRV_Button_Init(void) {
// 初始化按键引脚为输入上拉模式

GPIO_InitTypeDef gpio_init;
gpio_init.Mode = GPIO_MODE_INPUT_PULLUP;
gpio_init.Speed = GPIO_SPEED_LOW;

gpio_init.Port = BUTTON_MODE_PORT;
gpio_init.Pin = BUTTON_MODE_PIN;
HAL_GPIO_Init(&gpio_init);

gpio_init.Port = BUTTON_MIST_UP_PORT;
gpio_init.Pin = BUTTON_MIST_UP_PIN;
HAL_GPIO_Init(&gpio_init);

gpio_init.Port = BUTTON_MIST_DOWN_PORT;
gpio_init.Pin = BUTTON_MIST_DOWN_PIN;
HAL_GPIO_Init(&gpio_init);

gpio_init.Port = BUTTON_TIMER_PORT;
gpio_init.Pin = BUTTON_TIMER_PIN;
HAL_GPIO_Init(&gpio_init);
}

// 获取按键状态 (按下返回 true, 释放返回 false)
bool DRV_Button_GetState(Button_TypeDef button) {
GPIO_Port port;
GPIO_Pin pin;

switch (button) {
case BUTTON_MODE:
port = BUTTON_MODE_PORT;
pin = BUTTON_MODE_PIN;
break;
case BUTTON_MIST_UP:
port = BUTTON_MIST_UP_PORT;
pin = BUTTON_MIST_UP_PIN;
break;
case BUTTON_MIST_DOWN:
port = BUTTON_MIST_DOWN_PORT;
pin = BUTTON_MIST_DOWN_PIN;
break;
case BUTTON_TIMER:
port = BUTTON_TIMER_PORT;
pin = BUTTON_TIMER_PIN;
break;
default:
return false; // 默认返回 false
}

// 读取按键引脚电平 (上拉模式,按下为低电平)
return !HAL_GPIO_ReadPin(port, pin); // 按下返回 true
}

// 注册按键事件处理函数
void DRV_Button_RegisterEventHandler(ButtonEventHandler handler) {
button_event_handler = handler;
}

// 按键扫描任务 (建议在主循环中周期性调用)
void DRV_Button_ScanTask(void) {
for (int i = 0; i < BUTTON_MAX; i++) {
bool current_state = DRV_Button_GetState((Button_TypeDef)i);

if (current_state != button_state[i]) {
HAL_Delay_ms(BUTTON_DEBOUNCE_DELAY_MS); // 去抖动延时
if (DRV_Button_GetState((Button_TypeDef)i) == current_state) {
button_state[i] = current_state;
if (button_state[i] && button_event_handler != NULL) { // 按下事件,且注册了事件处理函数
button_event_handler((Button_TypeDef)i); // 调用事件处理函数
}
}
}
}
}

drv_led.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef DRV_LED_H
#define DRV_LED_H

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

// LED 定义 (根据实际硬件连接修改)
typedef enum {
LED_STATUS, // 状态指示 LED
LED_MODE, // 模式指示 LED
LED_MAX
} LED_TypeDef;

// LED 初始化
void DRV_LED_Init(void);

// 设置 LED 状态 (true: 亮, false: 灭)
void DRV_LED_SetState(LED_TypeDef led, bool state);

// 切换 LED 状态
void DRV_LED_Toggle(LED_TypeDef led);

#endif // DRV_LED_H

drv_led.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
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
#include "drv_led.h"
#include "hal_gpio.h"

// LED 引脚定义 (根据实际硬件连接修改)
#define LED_STATUS_PORT GPIO_PORT_C
#define LED_STATUS_PIN GPIO_PIN_0
#define LED_MODE_PORT GPIO_PORT_C
#define LED_MODE_PIN GPIO_PIN_1

// LED 初始化
void DRV_LED_Init(void) {
// 初始化 LED 引脚为推挽输出,默认关闭

GPIO_InitTypeDef gpio_init;
gpio_init.Mode = GPIO_MODE_OUTPUT;
gpio_init.OutputType = GPIO_OUTPUT_TYPE_PP;
gpio_init.Speed = GPIO_SPEED_LOW;

gpio_init.Port = LED_STATUS_PORT;
gpio_init.Pin = LED_STATUS_PIN;
HAL_GPIO_Init(&gpio_init);
DRV_LED_SetState(LED_STATUS, false); // 默认关闭

gpio_init.Port = LED_MODE_PORT;
gpio_init.Pin = LED_MODE_PIN;
HAL_GPIO_Init(&gpio_init);
DRV_LED_SetState(LED_MODE, false); // 默认关闭
}

// 设置 LED 状态 (true: 亮, false: 灭)
void DRV_LED_SetState(LED_TypeDef led, bool state) {
GPIO_Port port;
GPIO_Pin pin;

switch (led) {
case LED_STATUS:
port = LED_STATUS_PORT;
pin = LED_STATUS_PIN;
break;
case LED_MODE:
port = LED_MODE_PORT;
pin = LED_MODE_PIN;
break;
default:
return; // 无效 LED
}

HAL_GPIO_WritePin(port, pin, state); // 设置 LED 状态
}

// 切换 LED 状态
void DRV_LED_Toggle(LED_TypeDef led) {
GPIO_Port port;
GPIO_Pin pin;

switch (led) {
case LED_STATUS:
port = LED_STATUS_PORT;
pin = LED_STATUS_PIN;
break;
case LED_MODE:
port = LED_MODE_PORT;
pin = LED_MODE_PIN;
break;
default:
return; // 无效 LED
}

HAL_GPIO_TogglePin(port, pin); // 切换 LED 状态
}

3. 服务层 (Service Layer)

svc_humidifier.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
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
#ifndef SVC_HUMIDIFIER_H
#define SVC_HUMIDIFIER_H

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

// 雾化模式定义
typedef enum {
HUMIDIFIER_MODE_CONTINUOUS, // 连续雾化模式
HUMIDIFIER_MODE_INTERMITTENT, // 间歇雾化模式
HUMIDIFIER_MODE_MAX
} Humidifier_Mode;

// 雾量等级范围
#define HUMIDIFIER_MIST_LEVEL_MIN 0
#define HUMIDIFIER_MIST_LEVEL_MAX 100

// 间歇模式工作参数
typedef struct {
uint32_t work_time_ms; // 工作时长 (毫秒)
uint32_t stop_time_ms; // 停止时长 (毫秒)
} IntermittentModeConfig;

// 定时模式参数
typedef struct {
uint32_t timer_duration_ms; // 定时时长 (毫秒)
} TimerModeConfig;

// 初始化加湿器服务
void SVC_Humidifier_Init(void);

// 设置雾化模式
void SVC_Humidifier_SetMode(Humidifier_Mode mode);

// 获取当前雾化模式
Humidifier_Mode SVC_Humidifier_GetMode(void);

// 设置雾量等级 (0-100)
void SVC_Humidifier_SetMistLevel(uint8_t level);

// 获取当前雾量等级
uint8_t SVC_Humidifier_GetMistLevel(void);

// 设置间歇模式参数
void SVC_Humidifier_SetIntermittentModeConfig(const IntermittentModeConfig *config);

// 获取间歇模式参数
void SVC_Humidifier_GetIntermittentModeConfig(IntermittentModeConfig *config);

// 设置定时模式参数
void SVC_Humidifier_SetTimerModeConfig(const TimerModeConfig *config);

// 获取定时模式参数
void SVC_Humidifier_GetTimerModeConfig(TimerModeConfig *config);

// 启动雾化
void SVC_Humidifier_StartMist(void);

// 停止雾化
void SVC_Humidifier_StopMist(void);

// 加湿器服务任务 (需要在主循环中周期性调用)
void SVC_Humidifier_Task(void);

#endif // SVC_HUMIDIFIER_H

svc_humidifier.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
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "svc_humidifier.h"
#include "drv_fm8118.h"
#include "drv_led.h"
#include "hal_timer.h"

// 默认雾量等级
#define DEFAULT_MIST_LEVEL 50

// 默认间歇模式配置
static const IntermittentModeConfig default_intermittent_config = {
.work_time_ms = 3000, // 3 秒工作
.stop_time_ms = 2000, // 2 秒停止
};

// 默认定时模式配置 (无定时)
static const TimerModeConfig default_timer_config = {
.timer_duration_ms = 0, // 0 表示不定时
};

// 当前雾化模式
static Humidifier_Mode current_mode = HUMIDIFIER_MODE_CONTINUOUS;
// 当前雾量等级
static uint8_t current_mist_level = DEFAULT_MIST_LEVEL;
// 间歇模式配置
static IntermittentModeConfig intermittent_config = default_intermittent_config;
// 定时模式配置
static TimerModeConfig timer_config = default_timer_config;
// 间歇模式状态
static bool intermittent_mode_working = false;
static uint32_t intermittent_mode_timer = 0;
// 定时模式状态
static bool timer_mode_active = false;
static uint32_t timer_mode_start_time = 0;

// 初始化加湿器服务
void SVC_Humidifier_Init(void) {
DRV_FM8118_Init(); // 初始化 FM8118 驱动
DRV_LED_Init(); // 初始化 LED 驱动
SVC_Humidifier_SetMistLevel(DEFAULT_MIST_LEVEL); // 设置默认雾量等级
SVC_Humidifier_SetMode(HUMIDIFIER_MODE_CONTINUOUS); // 设置默认模式为连续雾化
SVC_Humidifier_StopMist(); // 默认停止雾化
}

// 设置雾化模式
void SVC_Humidifier_SetMode(Humidifier_Mode mode) {
if (mode < HUMIDIFIER_MODE_MAX) {
current_mode = mode;
DRV_LED_SetState(LED_MODE, (mode != HUMIDIFIER_MODE_CONTINUOUS)); // 模式 LED 指示
}
}

// 获取当前雾化模式
Humidifier_Mode SVC_Humidifier_GetMode(void) {
return current_mode;
}

// 设置雾量等级 (0-100)
void SVC_Humidifier_SetMistLevel(uint8_t level) {
if (level >= HUMIDIFIER_MIST_LEVEL_MIN && level <= HUMIDIFIER_MIST_LEVEL_MAX) {
current_mist_level = level;
DRV_FM8118_SetMistLevel(current_mist_level);
}
}

// 获取当前雾量等级
uint8_t SVC_Humidifier_GetMistLevel(void) {
return current_mist_level;
}

// 设置间歇模式参数
void SVC_Humidifier_SetIntermittentModeConfig(const IntermittentModeConfig *config) {
if (config != NULL) {
intermittent_config = *config;
} else {
intermittent_config = default_intermittent_config; // 使用默认配置
}
}

// 获取间歇模式参数
void SVC_Humidifier_GetIntermittentModeConfig(IntermittentModeConfig *config) {
if (config != NULL) {
*config = intermittent_config;
}
}

// 设置定时模式参数
void SVC_Humidifier_SetTimerModeConfig(const TimerModeConfig *config) {
if (config != NULL) {
timer_config = *config;
} else {
timer_config = default_timer_config; // 使用默认配置 (无定时)
}
}

// 获取定时模式参数
void SVC_Humidifier_GetTimerModeConfig(TimerModeConfig *config) {
if (config != NULL) {
*config = timer_config;
}
}

// 启动雾化
void SVC_Humidifier_StartMist(void) {
DRV_FM8118_StartMist();
DRV_LED_SetState(LED_STATUS, true); // 状态 LED 指示
timer_mode_start_time = HAL_TIM_GetCounter(TIM6); // 记录定时开始时间 (假设 TIM6 用于延时)
timer_mode_active = (timer_config.timer_duration_ms > 0); // 判断是否启用定时模式
}

// 停止雾化
void SVC_Humidifier_StopMist(void) {
DRV_FM8118_StopMist();
DRV_LED_SetState(LED_STATUS, false); // 状态 LED 指示
intermittent_mode_working = false; // 停止间歇模式
timer_mode_active = false; // 停止定时模式
}

// 加湿器服务任务 (需要在主循环中周期性调用)
void SVC_Humidifier_Task(void) {
// 间歇模式处理
if (current_mode == HUMIDIFIER_MODE_INTERMITTENT) {
if (intermittent_mode_working) { // 工作状态
if (HAL_TIM_GetCounter(TIM6) - intermittent_mode_timer >= intermittent_config.work_time_ms) {
SVC_Humidifier_StopMist(); // 停止雾化
intermittent_mode_timer = HAL_TIM_GetCounter(TIM6); // 更新计时器
intermittent_mode_working = false; // 进入停止状态
}
} else { // 停止状态
if (HAL_TIM_GetCounter(TIM6) - intermittent_mode_timer >= intermittent_config.stop_time_ms) {
SVC_Humidifier_StartMist(); // 启动雾化
intermittent_mode_timer = HAL_TIM_GetCounter(TIM6); // 更新计时器
intermittent_mode_working = true; // 进入工作状态
}
}
}

// 定时模式处理
if (timer_mode_active) {
if (HAL_TIM_GetCounter(TIM6) - timer_mode_start_time >= timer_config.timer_duration_ms) {
SVC_Humidifier_StopMist(); // 定时时间到,停止雾化
timer_mode_active = false; // 停止定时模式
}
}

// 故障检测 (如果有 FM8118 故障检测引脚)
if (DRV_FM8118_GetFaultStatus()) {
// 处理 FM8118 故障,例如停止雾化、指示错误等
SVC_Humidifier_StopMist();
// ... 添加故障处理代码,例如 LED 闪烁报警 ...
}
}

svc_button_handler.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef SVC_BUTTON_HANDLER_H
#define SVC_BUTTON_HANDLER_H

#include "drv_button.h"

// 初始化按键处理服务
void SVC_ButtonHandler_Init(void);

// 按键事件处理函数
void SVC_ButtonHandler_ProcessEvent(Button_TypeDef button);

#endif // SVC_BUTTON_HANDLER_H

svc_button_handler.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
45
46
47
48
49
50
51
52
53
#include "svc_button_handler.h"
#include "svc_humidifier.h"

// 初始化按键处理服务
void SVC_ButtonHandler_Init(void) {
DRV_Button_Init(); // 初始化按键驱动
DRV_Button_RegisterEventHandler(SVC_ButtonHandler_ProcessEvent); // 注册按键事件处理函数
}

// 按键事件处理函数
void SVC_ButtonHandler_ProcessEvent(Button_TypeDef button) {
static uint8_t mist_level = DEFAULT_MIST_LEVEL; // 雾量等级变量,用于按键调节

switch (button) {
case BUTTON_MODE:
// 切换雾化模式 (连续/间歇)
if (SVC_Humidifier_GetMode() == HUMIDIFIER_MODE_CONTINUOUS) {
SVC_Humidifier_SetMode(HUMIDIFIER_MODE_INTERMITTENT);
} else {
SVC_Humidifier_SetMode(HUMIDIFIER_MODE_CONTINUOUS);
}
break;
case BUTTON_MIST_UP:
// 增加雾量等级
mist_level += 10;
if (mist_level > HUMIDIFIER_MIST_LEVEL_MAX) {
mist_level = HUMIDIFIER_MIST_LEVEL_MAX;
}
SVC_Humidifier_SetMistLevel(mist_level);
break;
case BUTTON_MIST_DOWN:
// 减少雾量等级
mist_level -= 10;
if (mist_level < HUMIDIFIER_MIST_LEVEL_MIN) {
mist_level = HUMIDIFIER_MIST_LEVEL_MIN;
}
SVC_Humidifier_SetMistLevel(mist_level);
break;
case BUTTON_TIMER:
// 启动/停止定时 (例如,每次按下切换定时时长,或切换定时开关)
// 这里示例简单的定时 30 分钟
if (!timer_mode_active) {
TimerModeConfig timer_config = {.timer_duration_ms = 30 * 60 * 1000}; // 30 分钟
SVC_Humidifier_SetTimerModeConfig(&timer_config);
SVC_Humidifier_StartMist(); // 启动雾化并开始定时
} else {
SVC_Humidifier_StopMist(); // 停止雾化并取消定时
}
break;
default:
break;
}
}

4. 应用层 (Application Layer)

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
#include "system_clock.h" // 假设有系统时钟配置头文件
#include "svc_humidifier.h"
#include "svc_button_handler.h"
#include "drv_button.h" // 包含按键扫描任务函数

int main(void) {
SystemClock_Config(); // 初始化系统时钟 (根据实际 MCU 配置)

SVC_Humidifier_Init(); // 初始化加湿器服务
SVC_ButtonHandler_Init(); // 初始化按键处理服务

SVC_Humidifier_StartMist(); // 默认启动雾化 (可以根据实际需求修改)

while (1) {
SVC_Humidifier_Task(); // 加湿器服务任务
DRV_Button_ScanTask(); // 按键扫描任务 (周期性调用)

// 其他应用层任务 (如果有)
// ...

// 延时 (可选,降低 CPU 占用率)
HAL_Delay_ms(10); // 例如 10ms 延时
}
}

system_clock.h 和 system_clock.c:

这两个文件需要根据你实际使用的MCU芯片和开发环境进行配置,用于初始化系统时钟。这里提供一个简单的框架,你需要根据具体的MCU型号和时钟配置进行修改。

system_clock.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef SYSTEM_CLOCK_H
#define SYSTEM_CLOCK_H

#include <stdint.h>

// 系统时钟频率 (Hz)
#define SystemCoreClock /* ... 根据实际配置定义系统时钟频率 ... */

// 系统时钟配置函数
void SystemClock_Config(void);

#endif // SYSTEM_CLOCK_H

system_clock.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
#include "system_clock.h"

// 系统时钟配置函数
void SystemClock_Config(void) {
// *** 硬件相关代码 ***
// 配置系统时钟,例如:
// 1. 使能外部高速晶振 (HSE) 或内部高速时钟 (HSI)
// 2. 配置 PLL (如果需要倍频)
// 3. 选择系统时钟源
// 4. 配置 AHB, APB 总线时钟分频系数

// 示例 (伪代码,需要根据具体的MCU芯片和HAL库进行修改)
// 使能 HSE
// ...
// 配置 PLL
// ...
// 选择 PLL 作为系统时钟源
// ...
// 配置 AHB, APB 总线时钟分频系数
// ...

// 更新 SystemCoreClock 变量 (重要!)
SystemCoreClock = /* ... 计算或获取实际的系统时钟频率 ... */;
}

测试验证和维护升级

测试验证:

  • 单元测试: 针对HAL层、驱动层、服务层的各个模块进行单元测试,验证每个模块的功能是否正确。
  • 集成测试: 将各个模块组合起来进行集成测试,验证模块之间的接口和协作是否正常。
  • 系统测试: 进行完整的系统测试,模拟用户的使用场景,验证系统的整体功能和性能是否满足需求。
  • 可靠性测试: 进行长时间的运行测试,验证系统的稳定性。
  • 性能测试: 测试系统的响应速度、资源占用率等性能指标。

维护升级:

  • 模块化设计: 分层架构的模块化设计使得代码易于维护和升级。修改或添加功能时,只需要修改相应的模块,而不会影响其他模块。
  • 清晰的代码结构和注释: 良好的代码结构和详细的注释能够提高代码的可读性和可维护性,方便后续的维护和升级工作。
  • 版本控制: 使用版本控制工具(如Git)管理代码,方便代码的版本管理和回溯,便于维护和升级。
  • 预留升级接口: 在系统设计时,可以预留一些升级接口,例如通过UART或OTA (Over-The-Air) 方式进行固件升级,方便后续的功能扩展和bug修复。

总结

以上代码实现和架构设计方案,旨在提供一个可靠、高效、可扩展的嵌入式加湿器/雾化器系统平台。代码采用了分层架构,模块化设计,并包含了详细的注释,力求清晰易懂,易于维护和升级。实际项目中,需要根据具体的硬件平台、FM8118芯片的数据手册以及项目需求进行相应的修改和完善。

希望这个详细的解答能够帮助你理解嵌入式系统开发流程和代码架构设计,并为你的项目提供参考。祝你新年快乐,项目顺利!

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