编程技术分享

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

0%

简介:基于开源t12 858设计,重绘电路板到88*38*120铝外壳,最小体积,预留1.4寸TFT SPI接口和iic接口,上到彩屏,也可修改到jbc245来使用,预留了丰富的自定义空间

我将为您详细阐述基于开源T12 858设计的嵌入式焊接台项目的软件架构设计和C代码实现。这个项目目标是构建一个可靠、高效、可扩展的嵌入式系统平台,涵盖从需求分析到系统实现,再到测试验证和维护升级的完整开发流程。
关注微信公众号,提前获取相关推文

项目背景与需求分析

项目目标:

  • 最小体积: 将焊接台设计到 88*38*120 铝外壳内,实现最小体积。
  • 开源硬件基础: 基于开源 T12 858 设计,重绘电路板以适应新外壳。
  • 可扩展性: 预留 1.4 寸 TFT SPI 接口和 I2C 接口,支持彩色屏幕和外围传感器扩展。
  • 兼容性: 可修改固件以支持 JBC245 焊台手柄。
  • 用户自定义空间: 提供丰富的自定义空间,方便用户根据需求进行功能扩展和参数调整。
  • 可靠性: 系统需要稳定可靠运行,保证焊接质量和安全性。
  • 高效性: 快速响应用户操作,精确控温,提高工作效率。
  • 易维护升级: 方便固件升级和维护,延长产品生命周期。

需求分析关键点:

  1. 硬件驱动需求:

    • T12/JBC245 焊台手柄控制 (温度传感器读取、加热器驱动)。
    • 1.4 寸 TFT SPI 彩色屏幕驱动 (显示温度、状态、设置菜单等)。
    • I2C 接口驱动 (可能用于外围传感器或扩展模块)。
    • 旋转编码器或按键输入驱动 (用户交互)。
    • LED 指示灯驱动 (状态指示)。
    • ADC 模数转换器驱动 (温度传感器信号采集)。
    • PWM 脉冲宽度调制驱动 (加热器功率控制)。
    • 定时器驱动 (周期性任务、PID 控制)。
    • GPIO 通用输入输出驱动 (控制外围设备、状态指示)。
  2. 软件功能需求:

    • 温度控制: PID 算法实现精确温度控制,包括设定温度、实时温度读取、加热器功率调节。
    • 用户界面: 通过 TFT 彩色屏幕和旋转编码器/按键提供友好的用户交互界面,显示实时温度、设定温度、工作状态、设置菜单等。
    • 菜单系统: 实现多级菜单,允许用户设置目标温度、PID 参数、显示设置、系统设置等。
    • 状态管理: 管理焊接台的不同工作状态,如待机、加热、工作、错误等。
    • 配置管理: 存储和加载用户配置参数,如目标温度、PID 参数、显示设置等 (可以使用 EEPROM 或 Flash 存储)。
    • 保护机制: 过温保护、传感器故障检测、加热器异常检测等安全保护机制。
    • 可扩展性: 预留软件接口,方便未来扩展新功能,如数据记录、蓝牙/Wi-Fi 通信、固件在线升级等。
  3. 非功能性需求:

    • 实时性: 温度控制和用户界面需要实时响应。
    • 资源效率: 嵌入式系统资源有限,代码需要高效运行,占用资源少。
    • 可靠性: 系统需要稳定运行,避免崩溃和数据丢失。
    • 易维护性: 代码结构清晰,模块化设计,方便维护和升级。

代码设计架构

为了满足上述需求,并构建可靠、高效、可扩展的系统平台,我推荐采用分层架构结合模块化设计的代码架构。这种架构将系统划分为多个层次和模块,每个层次和模块负责特定的功能,层与层之间通过清晰的接口进行通信,模块之间相互独立,降低了系统复杂性,提高了代码的可维护性和可扩展性。

分层架构:

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

    • 功能: 直接与硬件交互,封装底层硬件操作,向上层提供统一的硬件接口。
    • 模块:
      • GPIO 驱动: 控制 GPIO 引脚的输入输出。
      • SPI 驱动: 控制 SPI 总线,用于 TFT 屏幕通信。
      • I2C 驱动: 控制 I2C 总线,用于外围传感器或扩展模块通信。
      • ADC 驱动: 读取 ADC 模数转换器的值,用于温度传感器信号采集。
      • PWM 驱动: 生成 PWM 信号,用于加热器功率控制。
      • Timer 驱动: 提供定时器功能,用于周期性任务和时间管理。
      • UART 驱动 (可选): 用于调试或串口通信。
      • EEPROM/Flash 驱动 (可选): 用于配置参数存储。
    • 优点: 硬件独立性,方便移植到不同的硬件平台;降低上层代码对硬件的依赖,简化上层开发。
  2. 板级支持包 (BSP - Board Support Package):

    • 功能: 针对具体的硬件平台进行配置和初始化,包括时钟配置、外设初始化、中断配置等,并提供更高层次的硬件接口,方便应用层使用。
    • 模块:
      • 系统时钟初始化: 配置系统时钟频率。
      • 外设初始化: 初始化 GPIO、SPI、I2C、ADC、PWM、Timer 等外设。
      • 中断服务函数: 编写各个外设的中断服务函数。
      • 板级硬件接口: 定义板级硬件接口,例如获取温度传感器值、控制加热器、驱动 TFT 屏幕等。
    • 优点: 平台相关性封装,方便在同一系列的不同硬件平台上复用代码;提供更高层次的硬件接口,简化应用层开发。
  3. 系统服务层 (System Services Layer):

    • 功能: 提供操作系统级别的服务,例如任务调度、内存管理、事件管理、软件定时器等,简化应用层开发,提高系统效率和可靠性。
    • 模块:
      • 任务调度器 (可选,可以使用简单的合作式调度或 RTOS): 管理和调度系统任务。
      • 软件定时器: 提供软件定时器功能,用于周期性任务和延时操作。
      • 配置管理模块: 负责加载和保存系统配置参数。
      • 错误处理模块: 处理系统错误和异常情况。
      • 日志记录模块 (可选): 记录系统运行日志,方便调试和维护。
    • 优点: 提供通用的系统服务,提高代码复用率;简化应用层开发,提高开发效率;增强系统的可靠性和可维护性。
  4. 应用层 (Application Layer):

    • 功能: 实现具体的应用逻辑,例如温度控制算法、用户界面、菜单系统、状态管理等。
    • 模块:
      • 温度控制模块 (PID 控制): 实现 PID 温度控制算法,包括温度读取、PID 计算、加热器功率控制。
      • 用户界面模块: 负责 TFT 屏幕显示和用户交互,包括显示温度、状态、菜单、处理旋转编码器/按键输入。
      • 菜单管理模块: 管理菜单结构和菜单操作,响应用户菜单选择。
      • 状态机模块: 管理焊接台的不同工作状态,并根据状态进行相应的操作。
      • 配置管理模块接口: 调用系统服务层的配置管理模块,加载和保存配置参数。
      • 错误处理接口: 调用系统服务层的错误处理模块,处理应用层错误。
    • 优点: 专注于应用逻辑开发,提高开发效率;与底层硬件和系统服务解耦,易于维护和升级;模块化设计,方便功能扩展。

模块化设计:

在每个层次内部,进一步采用模块化设计,将功能细分为更小的模块,每个模块负责特定的子功能,模块之间通过接口进行通信。例如,在应用层的用户界面模块中,可以进一步划分为:

  • 显示驱动模块: 负责 TFT 屏幕的底层驱动,例如初始化、清屏、画点、画线、显示字符等。
  • UI 元素模块: 封装常用的 UI 元素,例如按钮、文本框、进度条、菜单项等。
  • 界面布局模块: 负责界面的布局和组织,例如菜单界面、主界面、设置界面等。
  • 输入处理模块: 处理旋转编码器/按键输入,并将其转换为用户操作。

C 代码实现 (详细注释)

为了方便理解和实践,我将提供一个简化的 C 代码框架,展示上述分层架构和模块化设计的实现思路。由于代码量庞大,我将重点展示关键模块的代码实现,并提供详细注释。包括各种边界条件处理、错误处理、优化等,这里提供框架和核心代码示例。

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

typedef enum {
GPIO_PIN_0,
GPIO_PIN_1,
GPIO_PIN_2,
// ... 更多引脚定义
GPIO_PIN_MAX
} GPIO_PinTypeDef;

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
// ... 更多模式定义
} GPIO_ModeTypeDef;

typedef enum {
GPIO_OUTPUT_PP, // 推挽输出
GPIO_OUTPUT_OD, // 开漏输出
// ... 更多输出类型定义
} GPIO_OutputTypeTypeDef;

typedef enum {
GPIO_PULL_NONE,
GPIO_PULL_UP,
GPIO_PULL_DOWN,
// ... 更多上下拉定义
} GPIO_PullTypeDef;

// 初始化 GPIO 引脚
void HAL_GPIO_Init(GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode, GPIO_OutputTypeTypeDef output_type, GPIO_PullTypeDef pull);

// 设置 GPIO 引脚输出电平
void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, uint8_t value); // value: 0 或 1

// 读取 GPIO 引脚输入电平
uint8_t HAL_GPIO_ReadPin(GPIO_PinTypeDef 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
#include "hal_gpio.h"
// 假设使用 STM32 平台,需要包含相应的头文件
#include "stm32fxxx_hal.h" // 替换为你的平台 HAL 库头文件

void HAL_GPIO_Init(GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode, GPIO_OutputTypeTypeDef output_type, GPIO_PullTypeDef pull) {
GPIO_InitTypeDef GPIO_InitStruct = {0};

// 将 GPIO_PinTypeDef 转换为 HAL 库的引脚定义 (需要根据具体平台映射)
uint32_t hal_pin;
if (pin == GPIO_PIN_0) hal_pin = GPIO_PIN_0;
// ... 其他引脚映射

GPIO_InitStruct.Pin = hal_pin;

if (mode == GPIO_MODE_INPUT) {
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
} else if (mode == GPIO_MODE_OUTPUT) {
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 默认推挽输出,可以根据 output_type 调整
}
// ... 其他模式映射

if (pull == GPIO_PULL_NONE) {
GPIO_InitStruct.Pull = GPIO_NOPULL;
} else if (pull == GPIO_PULL_UP) {
GPIO_InitStruct.Pull = GPIO_PULLUP;
} // ... 其他上下拉映射

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 假设 GPIOA,需要根据实际硬件修改
}

void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, uint8_t value) {
uint32_t hal_pin;
if (pin == GPIO_PIN_0) hal_pin = GPIO_PIN_0;
// ... 其他引脚映射

HAL_GPIO_WritePin(GPIOA, hal_pin, (GPIO_PinState)value); // 假设 GPIOA
}

uint8_t HAL_GPIO_ReadPin(GPIO_PinTypeDef pin) {
uint32_t hal_pin;
if (pin == GPIO_PIN_0) hal_pin = GPIO_PIN_0;
// ... 其他引脚映射

return (uint8_t)HAL_GPIO_ReadPin(GPIOA, hal_pin); // 假设 GPIOA
}

类似地,可以实现 HAL 层的 SPI, I2C, ADC, PWM, Timer 等驱动,这里省略代码,只提供接口定义示例。

hal_spi.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef HAL_SPI_H
#define HAL_SPI_H

// ... SPI 相关定义 (时钟速度、模式等)

// SPI 初始化
void HAL_SPI_Init(/* ... SPI 初始化参数 */);

// SPI 发送数据
void HAL_SPI_Transmit(uint8_t *data, uint16_t size);

// SPI 接收数据
void HAL_SPI_Receive(uint8_t *data, uint16_t size);

// SPI 发送和接收数据
void HAL_SPI_TransmitReceive(uint8_t *tx_data, uint8_t *rx_data, uint16_t size);

#endif // HAL_SPI_H

hal_i2c.h:

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

// ... I2C 相关定义 (地址、速度等)

// I2C 初始化
void HAL_I2C_Init(/* ... I2C 初始化参数 */);

// I2C 发送数据
HAL_StatusTypeDef HAL_I2C_Master_Transmit(uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout);

// I2C 接收数据
HAL_StatusTypeDef HAL_I2C_Master_Receive(uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout);

#endif // HAL_I2C_H

hal_adc.h:

1
2
3
4
5
6
7
8
9
10
#ifndef HAL_ADC_H
#define HAL_ADC_H

// ADC 初始化
void HAL_ADC_Init(/* ... ADC 初始化参数 */);

// 读取 ADC 值
uint16_t HAL_ADC_GetValue(uint32_t channel); // channel: ADC 通道

#endif // HAL_ADC_H

hal_pwm.h:

1
2
3
4
5
6
7
8
9
10
#ifndef HAL_PWM_H
#define HAL_PWM_H

// PWM 初始化
void HAL_PWM_Init(/* ... PWM 初始化参数 */);

// 设置 PWM 占空比
void HAL_PWM_SetDutyCycle(uint32_t channel, uint32_t duty_cycle); // duty_cycle: 0-100 或 0-PWM_MAX

#endif // HAL_PWM_H

hal_timer.h:

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

// 定时器初始化
void HAL_Timer_Init(/* ... 定时器初始化参数 */);

// 启动定时器
void HAL_Timer_Start(uint32_t timer_id);

// 停止定时器
void HAL_Timer_Stop(uint32_t timer_id);

// 设置定时器回调函数 (用于周期性任务)
void HAL_Timer_SetCallback(uint32_t timer_id, void (*callback)(void));

#endif // HAL_TIMER_H

2. 板级支持包 (BSP)

bsp.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
#ifndef BSP_H
#define BSP_H

#include "hal_gpio.h"
#include "hal_spi.h"
#include "hal_i2c.h"
#include "hal_adc.h"
#include "hal_pwm.h"
#include "hal_timer.h"

// 板级硬件定义 (根据实际电路板修改)
#define LED_PIN GPIO_PIN_0
#define TFT_CS_PIN GPIO_PIN_1
#define TFT_RST_PIN GPIO_PIN_2
#define TFT_DC_PIN GPIO_PIN_3
#define ROTARY_ENCODER_A GPIO_PIN_4
#define ROTARY_ENCODER_B GPIO_PIN_5
#define HEATER_PWM_PIN GPIO_PIN_6
#define TEMP_SENSOR_ADC_CHANNEL 0 // ADC 通道 0

// 初始化板级硬件
void BSP_Init();

// 控制 LED 灯
void BSP_LED_Control(uint8_t on_off);

// 获取温度传感器值 (ADC 原始值)
uint16_t BSP_GetTemperatureSensorRawValue();

// 控制加热器功率 (PWM 占空比)
void BSP_Heater_SetPower(uint32_t power_percentage);

// TFT 屏幕相关函数 (更高层次的接口,例如初始化、清屏、显示字符串等,可以在 bsp_tft.c 中实现)
void BSP_TFT_Init();
void BSP_TFT_ClearScreen(uint16_t color);
void BSP_TFT_WriteString(uint16_t x, uint16_t y, char *str, uint16_t color, uint16_t bgcolor);

// 旋转编码器相关函数 (可以在 bsp_rotary_encoder.c 中实现)
uint8_t BSP_RotaryEncoder_GetDirection(); // 返回旋转方向 (顺时针/逆时针/无旋转)

#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
#include "bsp.h"
#include "delay.h" // 假设使用延时函数,需要根据实际情况添加

void BSP_Init() {
// 初始化 HAL 驱动 (根据实际硬件配置参数)
HAL_GPIO_Init(LED_PIN, GPIO_MODE_OUTPUT, GPIO_OUTPUT_PP, GPIO_PULL_NONE);
HAL_SPI_Init(/* ... SPI 初始化参数 */);
HAL_I2C_Init(/* ... I2C 初始化参数 */);
HAL_ADC_Init(/* ... ADC 初始化参数 */);
HAL_PWM_Init(/* ... PWM 初始化参数 */);
HAL_Timer_Init(/* ... Timer 初始化参数 */);

// 初始化 TFT 屏幕
BSP_TFT_Init();

// ... 其他板级初始化

delay_ms(100); // 延时等待硬件稳定
}

void BSP_LED_Control(uint8_t on_off) {
HAL_GPIO_WritePin(LED_PIN, on_off);
}

uint16_t BSP_GetTemperatureSensorRawValue() {
return HAL_ADC_GetValue(TEMP_SENSOR_ADC_CHANNEL);
}

void BSP_Heater_SetPower(uint32_t power_percentage) {
HAL_PWM_SetDutyCycle(/* ... 根据 power_percentage 计算占空比 */); // 需要根据 PWM 配置和加热器特性计算
}

// TFT 屏幕相关函数实现 (可以在 bsp_tft.c 中实现)
// ...

// 旋转编码器相关函数实现 (可以在 bsp_rotary_encoder.c 中实现)
// ...

3. 系统服务层 (System Services)

system_config.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 SYSTEM_CONFIG_H
#define SYSTEM_CONFIG_H

// 系统配置参数结构体
typedef struct {
float target_temperature;
float pid_kp;
float pid_ki;
float pid_kd;
uint8_t display_brightness;
// ... 更多配置参数
} SystemConfig_TypeDef;

// 加载系统配置
SystemConfig_TypeDef SystemConfig_Load();

// 保存系统配置
void SystemConfig_Save(SystemConfig_TypeDef *config);

// 获取配置参数
float SystemConfig_GetTargetTemperature();
float SystemConfig_GetPidKp();
// ... 其他配置参数获取函数

// 设置配置参数
void SystemConfig_SetTargetTemperature(float temperature);
void SystemConfig_SetPidKp(float kp);
// ... 其他配置参数设置函数

#endif // SYSTEM_CONFIG_H

system_config.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 "system_config.h"
#include "eeprom.h" // 假设使用 EEPROM 存储配置

// 默认配置参数
SystemConfig_TypeDef default_config = {
.target_temperature = 250.0f,
.pid_kp = 10.0f,
.pid_ki = 0.1f,
.pid_kd = 5.0f,
.display_brightness = 80,
// ... 默认值
};

SystemConfig_TypeDef SystemConfig_Load() {
SystemConfig_TypeDef config;
// 从 EEPROM 读取配置参数
if (EEPROM_Read(/* ... EEPROM 地址和大小 */, (uint8_t*)&config, sizeof(SystemConfig_TypeDef)) == EEPROM_OK) {
// 校验读取的数据是否有效 (例如校验和)
if (/* 数据有效性校验 */) {
return config;
}
}
// 读取失败或数据无效,返回默认配置
return default_config;
}

void SystemConfig_Save(SystemConfig_TypeDef *config) {
// 将配置参数写入 EEPROM
EEPROM_Write(/* ... EEPROM 地址和大小 */, (uint8_t*)config, sizeof(SystemConfig_TypeDef));
}

// 获取配置参数
float SystemConfig_GetTargetTemperature() {
SystemConfig_TypeDef config = SystemConfig_Load();
return config.target_temperature;
}
// ... 其他配置参数获取函数

// 设置配置参数
void SystemConfig_SetTargetTemperature(float temperature) {
SystemConfig_TypeDef config = SystemConfig_Load();
config.target_temperature = temperature;
SystemConfig_Save(&config);
}
// ... 其他配置参数设置函数

4. 应用层 (Application Layer)

temperature_control.h:

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

// 初始化温度控制模块
void TemperatureControl_Init();

// 执行温度控制 (PID 控制循环)
void TemperatureControl_Run();

// 设置目标温度
void TemperatureControl_SetTargetTemperature(float temperature);

// 获取当前温度
float TemperatureControl_GetCurrentTemperature();

// 获取目标温度
float TemperatureControl_GetTargetTemperature();

// 获取加热器功率百分比
uint32_t TemperatureControl_GetHeaterPowerPercentage();

#endif // TEMPERATURE_CONTROL_H

temperature_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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "temperature_control.h"
#include "bsp.h"
#include "system_config.h"
#include "hal_timer.h" // 使用定时器驱动 PID 控制循环

#define PID_CONTROL_PERIOD_MS 100 // PID 控制周期 100ms

static float current_temperature = 0.0f;
static float target_temperature = 250.0f;
static float last_error = 0.0f;
static float integral_error = 0.0f;
static float kp, ki, kd;

void TemperatureControl_Init() {
// 从配置加载 PID 参数
kp = SystemConfig_GetPidKp();
ki = SystemConfig_GetPidKi();
kd = SystemConfig_GetPidKd();
target_temperature = SystemConfig_GetTargetTemperature();

// 初始化定时器,用于周期性执行 PID 控制
HAL_Timer_Init(/* ... 定时器配置,周期为 PID_CONTROL_PERIOD_MS */);
HAL_Timer_SetCallback(/* ... 定时器 ID */, TemperatureControl_Run); // 设置定时器回调函数为 TemperatureControl_Run
HAL_Timer_Start(/* ... 定时器 ID */);
}

void TemperatureControl_Run() {
// 读取温度传感器原始值
uint16_t adc_value = BSP_GetTemperatureSensorRawValue();

// 将 ADC 值转换为温度值 (需要根据传感器特性和电路设计进行转换,例如查表法或线性公式)
current_temperature = ConvertAdcValueToTemperature(adc_value);

// PID 控制算法
float error = target_temperature - current_temperature;
integral_error += error * (PID_CONTROL_PERIOD_MS / 1000.0f); // 积分项
float derivative_error = (error - last_error) / (PID_CONTROL_PERIOD_MS / 1000.0f); // 微分项

float output = kp * error + ki * integral_error + kd * derivative_error; // PID 输出

// 限制 PID 输出范围 (例如 0-100%)
if (output < 0.0f) output = 0.0f;
if (output > 100.0f) output = 100.0f;

// 设置加热器功率
BSP_Heater_SetPower((uint32_t)output);

last_error = error;
}

// 示例 ADC 值到温度转换函数 (需要根据实际传感器和电路校准)
float ConvertAdcValueToTemperature(uint16_t adc_value) {
// 假设线性关系,需要根据实际情况调整参数
return (float)adc_value * 0.1f; // 示例公式,需要校准
}

void TemperatureControl_SetTargetTemperature(float temperature) {
target_temperature = temperature;
SystemConfig_SetTargetTemperature(temperature); // 保存到配置
}

float TemperatureControl_GetCurrentTemperature() {
return current_temperature;
}

float TemperatureControl_GetTargetTemperature() {
return target_temperature;
}

uint32_t TemperatureControl_GetHeaterPowerPercentage() {
// 可以通过读取 PWM 占空比来获取加热器功率百分比 (如果 HAL 层提供接口)
return 0; // 暂时返回 0,需要根据实际 HAL 实现
}

user_interface.h:

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

// 初始化用户界面模块
void UserInterface_Init();

// 运行用户界面 (处理用户输入、更新显示)
void UserInterface_Run();

// 显示主界面
void UserInterface_ShowMainScreen();

// 显示菜单界面
void UserInterface_ShowMenuScreen();

// 处理旋转编码器输入
void UserInterface_HandleRotaryEncoderInput(uint8_t direction); // direction: 旋转方向

// 处理按键输入 (如果有按键)
void UserInterface_HandleButtonInput(/* ... 按键事件参数 */);

#endif // USER_INTERFACE_H

user_interface.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
#include "user_interface.h"
#include "bsp.h"
#include "temperature_control.h"
#include "delay.h" // 延时函数

#define UI_REFRESH_PERIOD_MS 50 // UI 刷新周期 50ms

typedef enum {
UI_STATE_MAIN_SCREEN,
UI_STATE_MENU_SCREEN,
// ... 更多 UI 状态
} UIState_TypeDef;

static UIState_TypeDef current_ui_state = UI_STATE_MAIN_SCREEN;

void UserInterface_Init() {
BSP_TFT_Init(); // 初始化 TFT 屏幕
UserInterface_ShowMainScreen();

// 初始化定时器,用于周期性刷新 UI
HAL_Timer_Init(/* ... 定时器配置,周期为 UI_REFRESH_PERIOD_MS */);
HAL_Timer_SetCallback(/* ... 定时器 ID */, UserInterface_Run); // 设置定时器回调函数为 UserInterface_Run
HAL_Timer_Start(/* ... 定时器 ID */);
}

void UserInterface_Run() {
switch (current_ui_state) {
case UI_STATE_MAIN_SCREEN:
UserInterface_UpdateMainScreen();
break;
case UI_STATE_MENU_SCREEN:
UserInterface_UpdateMenuScreen();
break;
// ... 其他 UI 状态处理
default:
break;
}
}

void UserInterface_ShowMainScreen() {
current_ui_state = UI_STATE_MAIN_SCREEN;
BSP_TFT_ClearScreen(COLOR_BLACK); // 清屏黑色
// ... 绘制主界面元素 (温度显示、状态图标等)
UserInterface_UpdateMainScreen();
}

void UserInterface_UpdateMainScreen() {
float current_temp = TemperatureControl_GetCurrentTemperature();
float target_temp = TemperatureControl_GetTargetTemperature();
uint32_t heater_power = TemperatureControl_GetHeaterPowerPercentage();

// 更新 TFT 屏幕显示 (例如使用 BSP_TFT_WriteString 等函数)
char temp_str[20];
sprintf(temp_str, "Current: %.1f C", current_temp);
BSP_TFT_WriteString(10, 20, temp_str, COLOR_WHITE, COLOR_BLACK);

sprintf(temp_str, "Target: %.1f C", target_temp);
BSP_TFT_WriteString(10, 40, temp_str, COLOR_WHITE, COLOR_BLACK);

sprintf(temp_str, "Power: %lu%%", heater_power);
BSP_TFT_WriteString(10, 60, temp_str, COLOR_WHITE, COLOR_BLACK);

// ... 更新其他显示元素
}

void UserInterface_ShowMenuScreen() {
current_ui_state = UI_STATE_MENU_SCREEN;
BSP_TFT_ClearScreen(COLOR_BLUE); // 清屏蓝色
// ... 绘制菜单界面
UserInterface_UpdateMenuScreen();
}

void UserInterface_UpdateMenuScreen() {
// ... 更新菜单界面显示,例如高亮当前菜单项
}

void UserInterface_HandleRotaryEncoderInput(uint8_t direction) {
if (current_ui_state == UI_STATE_MAIN_SCREEN) {
if (direction == ROTARY_ENCODER_DIRECTION_CW) { // 顺时针旋转
float current_target_temp = TemperatureControl_GetTargetTemperature();
TemperatureControl_SetTargetTemperature(current_target_temp + 1.0f); // 目标温度 +1
} else if (direction == ROTARY_ENCODER_DIRECTION_CCW) { // 逆时针旋转
float current_target_temp = TemperatureControl_GetTargetTemperature();
TemperatureControl_SetTargetTemperature(current_target_temp - 1.0f); // 目标温度 -1
}
UserInterface_UpdateMainScreen(); // 更新主界面显示温度
} else if (current_ui_state == UI_STATE_MENU_SCREEN) {
// ... 处理菜单界面下的旋转编码器输入 (菜单项选择等)
}
}

// 旋转编码器输入处理任务 (示例,可以使用中断或轮询方式读取编码器)
void RotaryEncoder_Task() {
static uint8_t last_encoder_state = 0;
uint8_t current_encoder_state = BSP_RotaryEncoder_GetDirection(); // 获取旋转编码器状态

if (current_encoder_state != last_encoder_state) {
if (current_encoder_state == ROTARY_ENCODER_DIRECTION_CW) {
UserInterface_HandleRotaryEncoderInput(ROTARY_ENCODER_DIRECTION_CW);
} else if (current_encoder_state == ROTARY_ENCODER_DIRECTION_CCW) {
UserInterface_HandleRotaryEncoderInput(ROTARY_ENCODER_DIRECTION_CCW);
}
last_encoder_state = current_encoder_state;
}
}

// 主循环中调用 RotaryEncoder_Task
int main() {
BSP_Init();
TemperatureControl_Init();
UserInterface_Init();

while (1) {
RotaryEncoder_Task(); // 处理旋转编码器输入
// ... 其他任务 (例如按键扫描、错误处理等)
delay_ms(10); // 适当延时,降低 CPU 占用
}
}

main.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "bsp.h"
#include "temperature_control.h"
#include "user_interface.h"
#include "system_config.h"
#include "delay.h" // 延时函数

int main() {
BSP_Init(); // 初始化板级支持包
SystemConfig_Load(); // 加载系统配置
TemperatureControl_Init(); // 初始化温度控制模块
UserInterface_Init(); // 初始化用户界面模块

while (1) {
TemperatureControl_Run(); // 执行温度控制循环 (PID)
UserInterface_Run(); // 运行用户界面 (更新显示、处理输入)
// RotaryEncoder_Task(); // 旋转编码器输入已经在 UserInterface_Run 中处理了 (示例代码可以调整)
// ... 其他后台任务 (例如错误检测、数据记录等)

delay_ms(10); // 适当延时,降低 CPU 占用
}
}

5. 其他模块 (简要说明)

  • 状态机模块 (state_machine.h/c): 管理焊接台的不同状态 (待机、加热、工作、错误等),根据状态切换执行不同的操作。
  • 错误处理模块 (error_handler.h/c): 检测和处理系统错误 (传感器故障、加热器异常、过温等),提供错误日志记录和报警机制。
  • 菜单管理模块 (menu_manager.h/c): 管理菜单结构、菜单项、菜单操作,响应用户菜单选择。
  • EEPROM 驱动 (eeprom.h/c): 如果使用 EEPROM 存储配置参数,需要实现 EEPROM 驱动。
  • TFT 驱动 (bsp_tft.c): 实现 TFT 屏幕的底层驱动和高层 API (画点、画线、显示字符、显示图片等)。
  • 旋转编码器驱动 (bsp_rotary_encoder.c): 实现旋转编码器的驱动,检测旋转方向和按键事件。
  • 延时函数 (delay.h/c): 提供精确的毫秒级和微秒级延时函数。

代码编译和构建

  1. 工具链: 选择合适的嵌入式开发工具链,例如 GCC for ARM (如果使用 ARM Cortex-M 系列 MCU)。
  2. 项目管理: 使用 Makefile 或 IDE (例如 Keil MDK, IAR Embedded Workbench, Eclipse) 创建项目,管理代码文件和编译配置。
  3. 编译: 使用工具链编译所有 C 代码文件,生成目标文件 (.o)。
  4. 链接: 将目标文件链接成可执行文件 (.elf 或 .bin)。
  5. 烧录: 使用烧录器将可执行文件烧录到嵌入式设备的 Flash 存储器中。

测试验证和维护升级

  1. 单元测试: 对每个模块进行单元测试,验证模块功能的正确性。
  2. 集成测试: 将各个模块集成起来进行集成测试,验证模块之间的协同工作是否正常。
  3. 系统测试: 对整个系统进行全面测试,验证系统功能、性能、可靠性是否满足需求。
  4. 用户测试: 邀请用户进行实际使用测试,收集用户反馈,改进系统。
  5. 维护升级:
    • 固件升级: 预留固件升级接口 (例如通过串口或 USB),方便用户升级固件。
    • BUG 修复: 及时修复用户反馈的 BUG。
    • 功能扩展: 根据用户需求和技术发展,不断扩展系统功能。

总结

以上代码框架和架构设计提供了一个构建可靠、高效、可扩展的嵌入式焊接台系统的基础。实际项目中,需要根据具体的硬件平台、功能需求和资源限制进行详细设计和实现。需要根据各个模块的复杂程度进行扩展,并进行充分的测试和验证。 希望这份详细的解答能够帮助您理解嵌入式软件架构设计和 C 代码实现的关键步骤。

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