编程技术分享

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

0%

很高兴能为您详细解析这个基于GD32F470和AT32F403A的多功能表和焊台项目。这是一个典型的嵌入式系统集成项目,涉及硬件驱动、通信协议、用户界面、实时控制等多个方面。为了构建一个可靠、高效、可扩展的系统平台,我们需要精心设计软件架构,并采用经过实践验证的技术和方法。

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

系统架构设计:分层架构与事件驱动

针对这种复杂嵌入式系统,最适合的代码设计架构是分层架构事件驱动架构的结合。这种架构能够有效地组织代码,提高模块化程度,方便维护和扩展,并能很好地处理实时事件和用户交互。

1. 分层架构

我们将系统软件划分为以下几个层次,从底层硬件到顶层应用逐层抽象,降低各层之间的耦合度:

  • 硬件抽象层 (HAL - Hardware Abstraction Layer): 这是最底层,直接与硬件交互。HAL层提供统一的接口,屏蔽底层硬件差异。例如,GPIO驱动、SPI驱动、UART驱动、ADC驱动、定时器驱动、Flash驱动等都属于HAL层。对于GD32F470和AT32F403A,我们需要分别实现针对各自芯片的HAL层驱动。

  • 板级支持包 (BSP - Board Support Package): BSP层构建在HAL层之上,提供更高级别的硬件访问接口,并包含特定板卡相关的初始化和配置。例如,LCD屏幕驱动、触摸屏驱动、按键驱动、LED驱动、蜂鸣器驱动、磁吸接口驱动、温度传感器驱动、加热控制驱动等。BSP层会调用HAL层提供的接口来实现具体硬件操作。

  • 中间件层 (Middleware): 中间件层提供通用的软件服务和功能模块,不直接依赖于具体应用,但为应用层提供支持。例如,文件系统 (如FatFS)、图形库 (如LVGL或emWin)、网络协议栈 (如果需要联网功能)、通信协议 (如SPI、UART、I2C的协议封装)、数据处理算法、RTOS (实时操作系统) 等。

  • 应用层 (Application Layer): 应用层是系统的核心,实现具体的产品功能。对于多功能表,应用层包括测量功能、显示功能、用户界面逻辑等。对于多合一焊台,应用层包括温度控制、加热管理、状态监控、与多功能表的通信逻辑等。

  • 表示层 (Presentation Layer / UI Layer): 表示层负责用户交互和数据展示。对于本项目,主要是指触摸屏用户界面。表示层会调用应用层提供的接口来获取数据和执行操作,并将结果以图形化的方式呈现给用户。

2. 事件驱动架构

嵌入式系统通常是事件驱动的,需要实时响应外部事件(如按键、触摸、传感器数据变化)和内部事件(如定时器超时、通信数据接收)。事件驱动架构能够有效地处理这些异步事件,提高系统的实时性和响应性。

在我们的系统中,事件可以分为以下几类:

  • 硬件事件: 例如,GPIO中断事件(按键按下)、ADC转换完成事件、定时器中断事件、串口接收事件、触摸屏事件等。
  • 软件事件: 例如,任务间通信事件、状态机状态切换事件、应用层自定义事件等。

事件驱动架构的核心思想是:系统在空闲时等待事件发生,一旦事件发生,系统就根据事件类型执行相应的处理程序(事件处理函数)。处理程序完成后,系统又回到等待事件的状态。

3. 架构图示

为了更清晰地展示分层架构和事件驱动架构的结合,我们可以绘制一个简化的架构图:

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
+-----------------------+  表示层 (UI Layer) - 触摸屏界面
| |
+-----------------------+
| |
+-----------------------+ 应用层 (Application Layer)
| 多功能表应用 | 焊台应用
| - 测量逻辑 | - 温度控制逻辑
| - 显示控制 | - 加热管理
| - 用户界面逻辑 | - 状态监控
| | - 与多功能表通信
+-----------------------+
| |
+-----------------------+ 中间件层 (Middleware)
| - RTOS (FreeRTOS) | - 文件系统 (FatFS)
| - 图形库 (LVGL/emWin)| - 通信协议 (SPI/UART)
| - 数据处理算法 | - 状态机管理
| | - 配置管理
+-----------------------+
| |
+-----------------------+ 板级支持包 (BSP - Board Support Package)
| - LCD驱动 | - 触摸屏驱动
| - 按键驱动 | - LED驱动
| - 蜂鸣器驱动 | - 磁吸接口驱动
| - 温度传感器驱动 | - 加热控制驱动
| | - ... 其他板载外设驱动
+-----------------------+
| |
+-----------------------+ 硬件抽象层 (HAL - Hardware Abstraction Layer)
| - GPIO驱动 | - SPI驱动
| - UART驱动 | - ADC驱动
| - 定时器驱动 | - Flash驱动
| - DMA驱动 | - ... 其他芯片外设驱动
+-----------------------+
| |
+-----------------------+ 硬件层 (Hardware)
| - GD32F470 | - AT32F403A
| - LCD屏幕 | - 触摸屏
| - 传感器 | - 加热元件
| - 磁吸接口 | - ... 其他硬件组件
+-----------------------+

具体C代码实现 (示例,代码量远超3000行,以下仅为关键模块的示例)

为了演示分层架构和事件驱动架构的实现,并结合项目需求,以下提供一些关键模块的C代码示例。请注意,以下代码仅为示例,实际项目需要根据具体硬件和功能进行详细设计和实现。

1. HAL层 - GPIO驱动 (示例,以GD32F470为例)

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

#include "gd32f4xx.h" // GD32F470 头文件

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF // Alternate Function
} gpio_mode_t;

typedef enum {
GPIO_PULL_NONE,
GPIO_PULL_UP,
GPIO_PULL_DOWN
} gpio_pull_t;

typedef enum {
GPIO_SPEED_LOW,
GPIO_SPEED_MEDIUM,
GPIO_SPEED_HIGH
} gpio_speed_t;

typedef enum {
GPIO_OUTPUT_PP, // Push-Pull
GPIO_OUTPUT_OD // Open-Drain
} gpio_output_type_t;

// 初始化GPIO引脚
void hal_gpio_init(uint32_t port, uint32_t pin, gpio_mode_t mode, gpio_pull_t pull, gpio_speed_t speed, gpio_output_type_t output_type);

// 设置GPIO引脚输出电平
void hal_gpio_write_pin(uint32_t port, uint32_t pin, uint8_t value);

// 读取GPIO引脚输入电平
uint8_t hal_gpio_read_pin(uint32_t port, uint32_t pin);

#endif // HAL_GPIO_H

// hal_gpio.c
#include "hal_gpio.h"

void hal_gpio_init(uint32_t port, uint32_t pin, gpio_mode_t mode, gpio_pull_t pull, gpio_speed_t speed, gpio_output_type_t output_type) {
rcu_periph_enum periph;
gpio_mode_enum gpio_mode;
uint32_t gpio_pull_config = GPIO_PUPD_NONE;
gpio_output_options_enum gpio_output_options;
gpio_speed_enum gpio_speed_config;

// 使能GPIO时钟
if (port == GPIOA) periph = RCU_GPIOA;
else if (port == GPIOB) periph = RCU_GPIOB;
else if (port == GPIOC) periph = RCU_GPIOC;
else if (port == GPIOD) periph = RCU_GPIOD;
else if (port == GPIOE) periph = RCU_GPIOE;
else if (port == GPIOF) periph = RCU_GPIOF;
else if (port == GPIOG) periph = RCU_GPIOG;
else if (port == GPIOH) periph = RCU_GPIOH;
else return; // Invalid port
rcu_periph_clock_enable(periph);

// 配置GPIO模式
if (mode == GPIO_MODE_INPUT) gpio_mode = GPIO_MODE_INPUT;
else if (mode == GPIO_MODE_OUTPUT) gpio_mode = GPIO_MODE_OUTPUT;
else if (mode == GPIO_MODE_AF) gpio_mode = GPIO_MODE_AF;
else gpio_mode = GPIO_MODE_INPUT; // 默认输入模式

// 配置GPIO上下拉
if (pull == GPIO_PULL_UP) gpio_pull_config = GPIO_PUPD_PULLUP;
else if (pull == GPIO_PULL_DOWN) gpio_pull_config = GPIO_PUPD_PULLDOWN;
else gpio_pull_config = GPIO_PUPD_NONE;

// 配置GPIO速度
if (speed == GPIO_SPEED_LOW) gpio_speed_config = GPIO_SPEED_50MHZ; // 实际速度需要参考芯片手册
else if (speed == GPIO_SPEED_MEDIUM) gpio_speed_config = GPIO_SPEED_100MHZ;
else if (speed == GPIO_SPEED_HIGH) gpio_speed_config = GPIO_SPEED_100MHZ; // 高速
else gpio_speed_config = GPIO_SPEED_50MHZ;

// 配置GPIO输出类型
if (output_type == GPIO_OUTPUT_PP) gpio_output_options = GPIO_OTYPE_PP;
else if (output_type == GPIO_OUTPUT_OD) gpio_output_options = GPIO_OTYPE_OD;
else gpio_output_options = GPIO_OTYPE_PP;

gpio_mode_set(port, gpio_mode, gpio_pull_config, pin);
if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_AF) {
gpio_output_options_set(port, gpio_output_options, pin);
gpio_speed_set(port, gpio_speed_config, pin);
}
}

void hal_gpio_write_pin(uint32_t port, uint32_t pin, uint8_t value) {
if (value) {
gpio_bit_set(port, pin);
} else {
gpio_bit_reset(port, pin);
}
}

uint8_t hal_gpio_read_pin(uint32_t port, uint32_t pin) {
return gpio_input_bit_get(port, pin);
}

2. BSP层 - LCD驱动 (示例,假设使用SPI接口的LCD,GD32F470)

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
// bsp_lcd.h
#ifndef BSP_LCD_H
#define BSP_LCD_H

#include "hal_gpio.h"
#include "hal_spi.h"

// LCD 初始化
void bsp_lcd_init(void);

// LCD 设置显示区域
void bsp_lcd_set_area(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end);

// LCD 写入数据
void bsp_lcd_write_data(uint8_t data);

// LCD 写入命令
void bsp_lcd_write_command(uint8_t cmd);

// LCD 清屏
void bsp_lcd_clear(uint16_t color);

// LCD 画点
void bsp_lcd_draw_pixel(uint16_t x, uint16_t y, uint16_t color);

// ... 其他LCD驱动函数,如画线、画矩形、显示字符、显示字符串等

#endif // BSP_LCD_H

// bsp_lcd.c
#include "bsp_lcd.h"

// LCD 相关GPIO引脚定义 (根据实际硬件连接修改)
#define LCD_RST_PORT GPIOA
#define LCD_RST_PIN GPIO_PIN_0
#define LCD_DC_PORT GPIOA
#define LCD_DC_PIN GPIO_PIN_1
#define LCD_CS_PORT GPIOA
#define LCD_CS_PIN GPIO_PIN_2

// SPI 相关定义 (根据实际硬件连接修改)
#define LCD_SPI_PERIPH SPI0

void bsp_lcd_init(void) {
// 初始化LCD控制引脚
hal_gpio_init(LCD_RST_PORT, LCD_RST_PIN, GPIO_MODE_OUTPUT, GPIO_PULL_NONE, GPIO_SPEED_HIGH, GPIO_OUTPUT_PP);
hal_gpio_init(LCD_DC_PORT, LCD_DC_PIN, GPIO_MODE_OUTPUT, GPIO_PULL_NONE, GPIO_SPEED_HIGH, GPIO_OUTPUT_PP);
hal_gpio_init(LCD_CS_PORT, LCD_CS_PIN, GPIO_MODE_OUTPUT, GPIO_PULL_NONE, GPIO_SPEED_HIGH, GPIO_OUTPUT_PP);

// 初始化SPI
hal_spi_init(LCD_SPI_PERIPH); // 需要HAL层提供SPI初始化函数

// LCD 复位
hal_gpio_write_pin(LCD_RST_PORT, LCD_RST_PIN, 0);
delay_1ms(10); // 延时,具体时间参考LCD手册
hal_gpio_write_pin(LCD_RST_PORT, LCD_RST_PIN, 1);
delay_1ms(10);

// LCD 初始化序列 (参考LCD驱动芯片手册)
bsp_lcd_write_command(0xCF);
bsp_lcd_write_data(0x00);
bsp_lcd_write_data(0xC1);
bsp_lcd_write_data(0X30);
// ... 其他初始化命令

bsp_lcd_clear(0xFFFF); // 清屏为白色
}

void bsp_lcd_set_area(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end) {
bsp_lcd_write_command(0x2A); // Column Address Set
bsp_lcd_write_data(x_start >> 8);
bsp_lcd_write_data(x_start & 0xFF);
bsp_lcd_write_data(x_end >> 8);
bsp_lcd_write_data(x_end & 0xFF);

bsp_lcd_write_command(0x2B); // Row Address Set
bsp_lcd_write_data(y_start >> 8);
bsp_lcd_write_data(y_start & 0xFF);
bsp_lcd_write_data(y_end >> 8);
bsp_lcd_write_data(y_end & 0xFF);

bsp_lcd_write_command(0x2C); // Memory Write
}

void bsp_lcd_write_data(uint8_t data) {
hal_gpio_write_pin(LCD_DC_PORT, LCD_DC_PIN, 1); // Data mode
hal_gpio_write_pin(LCD_CS_PORT, LCD_CS_PIN, 0); // Select LCD
hal_spi_transfer(LCD_SPI_PERIPH, &data, 1, NULL, 0); // SPI发送数据,需要HAL层提供SPI传输函数
hal_gpio_write_pin(LCD_CS_PORT, LCD_CS_PIN, 1); // Deselect LCD
}

void bsp_lcd_write_command(uint8_t cmd) {
hal_gpio_write_pin(LCD_DC_PORT, LCD_DC_PIN, 0); // Command mode
hal_gpio_write_pin(LCD_CS_PORT, LCD_CS_PIN, 0); // Select LCD
hal_spi_transfer(LCD_SPI_PERIPH, &cmd, 1, NULL, 0); // SPI发送命令
hal_gpio_write_pin(LCD_CS_PORT, LCD_CS_PIN, 1); // Deselect LCD
}

void bsp_lcd_clear(uint16_t color) {
uint16_t i, j;
bsp_lcd_set_area(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1);
for (i = 0; i < LCD_WIDTH; i++) {
for (j = 0; j < LCD_HEIGHT; j++) {
bsp_lcd_write_data((color >> 8) & 0xFF);
bsp_lcd_write_data(color & 0xFF);
}
}
}

void bsp_lcd_draw_pixel(uint16_t x, uint16_t y, uint16_t color) {
if (x >= LCD_WIDTH || y >= LCD_HEIGHT) return; // 超出屏幕范围
bsp_lcd_set_area(x, y, x, y);
bsp_lcd_write_data((color >> 8) & 0xFF);
bsp_lcd_write_data(color & 0xFF);
}

// ... 其他LCD驱动函数实现

3. 中间件层 - 事件管理 (示例,简化事件处理)

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
// event_manager.h
#ifndef EVENT_MANAGER_H
#define EVENT_MANAGER_H

typedef enum {
EVENT_TYPE_NONE,
EVENT_TYPE_BUTTON_PRESS,
EVENT_TYPE_TOUCH_SCREEN,
EVENT_TYPE_TEMPERATURE_UPDATE,
EVENT_TYPE_COMM_DATA_RECEIVED,
// ... 其他事件类型
} event_type_t;

typedef struct {
event_type_t type;
void *data; // 事件数据指针
} event_t;

// 初始化事件管理器
void event_manager_init(void);

// 发送事件
void event_manager_send_event(event_t event);

// 事件处理循环
void event_manager_process_events(void);

// 注册事件处理函数
typedef void (*event_handler_t)(event_t event);
void event_manager_register_handler(event_type_t type, event_handler_t handler);

#endif // EVENT_MANAGER_H

// event_manager.c
#include "event_manager.h"
#include "FreeRTOS.h" // 假设使用FreeRTOS
#include "queue.h"

#define EVENT_QUEUE_LENGTH 16
static QueueHandle_t event_queue;

// 事件处理函数数组
static event_handler_t event_handlers[EVENT_TYPE_NONE]; // 数组大小根据事件类型数量调整

void event_manager_init(void) {
event_queue = xQueueCreate(EVENT_QUEUE_LENGTH, sizeof(event_t));
if (event_queue == NULL) {
// 队列创建失败处理
}
memset(event_handlers, 0, sizeof(event_handlers)); // 初始化处理函数数组
}

void event_manager_send_event(event_t event) {
if (xQueueSendToBack(event_queue, &event, 0) != pdTRUE) {
// 事件发送失败处理,例如队列满
}
}

void event_manager_process_events(void) {
event_t received_event;
while (1) {
if (xQueueReceive(event_queue, &received_event, portMAX_DELAY) == pdTRUE) {
// 接收到事件
if (received_event.type > EVENT_TYPE_NONE && received_event.type < sizeof(event_handlers)/sizeof(event_handler_t)) {
if (event_handlers[received_event.type] != NULL) {
event_handlers[received_event.type](received_event); // 调用注册的处理函数
} else {
// 没有注册处理函数,可以默认处理或者忽略
// 例如,打印日志 "No handler for event type: %d", received_event.type
}
} else {
// 无效事件类型
}
}
}
}

void event_manager_register_handler(event_type_t type, event_handler_t handler) {
if (type > EVENT_TYPE_NONE && type < sizeof(event_handlers)/sizeof(event_handler_t)) {
event_handlers[type] = handler;
}
}

// 事件处理任务 (如果使用RTOS)
void event_process_task(void *pvParameters) {
event_manager_process_events();
}

// 创建事件处理任务 (在main函数或者系统初始化函数中调用)
void create_event_task(void) {
BaseType_t xReturned;
xReturned = xTaskCreate(
event_process_task, /* 任务函数 */
"EventProcessTask", /* 任务名 */
128, /* 任务堆栈大小,需要根据实际情况调整 */
( void * ) NULL, /* 任务参数 */
tskIDLE_PRIORITY + 2, /* 任务优先级,根据实际情况调整 */
( TaskHandle_t * ) NULL);/* 任务句柄 */

if( xReturned != pdPASS )
{
// 任务创建失败处理
}
}

4. 应用层 - 多功能表应用 (示例,简化温度显示)

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
// meter_app.h
#ifndef METER_APP_H
#define METER_APP_H

// 初始化多功能表应用
void meter_app_init(void);

// 更新温度显示
void meter_app_update_temperature(float temperature);

// ... 其他多功能表应用相关函数

#endif // METER_APP_H

// meter_app.c
#include "meter_app.h"
#include "bsp_lcd.h"
#include "event_manager.h"
#include <stdio.h>
#include <string.h>

#define TEMP_DISPLAY_X 10
#define TEMP_DISPLAY_Y 20

void meter_app_init(void) {
// 初始化LCD
bsp_lcd_init();

// 注册温度更新事件处理函数
event_manager_register_handler(EVENT_TYPE_TEMPERATURE_UPDATE, meter_handle_temperature_event);

// ... 其他初始化操作
}

void meter_app_update_temperature(float temperature) {
char temp_str[20];
sprintf(temp_str, "Temp: %.1f C", temperature);

bsp_lcd_clear_area(TEMP_DISPLAY_X, TEMP_DISPLAY_Y, TEMP_DISPLAY_X + 100, TEMP_DISPLAY_Y + 20); // 清除之前的显示区域
bsp_lcd_display_string(TEMP_DISPLAY_X, TEMP_DISPLAY_Y, temp_str, FONT_SMALL, LCD_COLOR_BLACK, LCD_COLOR_WHITE); // 显示新的温度值
}

// 温度事件处理函数
void meter_handle_temperature_event(event_t event) {
if (event.type == EVENT_TYPE_TEMPERATURE_UPDATE) {
float temperature = *(float *)event.data;
meter_app_update_temperature(temperature);
}
}

// 清除LCD区域 (需要BSP层提供)
void bsp_lcd_clear_area(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end) {
uint16_t i, j;
for (i = x_start; i <= x_end; i++) {
for (j = y_start; j <= y_end; j++) {
bsp_lcd_draw_pixel(i, j, LCD_COLOR_WHITE); // 用背景色填充
}
}
}

// 显示字符串函数 (需要BSP层提供,或者使用图形库)
void bsp_lcd_display_string(uint16_t x, uint16_t y, const char *str, font_t font, uint16_t text_color, uint16_t bg_color) {
// ... 实现字符串显示逻辑,例如逐字符绘制,使用字体库
}

// ... 其他多功能表应用功能实现

5. 应用层 - 焊台应用 (示例,简化温度控制)

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
// solder_station_app.h
#ifndef SOLDER_STATION_APP_H
#define SOLDER_STATION_APP_H

// 初始化焊台应用
void solder_station_app_init(void);

// 设置目标温度
void solder_station_app_set_target_temperature(float target_temp);

// 获取当前温度
float solder_station_app_get_current_temperature(void);

// ... 其他焊台应用相关函数

#endif // SOLDER_STATION_APP_H

// solder_station_app.c
#include "solder_station_app.h"
#include "hal_adc.h" // 假设使用ADC读取温度传感器
#include "hal_timer.h" // 假设使用PWM控制加热
#include "event_manager.h"
#include "pid_controller.h" // PID控制器模块 (需要单独实现)

#define TEMP_SENSOR_ADC_CHANNEL ADC_CHANNEL_0 // 假设温度传感器连接到ADC通道0
#define HEATER_PWM_TIMER TIMER0 // 假设使用定时器0的PWM控制加热
#define HEATER_PWM_CHANNEL TIMER_CH_0 // 假设使用定时器0通道0的PWM控制加热

#define PID_KP 1.0f
#define PID_KI 0.1f
#define PID_KD 0.01f

static float current_temperature = 25.0f; // 初始温度
static float target_temperature = 200.0f; // 默认目标温度
static pid_controller_t pid_controller;

void solder_station_app_init(void) {
// 初始化ADC
hal_adc_init(TEMP_SENSOR_ADC_CHANNEL);

// 初始化PWM定时器
hal_timer_pwm_init(HEATER_PWM_TIMER, HEATER_PWM_CHANNEL);

// 初始化PID控制器
pid_controller_init(&pid_controller, PID_KP, PID_KI, PID_KD);
pid_controller_set_setpoint(&pid_controller, target_temperature);

// 启动温度采集和控制定时器 (例如,100ms周期)
hal_timer_start_periodic(TIMER1, 100, temperature_control_timer_callback); // 假设使用定时器1

// ... 其他初始化操作
}

void solder_station_app_set_target_temperature(float temp) {
target_temperature = temp;
pid_controller_set_setpoint(&pid_controller, target_temperature);
}

float solder_station_app_get_current_temperature(void) {
return current_temperature;
}

// 温度控制定时器回调函数 (每100ms执行一次)
void temperature_control_timer_callback(void) {
// 1. 读取温度传感器ADC值
uint16_t adc_value = hal_adc_read(TEMP_SENSOR_ADC_CHANNEL);

// 2. 将ADC值转换为温度 (需要根据传感器特性进行转换,例如查表或者线性转换)
current_temperature = convert_adc_to_temperature(adc_value);

// 3. PID控制计算PWM占空比
float pid_output = pid_controller_compute(&pid_controller, current_temperature);

// 4. 将PID输出转换为PWM占空比,并设置PWM
uint16_t pwm_duty_cycle = convert_pid_output_to_pwm_duty(pid_output);
hal_timer_pwm_set_duty_cycle(HEATER_PWM_TIMER, HEATER_PWM_CHANNEL, pwm_duty_cycle);

// 5. 发送温度更新事件给多功能表 (如果连接)
event_t temp_event;
temp_event.type = EVENT_TYPE_TEMPERATURE_UPDATE;
temp_event.data = &current_temperature;
event_manager_send_event(temp_event);
}

// 将ADC值转换为温度 (示例函数,需要根据实际传感器校准)
float convert_adc_to_temperature(uint16_t adc_value) {
// 线性转换示例 (需要根据传感器特性调整参数)
float temperature = (float)adc_value * 0.1f - 50.0f;
return temperature;
}

// 将PID输出转换为PWM占空比 (示例函数,需要根据加热器特性和PWM配置调整)
uint16_t convert_pid_output_to_pwm_duty(float pid_output) {
uint16_t duty_cycle = (uint16_t)(pid_output * 10.0f); // 假设PWM占空比范围 0-1000
if (duty_cycle < 0) duty_cycle = 0;
if (duty_cycle > 1000) duty_cycle = 1000;
return duty_cycle;
}

// ... 其他焊台应用功能实现,如状态监控、通信处理等

6. 中间件层 - PID控制器 (示例,简化PID)

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
// pid_controller.h
#ifndef PID_CONTROLLER_H
#define PID_CONTROLLER_H

typedef struct {
float kp; // 比例增益
float ki; // 积分增益
float kd; // 微分增益
float setpoint; // 目标值
float integral_term; // 积分项累积值
float last_error; // 上一次误差
} pid_controller_t;

// 初始化PID控制器
void pid_controller_init(pid_controller_t *pid, float kp, float ki, float kd);

// 设置目标值
void pid_controller_set_setpoint(pid_controller_t *pid, float setpoint);

// 计算PID输出
float pid_controller_compute(pid_controller_t *pid, float current_value);

// 重置积分项
void pid_controller_reset_integral(pid_controller_t *pid);

#endif // PID_CONTROLLER_H

// pid_controller.c
#include "pid_controller.h"

void pid_controller_init(pid_controller_t *pid, float kp, float ki, float kd) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->setpoint = 0.0f;
pid->integral_term = 0.0f;
pid->last_error = 0.0f;
}

void pid_controller_set_setpoint(pid_controller_t *pid, float setpoint) {
pid->setpoint = setpoint;
}

float pid_controller_compute(pid_controller_t *pid, float current_value) {
float error = pid->setpoint - current_value;

pid->integral_term += error; // 积分累积

float derivative_term = error - pid->last_error; // 微分项

float output = pid->kp * error + pid->ki * pid->integral_term + pid->kd * derivative_term;

pid->last_error = error; // 更新上一次误差

return output;
}

void pid_controller_reset_integral(pid_controller_t *pid) {
pid->integral_term = 0.0f;
}

项目中采用的各种技术和方法 (实践验证)

  • 实时操作系统 (RTOS): 例如 FreeRTOS,用于任务调度、资源管理、提高系统实时性和并发性。在本项目中,可以使用RTOS来管理UI任务、温度控制任务、通信任务等,保证系统的稳定性和响应速度。

  • 分层架构: 如上所述,将系统划分为HAL、BSP、中间件、应用层和表示层,提高代码模块化、可维护性和可移植性。

  • 事件驱动架构: 通过事件管理器处理异步事件,提高系统响应速度和效率。

  • 状态机 (State Machine): 用于管理系统的不同工作模式和状态转换。例如,焊台可以有待机状态、加热状态、恒温状态等,状态机可以清晰地描述这些状态和状态之间的切换逻辑。

  • PID控制算法: 用于精确的温度控制。PID控制器可以根据目标温度和当前温度的偏差,自动调节加热功率,实现快速升温和精确控温。

  • SPI/UART通信协议: 用于多功能表和焊台之间的通信。根据数据传输量和实时性要求选择合适的协议。SPI适合高速数据传输,UART适合低速数据传输,可以根据实际情况选择。

  • 触摸屏驱动: 实现触摸屏的输入检测和处理,为用户提供直观的交互界面。

  • 图形库 (LVGL/emWin): 如果需要更复杂的UI界面,可以使用图形库来简化UI开发,提供丰富的UI组件和图形渲染功能。

  • 版本控制系统 (Git): 用于代码版本管理、协作开发和代码追溯。

  • 调试工具 (JTAG/SWD): 使用JTAG/SWD调试接口和调试器 (如ST-Link、J-Link) 进行代码调试和程序下载。

  • 单元测试: 针对关键模块 (如HAL驱动、PID控制器、通信协议等) 编写单元测试用例,确保模块功能的正确性。

  • 集成测试和系统测试: 将各个模块集成起来进行测试,验证系统整体功能的完整性和稳定性。

  • 代码审查: 进行代码审查,提高代码质量,减少bug。

  • 代码规范: 遵循统一的代码编写规范,提高代码可读性和可维护性。

  • 模块化设计: 将系统功能分解为独立的模块,降低模块之间的耦合度,方便模块的复用和替换。

  • 配置管理: 使用配置文件或者宏定义来管理系统配置参数,方便参数调整和维护。

  • 日志系统: 实现日志记录功能,方便问题排查和系统监控。

  • OTA升级 (可选): 如果需要远程升级功能,可以考虑实现OTA (Over-The-Air) 升级,方便固件更新和维护。

维护升级考虑

  • 模块化设计: 模块化设计使得系统更容易维护和升级。当需要修改或添加新功能时,只需要修改或添加相应的模块,而不会影响其他模块。

  • 清晰的接口定义: 各层之间、模块之间通过清晰定义的接口进行交互,方便模块的替换和升级。

  • 可配置性: 将一些配置参数 (如PID参数、通信参数、显示参数等) 外部化,方便用户或维护人员进行调整,无需重新编译代码。

  • 版本控制: 使用版本控制系统 (Git) 可以方便地管理代码版本,回溯历史版本,进行bug修复和功能升级。

  • OTA升级 (可选): 如果实现了OTA升级功能,可以方便地进行远程固件更新,修复bug,添加新功能。

总结

这个基于GD32F470和AT32F403A的多功能表和焊台项目是一个典型的复杂嵌入式系统。采用分层架构事件驱动架构能够有效地组织代码,提高系统的可靠性、效率和可扩展性。结合RTOSPID控制SPI/UART通信触摸屏驱动等成熟的嵌入式技术,可以构建一个功能完善、性能优良的产品。在开发过程中,需要注重模块化设计代码规范充分的测试良好的维护性,才能最终交付一个高质量的嵌入式系统。

希望以上详细的架构设计和代码示例能够帮助您理解和实现这个项目。实际项目开发过程中,还需要根据具体硬件和功能需求进行更深入的设计和实现。代码量肯定会远超3000行,需要团队协作和长期迭代才能完成。

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