编程技术分享

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

0%

简介:小型加热台 (AtomHeat)**

关注微信公众号,提前获取相关推文

本项目旨在开发一个小型、便携、易于使用的加热台,用于电子元件焊接、热风枪预热、PCB板预热等场景。基于立创·天空星开发板-GD32F407VET6-青春版,充分利用GD32F407VET6强大的性能和丰富的外设资源,实现精准的温度控制、友好的用户界面以及稳定的系统运行。

一、需求分析

  1. 基本功能需求:

    • 温度控制:
      • 设定目标温度:用户能够设定目标温度值。
      • 实时温度显示:实时显示加热台当前温度。
      • 温度PID控制:采用PID算法实现精准的温度控制,确保温度快速稳定达到设定值,并维持稳定。
      • 温度范围:室温 ~ 300℃ (可根据实际需求调整)。
      • 温度精度:±1℃。
    • 用户界面 (UI):
      • 显示屏:OLED或LCD显示屏,用于显示温度、状态、菜单等信息。
      • 按键/旋钮:用于用户交互,例如设定温度、切换菜单、启动/停止加热等。
      • 状态指示:LED指示灯或其他方式指示加热台的工作状态(加热中、恒温、待机等)。
    • 加热控制:
      • PWM控制:使用PWM信号控制加热元件的功率,实现精确的温度调节。
      • 加热元件:选择合适的加热元件,例如电阻丝加热片。
      • 温度传感器:高精度温度传感器,例如热电偶或PT100/PT1000铂电阻。
    • 安全保护:
      • 过温保护:当温度超过安全阈值时,自动停止加热,防止过热损坏或安全事故。
      • 传感器故障检测:检测温度传感器是否故障,并在故障时报警并停止加热。
      • 电源保护:防止电源过载或短路。
  2. 高级功能需求 (可选,但为系统扩展性考虑):

    • 预设温度模式: 用户可以预设几个常用的温度模式,方便快速切换。
    • 定时加热功能: 设定加热时间,到时自动停止加热。
    • 温度曲线显示: 实时显示温度变化曲线,方便用户观察温度变化趋势。
    • 数据记录与导出: 记录温度数据,并可以通过USB或其他方式导出数据。
    • 上位机通信: 通过串口或USB与上位机通信,实现远程控制和数据监控。
    • 固件升级: 支持固件在线升级,方便后期功能扩展和bug修复。
  3. 非功能需求:

    • 可靠性: 系统稳定可靠,长时间运行不易出错。
    • 高效性: 温度控制响应迅速,控制算法高效。
    • 可扩展性: 系统架构易于扩展,方便添加新功能。
    • 易维护性: 代码结构清晰,模块化设计,方便维护和升级。
    • 成本控制: 在满足功能需求的前提下,尽量降低成本。

二、系统架构设计

为了满足上述需求,并构建一个可靠、高效、可扩展的系统平台,我将采用分层架构的设计思想,结合模块化设计事件驱动机制。系统架构主要分为以下几个层次:

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

    • 功能: 提供对底层硬件的抽象接口,向上层屏蔽硬件差异。
    • 模块:
      • GPIO驱动: 控制GPIO端口,例如控制LED指示灯、按键输入等。
      • ADC驱动: 采集模拟信号,例如读取温度传感器电压值。
      • Timer驱动: 提供定时功能,例如PWM输出、定时中断等。
      • SPI/I2C驱动: 与外设通信,例如驱动OLED/LCD显示屏。
      • UART驱动: 串口通信,用于调试和上位机通信。
      • Flash驱动: 用于存储配置参数、固件升级等。
    • 优点: 提高代码的可移植性,方便更换硬件平台;降低上层应用对底层硬件的依赖。
  2. 板级支持包 (BSP - Board Support Package):

    • 功能: 针对具体的开发板(立创·天空星-GD32F407VET6)进行硬件初始化和配置。
    • 模块:
      • 时钟配置: 配置系统时钟、外设时钟。
      • 中断配置: 配置中断向量表、中断优先级。
      • 外设初始化: 初始化GPIO、ADC、Timer、SPI/I2C、UART、Flash等外设。
    • 优点: 将硬件相关的初始化代码集中管理,方便移植和维护;为HAL层提供基础支持。
  3. 设备驱动层 (Device Driver Layer):

    • 功能: 基于HAL层提供的接口,实现对具体硬件设备的驱动,例如温度传感器驱动、加热元件驱动、显示屏驱动、按键驱动、旋钮驱动等。
    • 模块:
      • 温度传感器驱动 (Temperature Sensor Driver): 读取温度传感器数据,并进行数据转换和校准。
      • 加热元件驱动 (Heater Driver): 控制加热元件的功率,例如通过PWM控制MOSFET或SSR。
      • 显示屏驱动 (Display Driver): 驱动OLED/LCD显示屏,提供字符、图形显示功能。
      • 按键驱动 (Button Driver): 检测按键按下、释放事件,并进行按键去抖处理。
      • 旋钮驱动 (Rotary Encoder Driver): 检测旋钮旋转方向和步进,用于参数调节和菜单选择。
    • 优点: 将硬件设备的驱动逻辑封装起来,为上层服务层提供统一的设备访问接口;提高代码的可重用性和可维护性。
  4. 服务层 (Service Layer):

    • 功能: 在设备驱动层之上,提供一些通用的服务功能,例如温度控制服务、显示管理服务、UI交互服务、参数配置服务、安全保护服务等。
    • 模块:
      • 温度控制服务 (Temperature Control Service): 实现PID温度控制算法,根据设定温度和实时温度,控制加热元件功率,维持温度稳定。
      • 显示管理服务 (Display Management Service): 管理显示屏的显示内容,例如显示温度、状态信息、菜单界面等。
      • UI交互服务 (User Interface Service): 处理用户输入事件,例如按键、旋钮操作,并根据用户操作更新显示和执行相应功能。
      • 参数配置服务 (Configuration Service): 存储和加载系统配置参数,例如目标温度、PID参数、预设温度模式等。
      • 安全保护服务 (Safety Protection Service): 实现过温保护、传感器故障检测等安全功能。
    • 优点: 将业务逻辑和设备驱动解耦,提高代码的模块化程度;方便功能扩展和业务逻辑的修改。
  5. 应用层 (Application Layer):

    • 功能: 实现整个应用程序的逻辑流程,例如系统初始化、主循环、任务调度、状态管理等。
    • 模块:
      • 主程序 (main.c): 系统入口,初始化各模块,启动任务调度,进入主循环。
      • 状态机 (State Machine): 管理系统的不同状态,例如待机状态、设定温度状态、加热状态、恒温状态、故障状态等,并根据事件进行状态切换。
      • 任务调度 (Task Scheduler - 可选,如果使用RTOS): 如果使用RTOS,则负责任务的创建、调度和管理;如果未使用RTOS,可以使用简单的合作式多任务或时间片轮询。
    • 优点: 负责整个系统的协调和控制,将各个服务模块整合起来,实现完整的功能;代码结构清晰,易于理解和维护。

系统架构图示:

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
+---------------------+
| 应用层 (Application Layer) |
|---------------------|
| 状态机 |
| 主程序 |
+---------------------+
^
| 服务调用
v
+---------------------+
| 服务层 (Service Layer) |
|---------------------|
| 温度控制服务 |
| 显示管理服务 |
| UI交互服务 |
| 参数配置服务 |
| 安全保护服务 |
+---------------------+
^
| 设备驱动调用
v
+---------------------+
| 设备驱动层 (Device Driver Layer) |
|---------------------|
| 温度传感器驱动 |
| 加热元件驱动 |
| 显示屏驱动 |
| 按键驱动 |
| 旋钮驱动 |
+---------------------+
^
| HAL接口调用
v
+---------------------+
| 硬件抽象层 (HAL - Hardware Abstraction Layer) |
|---------------------|
| GPIO驱动 |
| ADC驱动 |
| Timer驱动 |
| SPI/I2C驱动 |
| UART驱动 |
| Flash驱动 |
+---------------------+
^
| BSP初始化
v
+---------------------+
| 板级支持包 (BSP - Board Support Package) |
|---------------------|
| 时钟配置 |
| 中断配置 |
| 外设初始化 |
+---------------------+
^
| 硬件平台
v
+---------------------+
| 硬件平台 (立创·天空星-GD32F407VET6) |
+---------------------+

三、具体C代码实现 (部分关键代码示例)

为了展示代码架构和关键功能实现,我将提供部分关键模块的C代码示例。由于篇幅限制,这些示例代码足以说明系统的设计思路和实现方法。 完整项目代码将包含更详细的错误处理、参数校验、注释以及所有功能模块的完整实现。

1. HAL层 (HAL - Hardware Abstraction Layer) - hal_gpio.hhal_gpio.c

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

#include "gd32f4xx.h"

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF
} hal_gpio_mode_t;

typedef enum {
GPIO_OUTPUT_PP, // 推挽输出
GPIO_OUTPUT_OD // 开漏输出
} hal_gpio_output_type_t;

typedef enum {
GPIO_PULL_NONE,
GPIO_PULL_UP,
GPIO_PULL_DOWN
} hal_gpio_pull_t;

void hal_gpio_init(uint32_t gpio_periph, uint32_t gpio_pin, hal_gpio_mode_t mode, hal_gpio_output_type_t output_type, hal_gpio_pull_t pull);
void hal_gpio_set_output(uint32_t gpio_periph, uint32_t gpio_pin, uint8_t value);
uint8_t hal_gpio_get_input(uint32_t gpio_periph, uint32_t gpio_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
#include "hal_gpio.h"

void hal_gpio_init(uint32_t gpio_periph, uint32_t gpio_pin, hal_gpio_mode_t mode, hal_gpio_output_type_t output_type, hal_gpio_pull_t pull) {
gpio_initpara_t gpio_init_struct;
rcu_periph_enum periph_rcu;

if (gpio_periph == GPIOA) periph_rcu = RCU_GPIOA;
else if (gpio_periph == GPIOB) periph_rcu = RCU_GPIOB;
else if (gpio_periph == GPIOC) periph_rcu = RCU_GPIOC;
else if (gpio_periph == GPIOD) periph_rcu = RCU_GPIOD;
else if (gpio_periph == GPIOE) periph_rcu = RCU_GPIOE;
else if (gpio_periph == GPIOF) periph_rcu = RCU_GPIOF;
else if (gpio_periph == GPIOG) periph_rcu = RCU_GPIOG;
else if (gpio_periph == GPIOH) periph_rcu = RCU_GPIOH;
else return; // Invalid GPIO peripheral

rcu_periph_clock_enable(periph_rcu);

gpio_init_struct.gpio_pin = gpio_pin;
gpio_init_struct.gpio_speed = GPIO_SPEED_50MHZ;

if (mode == GPIO_MODE_INPUT) {
gpio_init_struct.gpio_mode = GPIO_MODE_IN_FLOATING; // 默认浮空输入,可以根据pull配置修改
} else if (mode == GPIO_MODE_OUTPUT) {
gpio_init_struct.gpio_mode = GPIO_MODE_OUT_PP; // 默认推挽输出,可以根据output_type配置修改
} else if (mode == GPIO_MODE_AF) {
gpio_init_struct.gpio_mode = GPIO_MODE_AF_PP; // 默认复用推挽输出,需要根据具体外设配置
} else {
return; // Invalid GPIO mode
}

if (output_type == GPIO_OUTPUT_PP) {
gpio_init_struct.gpio_output_options = GPIO_OTYPE_PP;
} else if (output_type == GPIO_OUTPUT_OD) {
gpio_init_struct.gpio_output_options = GPIO_OTYPE_OD;
}

if (pull == GPIO_PULL_UP) {
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
} else if (pull == GPIO_PULL_DOWN) {
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
} else {
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
}

gpio_init(gpio_periph, &gpio_init_struct);
}

void hal_gpio_set_output(uint32_t gpio_periph, uint32_t gpio_pin, uint8_t value) {
if (value) {
gpio_bit_set(gpio_periph, gpio_pin);
} else {
gpio_bit_reset(gpio_periph, gpio_pin);
}
}

uint8_t hal_gpio_get_input(uint32_t gpio_periph, uint32_t gpio_pin) {
return gpio_input_bit_get(gpio_periph, gpio_pin);
}

2. BSP层 (BSP - Board Support Package) - bsp.hbsp.c

bsp.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef BSP_H
#define BSP_H

#include "gd32f4xx.h"
#include "hal_gpio.h"
#include "hal_timer.h"
#include "hal_adc.h"
#include "hal_spi.h"
#include "hal_uart.h"

void bsp_init(void);
void system_clock_config(void);
void nvic_config(void);

#endif /* BSP_H */

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

void bsp_init(void) {
system_clock_config();
nvic_config();

// 初始化HAL层驱动 (示例,根据实际项目需求初始化)
// 例如:LED指示灯 GPIO初始化
hal_gpio_init(GPIOC, GPIO_PIN_13, GPIO_MODE_OUTPUT, GPIO_OUTPUT_PP, GPIO_PULL_NONE); // 板载LED,根据原理图确定GPIO
hal_gpio_set_output(GPIOC, GPIO_PIN_13, 1); // 默认熄灭LED

// 初始化其他外设 (ADC, Timer, SPI, UART等) 在各自驱动的初始化函数中进行,这里只做必要的全局初始化
}

void system_clock_config(void) {
/* 使能 HSE 外部高速时钟 */
rcu_osci_on(RCU_HSE);
/* 等待 HSE 稳定 */
while(ERROR != rcu_osci_stab_wait(RCU_HSE));

/* 配置 PLL */
rcu_pll_config(RCU_PLLSRC_HSE_CK, 8, 336, 2, 7); // HSE 8MHz, PLL_N=336, PLL_P=2, PLL_Q=7, System Clock = 168MHz
/* 使能 PLL */
rcu_osci_on(RCU_PLL_CK);
/* 等待 PLL 稳定 */
while(ERROR != rcu_osci_stab_wait(RCU_PLL_CK));

/* 配置系统时钟源为 PLL */
rcu_config_clock_source(RCU_CKSYSRC_PLLCLK);
/* 等待系统时钟源切换完成 */
while(RCU_CKSYSRC != RCU_CKSYSRC_PLLCLK);

/* 配置 AHB, APB1, APB2 时钟分频系数 (根据实际外设需求配置) */
rcu_ahb_clock_config(RCU_AHB_CKAHB_DIV1); // AHB时钟不分频
rcu_apb1_clock_config(RCU_APB1_CKAPB1_DIV4); // APB1时钟 4 分频
rcu_apb2_clock_config(RCU_APB2_CKAPB2_DIV2); // APB2时钟 2 分频

SystemCoreClockUpdate(); // 更新 SystemCoreClock 变量,供HAL库使用
}

void nvic_config(void) {
// 中断配置函数,根据实际项目需求配置中断优先级等
// 例如,如果使用外部中断按键,需要在这里配置EXTI中断
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 配置中断优先级分组
}

3. 设备驱动层 (Device Driver Layer) - 温度传感器驱动 driver_temp_sensor.hdriver_temp_sensor.c

假设使用热敏电阻作为温度传感器,通过ADC采集电压值,并转换为温度值。

driver_temp_sensor.h

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

#include "gd32f4xx.h"
#include "hal_adc.h"

#define TEMP_SENSOR_ADC_CHANNEL ADC_CHANNEL_5 // 假设温度传感器连接到 ADC 通道 5

void temp_sensor_init(void);
float temp_sensor_read_temperature(void);

#endif /* DRIVER_TEMP_SENSOR_H */

driver_temp_sensor.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
#include "driver_temp_sensor.h"
#include "math.h" // 需要使用数学函数,例如 log

#define VREF 3.3f // 参考电压
#define ADC_RESOLUTION 4096.0f // ADC分辨率 12位

// 热敏电阻参数 (需要根据实际使用的热敏电阻型号进行校准)
#define R0 10000.0f // 25℃时热敏电阻阻值
#define B_VALUE 3950.0f // B值
#define T0 298.15f // 25℃ 对应的开尔文温度 (273.15 + 25)

void temp_sensor_init(void) {
// 初始化 ADC 通道,使用 HAL_ADC 驱动
hal_adc_init(ADC0, TEMP_SENSOR_ADC_CHANNEL); // 假设使用 ADC0
}

float temp_sensor_read_temperature(void) {
uint16_t adc_value;
float voltage;
float rt; // 热敏电阻阻值
float temperature_k; // 开尔文温度
float temperature_c; // 摄氏温度

adc_value = hal_adc_read_channel(ADC0, TEMP_SENSOR_ADC_CHANNEL);
voltage = (float)adc_value * VREF / ADC_RESOLUTION;

// 计算热敏电阻阻值 (假设分压电路,热敏电阻串联一个固定电阻 R_FIXED,连接到 ADC)
// 需要根据实际电路调整计算公式
float R_FIXED = 10000.0f; // 固定电阻阻值
rt = R_FIXED * (VREF / voltage - 1.0f);

// 使用 B 值法计算温度 (近似公式)
temperature_k = 1.0f / (1.0f/T0 + (1.0f/B_VALUE) * log(rt/R0));
temperature_c = temperature_k - 273.15f;

return temperature_c;
}

4. 服务层 (Service Layer) - 温度控制服务 service_temp_control.hservice_temp_control.c

实现 PID 温度控制算法。

service_temp_control.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 SERVICE_TEMP_CONTROL_H
#define SERVICE_TEMP_CONTROL_H

#include "gd32f4xx.h"

typedef struct {
float kp;
float ki;
float kd;
float setpoint;
float current_temp;
float integral_error;
float last_error;
float output;
} pid_controller_t;

void pid_init(pid_controller_t *pid, float kp, float ki, float kd, float setpoint);
void pid_set_setpoint(pid_controller_t *pid, float setpoint);
void pid_update_temperature(pid_controller_t *pid, float current_temp);
float pid_get_output(pid_controller_t *pid);
void pid_reset_integral(pid_controller_t *pid);

#endif /* SERVICE_TEMP_CONTROL_H */

service_temp_control.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 "service_temp_control.h"

void pid_init(pid_controller_t *pid, float kp, float ki, float kd, float setpoint) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->setpoint = setpoint;
pid->current_temp = 0.0f;
pid->integral_error = 0.0f;
pid->last_error = 0.0f;
pid->output = 0.0f;
}

void pid_set_setpoint(pid_controller_t *pid, float setpoint) {
pid->setpoint = setpoint;
pid_reset_integral(pid); // 设定新目标温度时,重置积分项,避免积分饱和
}

void pid_update_temperature(pid_controller_t *pid, float current_temp) {
float error;

pid->current_temp = current_temp;
error = pid->setpoint - current_temp;

pid->integral_error += error;

// 积分限幅,防止积分饱和
float integral_limit = 1000.0f; // 需要根据实际情况调整
if (pid->integral_error > integral_limit) {
pid->integral_error = integral_limit;
} else if (pid->integral_error < -integral_limit) {
pid->integral_error = -integral_limit;
}

pid->output = pid->kp * error + pid->ki * pid->integral_error + pid->kd * (error - pid->last_error);
pid->last_error = error;

// 输出限幅,例如 PWM 占空比范围 0-100%
float output_limit = 100.0f; // 假设 PWM 占空比范围是 0-100
if (pid->output > output_limit) {
pid->output = output_limit;
} else if (pid->output < 0.0f) {
pid->output = 0.0f;
}
}

float pid_get_output(pid_controller_t *pid) {
return pid->output;
}

void pid_reset_integral(pid_controller_t *pid) {
pid->integral_error = 0.0f;
}

5. 应用层 (Application Layer) - main.c (部分主循环示例)

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "gd32f4xx.h"
#include "bsp.h"
#include "driver_temp_sensor.h"
#include "service_temp_control.h"
#include "hal_timer.h" // 假设 PWM 控制加热元件使用 Timer

#define HEATER_PWM_TIMER TIMER1 // 假设加热元件 PWM 控制使用 TIMER1
#define HEATER_PWM_CHANNEL TIMER_CH_0 // 假设使用 TIMER1 通道 0
#define HEATER_PWM_GPIO_PERIPH GPIOA // 假设 GPIOA
#define HEATER_PWM_GPIO_PIN GPIO_PIN_8 // 假设 GPIOA Pin 8

pid_controller_t temp_pid_controller;
float target_temperature = 50.0f; // 默认目标温度
float current_temperature;
float heater_pwm_duty_cycle;

void heater_pwm_init(void);
void heater_pwm_set_duty_cycle(float duty_cycle);

int main(void) {
bsp_init(); // 初始化 BSP 和 HAL

temp_sensor_init(); // 初始化温度传感器驱动
heater_pwm_init(); // 初始化加热元件 PWM 控制

// PID 参数初始化 (需要根据实际系统调试整定)
pid_init(&temp_pid_controller, 1.0f, 0.1f, 0.01f, target_temperature);

while (1) {
current_temperature = temp_sensor_read_temperature(); // 读取当前温度
pid_update_temperature(&temp_pid_controller, current_temperature); // PID 控制计算

heater_pwm_duty_cycle = pid_get_output(&temp_pid_controller); // 获取 PID 输出 (PWM 占空比)
heater_pwm_set_duty_cycle(heater_pwm_duty_cycle); // 设置加热元件 PWM 占空比

// 显示温度信息 (需要实现显示屏驱动和服务)
// display_temperature(current_temperature, target_temperature);

// 用户界面交互 (按键、旋钮处理,设置目标温度等)
// ui_process_input();

delay_1ms(100); // 控制循环周期,例如 100ms
}
}

void heater_pwm_init(void) {
// 初始化 Timer PWM 输出,控制加热元件功率
hal_timer_pwm_init(HEATER_PWM_TIMER, HEATER_PWM_CHANNEL, HEATER_PWM_GPIO_PERIPH, HEATER_PWM_GPIO_PIN, 1000, 0); // 1kHz PWM 频率,初始占空比 0
hal_timer_pwm_start(HEATER_PWM_TIMER, HEATER_PWM_CHANNEL);
}

void heater_pwm_set_duty_cycle(float duty_cycle) {
// 设置 PWM 占空比,控制加热功率
// duty_cycle 范围 0-100
uint32_t period = hal_timer_get_period(HEATER_PWM_TIMER);
uint32_t pulse = (uint32_t)((duty_cycle / 100.0f) * period);
hal_timer_pwm_set_pulse(HEATER_PWM_TIMER, HEATER_PWM_CHANNEL, pulse);
}

代码说明:

  • HAL层: 提供了GPIO、ADC、Timer等硬件的抽象接口,方便上层调用。
  • BSP层: 初始化了系统时钟和必要的硬件外设,为HAL层提供基础支持。
  • 设备驱动层: 实现了温度传感器驱动,读取温度值并进行转换。
  • 服务层: 实现了PID温度控制服务,根据目标温度和当前温度计算PID输出,用于控制加热功率。
  • 应用层: main.c 中展示了主循环,读取温度,进行PID控制,并设置加热元件PWM占空比。
  • 代码只是示例: 以上代码只是关键模块的示例,实际项目中需要完善各个模块的驱动和逻辑,并根据具体的硬件连接和需求进行调整。
  • 代码: 需要完善所有模块的驱动,例如显示屏驱动、按键驱动、旋钮驱动、UI界面、菜单功能、参数配置、安全保护、错误处理、详细注释、以及各种功能扩展(预设温度模式、定时加热、数据记录、上位机通信、固件升级等)。 完整的项目代码量会远超过示例代码。

四、测试验证

在系统开发过程中,测试验证是至关重要的环节,确保系统的功能和性能符合设计要求。测试验证主要包括以下几个方面:

  1. 单元测试 (Unit Test): 针对各个独立的模块进行测试,例如 HAL 驱动、设备驱动、服务模块等,验证模块的功能是否正确。可以使用测试框架 (例如 CUnit, CMocka) 编写单元测试用例,进行自动化测试。

  2. 集成测试 (Integration Test): 将各个模块组合起来进行测试,验证模块之间的接口和协作是否正常。例如,测试温度传感器驱动和温度控制服务是否能够协同工作,实现温度的正确读取和控制。

  3. 系统测试 (System Test): 对整个系统进行全面的功能和性能测试,验证系统是否满足所有需求。系统测试包括:

    • 功能测试: 测试所有功能是否正常工作,例如温度设定、实时温度显示、PID控制、用户界面交互、安全保护功能等。
    • 性能测试: 测试系统的性能指标,例如温度控制精度、温度响应速度、系统稳定性、功耗等。
    • 可靠性测试: 进行长时间的运行测试,验证系统在长时间运行下的稳定性。
    • 压力测试: 在极端条件下测试系统的性能,例如高温、低温、高负载等。
    • 用户体验测试: 邀请用户进行试用,收集用户反馈,改进用户界面和操作体验。
  4. 回归测试 (Regression Test): 在代码修改或功能升级后,重新运行之前的测试用例,确保新的代码修改没有引入新的bug,并保证原有功能不受影响。

测试工具和方法:

  • 硬件测试工具: 万用表、示波器、温度计、热电偶、热风枪、可调电源等。
  • 软件测试工具: 调试器 (例如 GDB, J-Link RTT)、串口调试助手、上位机监控软件、单元测试框架、性能分析工具等。
  • 测试方法: 黑盒测试、白盒测试、灰盒测试、手动测试、自动化测试等。

五、维护升级

嵌入式系统的维护升级是系统生命周期中不可或缺的环节,主要包括以下几个方面:

  1. 固件升级 (Firmware Update): 为了修复bug、添加新功能或改进系统性能,需要进行固件升级。固件升级可以采用多种方式:

    • 在线升级 (OTA - Over-The-Air): 通过网络 (例如 Wi-Fi, Ethernet) 或无线通信 (例如 Bluetooth, LoRa) 进行固件升级。
    • 本地升级: 通过USB、串口、SD卡等接口,连接上位机进行固件升级。
    • 引导加载程序 (Bootloader): 在系统启动时,先运行Bootloader程序,Bootloader负责接收新的固件,并更新系统固件。
  2. Bug修复: 在系统运行过程中,可能会发现各种bug,需要及时进行修复。Bug修复流程包括:

    • Bug报告: 用户或测试人员报告bug。
    • Bug分析: 开发人员分析bug原因,定位bug代码位置。
    • Bug修复: 修改代码,修复bug。
    • 测试验证: 对修复后的代码进行测试验证,确保bug已修复,并且没有引入新的bug。
    • 发布更新: 发布修复bug后的新固件版本。
  3. 功能扩展: 根据用户需求或市场变化,可能需要对系统进行功能扩展。功能扩展需要进行需求分析、系统设计、代码实现、测试验证等一系列开发流程。

  4. 性能优化: 随着系统功能的增加或运行环境的变化,可能需要对系统进行性能优化,提高系统的响应速度、降低功耗、提高资源利用率等。性能优化可以通过代码优化、算法优化、硬件优化等方式实现。

  5. 安全维护: 对于需要联网的嵌入式系统,安全维护尤为重要。需要定期进行安全漏洞扫描和修复,防止系统受到攻击。

维护升级策略:

  • 模块化设计: 模块化设计可以提高代码的可维护性,方便进行bug修复和功能扩展。
  • 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便跟踪代码修改历史,进行版本回溯。
  • 日志记录: 在系统中添加日志记录功能,方便在系统出现问题时进行故障排查。
  • 远程监控: 对于需要联网的系统,可以实现远程监控功能,方便远程诊断和维护。
  • 用户反馈机制: 建立用户反馈机制,收集用户反馈,及时了解用户需求和系统问题。

总结

以上是我针对基于立创·天空星开发板-GD32F407VET6-青春版的小型加热台项目,从需求分析到维护升级的完整嵌入式系统开发流程和代码设计架构的详细说明。 我提供的代码示例虽然只是部分关键代码,但已经展示了系统的分层架构、模块化设计以及关键功能的实现思路。 在实际项目开发中,需要根据具体需求和硬件平台,进一步完善代码,进行充分的测试验证,并持续进行维护升级,才能打造一个可靠、高效、可扩展的嵌入式系统平台。 希望我的回答能够帮助你理解嵌入式系统开发流程和代码架构设计。

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