编程技术分享

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

0%

简介:P150C Pro-D系列直流恒流型数控电子负载是基于STC8H系列单片机为主控芯片开发而成,该产品支持±150V电压测量/15A电流测量/150W功率耗散,测量精度高达0.5%,并且支持多种测量模式

好的,作为一名高级嵌入式软件开发工程师,我将为您详细阐述P150C Pro-D系列直流恒流型数控电子负载的嵌入式软件架构设计,并提供相应的C代码示例。由于代码量庞大,我将重点展示核心模块的代码框架和关键功能实现,并解释所采用的技术和方法。最终代码量会尽量接近3000行,以涵盖一个相对完整的系统实现。
关注微信公众号,提前获取相关推文

系统架构设计

为了构建一个可靠、高效、可扩展的嵌入式系统平台,我将采用分层架构的设计思想,将系统划分为以下几个层次:

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

    • 功能: 屏蔽底层硬件差异,为上层软件提供统一的硬件接口。
    • 模块
      • ADC 驱动:负责模数转换器 (ADC) 的初始化、配置、采样和数据读取。
      • DAC 驱动:负责数模转换器 (DAC) 的初始化、配置和电压输出控制(如果需要模拟负载电阻或电压控制)。
      • GPIO 驱动:负责通用输入/输出端口 (GPIO) 的配置和控制,例如按键输入、LED 指示灯、继电器控制等。
      • 定时器驱动:负责定时器的初始化、配置和中断处理,用于定时采样、PWM 生成、系统时钟等。
      • UART 驱动:负责通用异步收发传输器 (UART) 的初始化、配置、数据发送和接收,用于串口通信。
      • 显示驱动:负责显示屏 (LCD/TFT) 的初始化、清屏、字符/图形显示等,例如 SPI 或并行接口驱动。
      • 风扇驱动:负责风扇控制,例如 PWM 调速或开关控制。
      • EEPROM/Flash 驱动:负责非易失性存储器 (EEPROM/Flash) 的读写操作,用于存储配置参数、校准数据等。
      • 看门狗驱动:负责看门狗定时器的配置和喂狗操作,提高系统可靠性。
  2. **板级支持包 (BSP, Board Support Package)**:

    • 功能: 初始化 MCU 硬件资源,包括时钟配置、外设初始化、中断向量表设置等,为操作系统或裸机应用提供基础支持。
    • 模块
      • 系统时钟初始化:配置 MCU 的系统时钟频率。
      • 外设时钟使能:使能各个外设的时钟。
      • GPIO 初始化:配置 GPIO 的功能和模式。
      • 中断控制器初始化:配置中断优先级和使能中断。
      • 低功耗管理:配置低功耗模式(可选)。
  3. **服务层 (Service Layer)**:

    • 功能: 提供系统核心功能模块,例如测量、控制、显示、通信、保护等。
    • 模块
      • 测量服务
        • 电压测量模块:负责电压信号的采集、滤波、校准和计算。
        • 电流测量模块:负责电流信号的采集、滤波、校准和计算。
        • 功率计算模块:根据电压和电流计算功率。
        • 精度校准模块:提供电压、电流、功率的校准功能。
      • 控制服务
        • 恒流 (CC) 控制模块:实现恒流模式下的负载电流控制。
        • 恒压 (CV) 控制模块:实现恒压模式下的负载电压控制。
        • 恒功率 (CP) 控制模块:实现恒功率模式下的负载功率控制。
        • 负载使能/禁用模块:控制电子负载的开启和关闭。
      • 显示服务
        • 显示管理模块:负责显示内容的组织和管理。
        • UI 界面模块:实现用户界面,例如菜单、参数显示、状态显示等。
      • 通信服务
        • 串口通信模块:处理串口数据接收和发送,实现上位机通信。
        • 协议解析模块:解析上位机发送的控制命令。
        • 数据打包模块:将测量数据和状态信息打包发送给上位机。
      • 保护服务
        • 过压保护模块:检测输入电压是否超过设定阈值,并采取保护措施。
        • 过流保护模块:检测负载电流是否超过设定阈值,并采取保护措施。
        • 过功率保护模块:检测负载功率是否超过设定阈值,并采取保护措施。
        • 过温保护模块:检测系统温度是否超过设定阈值(通过温度传感器),并采取保护措施。
      • 风扇控制服务
        • 温控风扇模块:根据系统温度自动调节风扇转速。
        • 手动风扇控制模块:提供手动调节风扇转速的功能(可选)。
      • 参数配置服务
        • 参数存储模块:将用户配置参数存储到 EEPROM/Flash 中。
        • 参数加载模块:从 EEPROM/Flash 中加载配置参数。
  4. **应用层 (Application Layer)**:

    • 功能: 实现系统的整体逻辑和用户交互,协调各个服务模块完成特定任务。
    • 模块
      • **主程序模块 (main 函数)**:系统入口,负责初始化所有模块,进入主循环,处理用户输入和系统事件。
      • 状态机模块:管理电子负载的不同工作状态,例如待机状态、恒流模式、恒压模式、恒功率模式、保护状态等。
      • 按键处理模块:处理按键输入,例如模式切换、参数设置、菜单导航等。
      • 命令解析模块:解析上位机通过串口发送的控制命令。
      • 错误处理模块:处理系统运行过程中出现的错误,例如硬件故障、参数错误等。

技术和方法

  • 模块化设计:将系统分解成多个模块,每个模块负责特定的功能,提高代码可读性、可维护性和可重用性。
  • 分层架构:采用分层架构,降低层与层之间的耦合度,提高系统的可扩展性和灵活性。
  • 状态机:使用状态机管理系统的工作状态,清晰地描述系统的行为和状态转换。
  • 中断驱动:充分利用中断机制,提高系统实时性和响应速度,例如 ADC 采样中断、定时器中断、串口接收中断等。
  • 查表法:对于非线性校准或复杂的计算,可以使用查表法提高效率和精度。
  • 滤波算法:采用数字滤波算法,例如滑动平均滤波、中值滤波、卡尔曼滤波等,降低测量噪声,提高数据稳定性。
  • PID 控制算法:在恒流、恒压、恒功率控制中,可以使用 PID 控制算法实现精确的闭环控制。
  • 软件校准:通过软件校准算法,补偿硬件误差,提高测量精度。
  • 错误处理机制:建立完善的错误处理机制,包括错误检测、错误报告和错误恢复,提高系统可靠性。
  • 代码注释和文档:编写清晰的代码注释和文档,提高代码可读性和可维护性。
  • 版本控制:使用版本控制工具 (例如 Git) 管理代码,方便代码管理和协同开发。
  • 软件测试:进行单元测试、集成测试和系统测试,确保软件质量。

C 代码实现 (示例代码框架和关键功能)

以下代码示例将重点展示各个模块的框架和关键功能实现,由于代码量限制,每个模块只提供部分核心代码,实际项目中需要根据具体需求进行完善。

(1) HAL 层 (HAL Layer)

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

#include "stdint.h"

// ADC 初始化配置结构体
typedef struct {
uint32_t clock_prescaler; // ADC 时钟预分频
uint8_t resolution; // ADC 分辨率 (例如 8位, 10位, 12位)
uint8_t channel; // ADC 通道
} HAL_ADC_ConfigTypeDef;

// 初始化 ADC
void HAL_ADC_Init(HAL_ADC_ConfigTypeDef *config);

// 读取 ADC 原始值
uint16_t HAL_ADC_ReadRawValue(uint8_t channel);

// 获取 ADC 电压值 (需要根据参考电压和分辨率计算)
float HAL_ADC_GetVoltage(uint8_t channel);

#endif // HAL_ADC_H
  • hal_adc.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
#include "hal_adc.h"
#include "stc8h_adc.h" // 假设 STC8H 的 ADC 驱动头文件

// 初始化 ADC
void HAL_ADC_Init(HAL_ADC_ConfigTypeDef *config) {
// 配置 STC8H ADC 相关寄存器,例如 ADC_CONTR, ADC_RES, ADC_CHS 等
STC8H_ADC_SetClockPrescaler(config->clock_prescaler);
STC8H_ADC_SetResolution(config->resolution);
// ... 其他 ADC 初始化配置 ...
STC8H_ADC_Enable(); // 使能 ADC
}

// 读取 ADC 原始值
uint16_t HAL_ADC_ReadRawValue(uint8_t channel) {
STC8H_ADC_SelectChannel(channel);
STC8H_ADC_StartConversion();
while (!STC8H_ADC_IsConversionComplete()); // 等待转换完成
return STC8H_ADC_GetResult();
}

// 获取 ADC 电压值
float HAL_ADC_GetVoltage(uint8_t channel) {
uint16_t rawValue = HAL_ADC_ReadRawValue(channel);
// 假设参考电压为 3.3V,分辨率为 12 位
float voltage = (float)rawValue * 3.3f / 4095.0f;
return voltage;
}
  • hal_dac.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef HAL_DAC_H
#define HAL_DAC_H

#include "stdint.h"

// DAC 初始化配置结构体
typedef struct {
uint32_t clock_prescaler; // DAC 时钟预分频 (如果 DAC 需要时钟)
uint8_t resolution; // DAC 分辨率 (例如 8位, 10位, 12位)
uint8_t channel; // DAC 通道
} HAL_DAC_ConfigTypeDef;

// 初始化 DAC
void HAL_DAC_Init(HAL_DAC_ConfigTypeDef *config);

// 设置 DAC 输出电压值
void HAL_DAC_SetVoltage(uint8_t channel, float voltage);

// 设置 DAC 输出数字值 (根据分辨率和参考电压计算)
void HAL_DAC_SetRawValue(uint8_t channel, uint16_t rawValue);

#endif // HAL_DAC_H
  • hal_dac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "hal_dac.h"
#include "stc8h_dac.h" // 假设 STC8H 的 DAC 驱动头文件

// 初始化 DAC
void HAL_DAC_Init(HAL_DAC_ConfigTypeDef *config) {
// 配置 STC8H DAC 相关寄存器,例如 DAC_CONTR, DAC_DATA 等
// ... DAC 初始化配置 ...
STC8H_DAC_Enable(); // 使能 DAC
}

// 设置 DAC 输出电压值
void HAL_DAC_SetVoltage(uint8_t channel, float voltage) {
// 假设参考电压为 3.3V,分辨率为 12 位
uint16_t rawValue = (uint16_t)(voltage * 4095.0f / 3.3f);
HAL_DAC_SetRawValue(channel, rawValue);
}

// 设置 DAC 输出数字值
void HAL_DAC_SetRawValue(uint8_t channel, uint16_t rawValue) {
STC8H_DAC_SelectChannel(channel);
STC8H_DAC_SetData(rawValue);
}
  • 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
#ifndef HAL_GPIO_H
#define HAL_GPIO_H

#include "stdint.h"

// GPIO 端口定义 (根据 STC8H 具体型号定义)
typedef enum {
GPIO_PORT_P0,
GPIO_PORT_P1,
GPIO_PORT_P2,
GPIO_PORT_P3,
GPIO_PORT_P4,
// ... 其他端口 ...
GPIO_PORT_MAX
} GPIO_PortTypeDef;

// GPIO 引脚定义 (0-7)
typedef enum {
GPIO_PIN_0,
GPIO_PIN_1,
GPIO_PIN_2,
GPIO_PIN_3,
GPIO_PIN_4,
GPIO_PIN_5,
GPIO_PIN_6,
GPIO_PIN_7,
GPIO_PIN_ALL // 所有引脚
} GPIO_PinTypeDef;

// GPIO 模式定义
typedef enum {
GPIO_MODE_INPUT, // 输入模式
GPIO_MODE_OUTPUT, // 输出模式
GPIO_MODE_INPUT_PU, // 输入上拉模式
GPIO_MODE_OUTPUT_OD, // 输出开漏模式
// ... 其他模式 ...
} GPIO_ModeTypeDef;

// 初始化 GPIO 引脚
void HAL_GPIO_Init(GPIO_PortTypeDef port, GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode);

// 设置 GPIO 引脚输出高电平
void HAL_GPIO_SetPinHigh(GPIO_PortTypeDef port, GPIO_PinTypeDef pin);

// 设置 GPIO 引脚输出低电平
void HAL_GPIO_SetPinLow(GPIO_PortTypeDef port, GPIO_PinTypeDef pin);

// 读取 GPIO 引脚电平
uint8_t HAL_GPIO_ReadPin(GPIO_PortTypeDef port, 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
#include "hal_gpio.h"
#include "stc8h_gpio.h" // 假设 STC8H 的 GPIO 驱动头文件

// 初始化 GPIO 引脚
void HAL_GPIO_Init(GPIO_PortTypeDef port, GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode) {
// 配置 STC8H GPIO 相关寄存器,例如 P0M0, P0M1, P1M0, P1M1 等
STC8H_GPIO_SetPinMode(port, pin, mode);
// ... 其他 GPIO 初始化配置 ...
}

// 设置 GPIO 引脚输出高电平
void HAL_GPIO_SetPinHigh(GPIO_PortTypeDef port, GPIO_PinTypeDef pin) {
STC8H_GPIO_SetOutputHigh(port, pin);
}

// 设置 GPIO 引脚输出低电平
void HAL_GPIO_SetPinLow(GPIO_PortTypeDef port, GPIO_PinTypeDef pin) {
STC8H_GPIO_SetOutputLow(port, pin);
}

// 读取 GPIO 引脚电平
uint8_t HAL_GPIO_ReadPin(GPIO_PortTypeDef port, GPIO_PinTypeDef pin) {
return STC8H_GPIO_ReadInput(port, pin);
}
  • hal_timer.h, hal_timer.c, hal_uart.h, hal_uart.c, hal_display.h, hal_display.c, hal_fan.h, hal_fan.c, hal_eeprom.h, hal_eeprom.c, hal_watchdog.h, hal_watchdog.c 等 HAL 层模块的头文件和源文件,代码结构类似,主要封装 STC8H 硬件外设的驱动函数。 * (此处省略代码,实际项目中需要根据具体硬件和需求实现) *

(2) BSP 层 (BSP Layer)

  • bsp.h
1
2
3
4
5
6
#ifndef BSP_H
#define BSP_H

void BSP_Init(void); // BSP 初始化函数

#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
46
47
48
49
50
51
52
53
54
55
56
57
#include "bsp.h"
#include "stc8h_system.h" // 假设 STC8H 系统初始化头文件
#include "hal_gpio.h"
#include "hal_adc.h"
#include "hal_dac.h"
#include "hal_timer.h"
#include "hal_uart.h"
#include "hal_display.h"
#include "hal_fan.h"
#include "hal_eeprom.h"
#include "hal_watchdog.h"

void BSP_Init(void) {
// 系统时钟初始化
STC8H_SystemClockInit();

// GPIO 初始化
HAL_GPIO_Init(...); // 初始化 LED 指示灯 GPIO
HAL_GPIO_Init(...); // 初始化 按键 GPIO
HAL_GPIO_Init(...); // 初始化 风扇控制 GPIO
// ... 其他 GPIO 初始化 ...

// ADC 初始化
HAL_ADC_ConfigTypeDef adcConfig = {
.clock_prescaler = ADC_CLOCK_DIV_8, // 示例:ADC 时钟预分频为 8
.resolution = ADC_RESOLUTION_12BIT, // 示例:ADC 分辨率为 12 位
.channel = ADC_CHANNEL_0 // 示例:默认通道
};
HAL_ADC_Init(&adcConfig);

// DAC 初始化 (如果需要)
HAL_DAC_ConfigTypeDef dacConfig = {
// ... DAC 配置 ...
};
HAL_DAC_Init(&dacConfig);

// 定时器初始化
HAL_Timer_Init(...);

// UART 初始化
HAL_UART_Init(...);

// 显示屏初始化
HAL_Display_Init(...);

// 风扇驱动初始化
HAL_Fan_Init(...);

// EEPROM/Flash 初始化
HAL_EEPROM_Init(...);

// 看门狗初始化
HAL_Watchdog_Init(...);

// 中断初始化 (例如 NVIC 配置)
STC8H_NVIC_Init();
}

(3) 服务层 (Service Layer)

  • measurement_service.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
#ifndef MEASUREMENT_SERVICE_H
#define MEASUREMENT_SERVICE_H

#include "stdint.h"

// 测量数据结构体
typedef struct {
float voltage; // 电压值 (V)
float current; // 电流值 (A)
float power; // 功率值 (W)
float temperature; // 温度值 (°C) (可选)
} MeasurementDataTypeDef;

// 初始化测量服务
void MeasurementService_Init(void);

// 获取测量数据
MeasurementDataTypeDef MeasurementService_GetData(void);

// 进行电压校准
void MeasurementService_VoltageCalibration(float referenceVoltage);

// 进行电流校准
void MeasurementService_CurrentCalibration(float referenceCurrent);

#endif // MEASUREMENT_SERVICE_H
  • measurement_service.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
#include "measurement_service.h"
#include "hal_adc.h"
#include "config.h" // 假设配置文件

// 电压校准系数
static float voltageCalibrationFactor = 1.0f;
// 电流校准系数
static float currentCalibrationFactor = 1.0f;

// 初始化测量服务
void MeasurementService_Init(void) {
// 初始化 ADC (已经在 BSP 中完成)
// ... 其他初始化 ...
}

// 获取测量数据
MeasurementDataTypeDef MeasurementService_GetData(void) {
MeasurementDataTypeDef data;

// 读取电压 ADC 值,假设电压通道为 ADC_CHANNEL_VOLTAGE
float voltageRaw = HAL_ADC_GetVoltage(ADC_CHANNEL_VOLTAGE);
// 假设电压分压比例为 VOLTAGE_DIVIDER_RATIO (例如 10:1 分压)
data.voltage = voltageRaw * VOLTAGE_DIVIDER_RATIO * voltageCalibrationFactor;

// 读取电流 ADC 值,假设电流通道为 ADC_CHANNEL_CURRENT
float currentRaw = HAL_ADC_GetVoltage(ADC_CHANNEL_CURRENT);
// 假设电流采样电阻阻值为 CURRENT_SENSE_RESISTOR (例如 0.1 欧姆)
data.current = currentRaw / CURRENT_SENSE_RESISTOR * currentCalibrationFactor;

// 计算功率
data.power = data.voltage * data.current;

// 读取温度传感器数据 (可选)
// data.temperature = HAL_ADC_GetTemperature(ADC_CHANNEL_TEMPERATURE);

return data;
}

// 进行电压校准
void MeasurementService_VoltageCalibration(float referenceVoltage) {
MeasurementDataTypeDef currentData = MeasurementService_GetData();
voltageCalibrationFactor = referenceVoltage / currentData.voltage;
}

// 进行电流校准
void MeasurementService_CurrentCalibration(float referenceCurrent) {
MeasurementDataTypeDef currentData = MeasurementService_GetData();
currentCalibrationFactor = referenceCurrent / currentData.current;
}
  • control_service.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
#ifndef CONTROL_SERVICE_H
#define CONTROL_SERVICE_H

#include "stdint.h"

// 控制模式定义
typedef enum {
CONTROL_MODE_CC, // 恒流模式
CONTROL_MODE_CV, // 恒压模式
CONTROL_MODE_CP, // 恒功率模式
CONTROL_MODE_OFF // 负载关闭
} ControlModeTypeDef;

// 初始化控制服务
void ControlService_Init(void);

// 设置控制模式
void ControlService_SetMode(ControlModeTypeDef mode);

// 设置恒流模式电流值 (A)
void ControlService_SetCCCurrent(float current);

// 设置恒压模式电压值 (V)
void ControlService_SetCVVoltage(float voltage);

// 设置恒功率模式功率值 (W)
void ControlService_SetCPPower(float power);

// 使能负载
void ControlService_EnableLoad(void);

// 禁用负载
void ControlService_DisableLoad(void);

// 获取当前控制模式
ControlModeTypeDef ControlService_GetMode(void);

#endif // CONTROL_SERVICE_H
  • control_service.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
#include "control_service.h"
#include "hal_dac.h"
#include "measurement_service.h"
#include "pid_controller.h" // 假设 PID 控制器模块

// 当前控制模式
static ControlModeTypeDef currentControlMode = CONTROL_MODE_OFF;
// 恒流模式目标电流值
static float targetCCCurrent = 0.0f;
// 恒压模式目标电压值
static float targetCVVoltage = 0.0f;
// 恒功率模式目标功率值
static float targetCPPower = 0.0f;

// PID 控制器实例 (用于 CC, CV, CP 模式)
static PID_ControllerTypeDef ccPidController;
static PID_ControllerTypeDef cvPidController;
static PID_ControllerTypeDef cpPidController;

// 初始化控制服务
void ControlService_Init(void) {
// 初始化 DAC (已经在 BSP 中完成)

// 初始化 PID 控制器参数 (需要根据实际系统调试)
PID_Init(&ccPidController, 1.0f, 0.1f, 0.01f); // 示例 PID 参数
PID_Init(&cvPidController, 1.0f, 0.1f, 0.01f);
PID_Init(&cpPidController, 1.0f, 0.1f, 0.01f);

// 默认禁用负载
ControlService_DisableLoad();
}

// 设置控制模式
void ControlService_SetMode(ControlModeTypeDef mode) {
currentControlMode = mode;
if (mode == CONTROL_MODE_OFF) {
ControlService_DisableLoad();
} else {
ControlService_EnableLoad();
}
}

// 设置恒流模式电流值
void ControlService_SetCCCurrent(float current) {
targetCCCurrent = current;
}

// 设置恒压模式电压值
void ControlService_SetCVVoltage(float voltage) {
targetCVVoltage = voltage;
}

// 设置恒功率模式功率值
void ControlService_SetCPPower(float power) {
targetCPPower = power;
}

// 使能负载
void ControlService_EnableLoad(void) {
// 实际项目中需要控制功率器件 (例如 MOSFET) 的导通,这里简化为 DAC 输出控制信号
// 例如控制 DAC 输出电压,间接控制负载电流
// ... 负载使能硬件控制 ...
HAL_DAC_SetVoltage(DAC_CHANNEL_LOAD_CONTROL, 0.5f); // 示例:输出一个初始电压
}

// 禁用负载
void ControlService_DisableLoad(void) {
// 关闭功率器件
// ... 负载禁用硬件控制 ...
HAL_DAC_SetVoltage(DAC_CHANNEL_LOAD_CONTROL, 0.0f); // 示例:输出 0V 关闭负载
}

// 获取当前控制模式
ControlModeTypeDef ControlService_GetMode(void) {
return currentControlMode;
}

// 定期执行的控制循环 (例如在定时器中断中调用)
void ControlService_ControlLoop(void) {
if (currentControlMode == CONTROL_MODE_CC) {
// 恒流模式 PID 控制
MeasurementDataTypeDef data = MeasurementService_GetData();
float currentError = targetCCCurrent - data.current;
float controlOutput = PID_Calculate(&ccPidController, currentError);
// 将控制输出转换为 DAC 输出电压,控制负载电流
HAL_DAC_SetVoltage(DAC_CHANNEL_LOAD_CONTROL, controlOutput);
} else if (currentControlMode == CONTROL_MODE_CV) {
// 恒压模式 PID 控制
MeasurementDataTypeDef data = MeasurementService_GetData();
float voltageError = targetCVVoltage - data.voltage;
float controlOutput = PID_Calculate(&cvPidController, voltageError);
HAL_DAC_SetVoltage(DAC_CHANNEL_LOAD_CONTROL, controlOutput);
} else if (currentControlMode == CONTROL_MODE_CP) {
// 恒功率模式 PID 控制
MeasurementDataTypeDef data = MeasurementService_GetData();
float powerError = targetCPPower - data.power;
float controlOutput = PID_Calculate(&cpPidController, powerError);
HAL_DAC_SetVoltage(DAC_CHANNEL_LOAD_CONTROL, controlOutput);
}
// CONTROL_MODE_OFF 模式下,负载已禁用,无需控制
}
  • display_service.h, display_service.c, comm_service.h, comm_service.c, protection_service.h, protection_service.c, fan_control_service.h, fan_control_service.c, config_service.h, config_service.c, pid_controller.h, pid_controller.c 等服务层模块的头文件和源文件,代码结构类似,实现各自的功能。 * (此处省略代码,实际项目中需要根据具体需求实现) *

(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
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
152
153
154
155
156
157
#include "bsp.h"
#include "measurement_service.h"
#include "control_service.h"
#include "display_service.h"
#include "comm_service.h"
#include "protection_service.h"
#include "fan_control_service.h"
#include "config_service.h"
#include "hal_timer.h"
#include "hal_gpio.h"

// 系统状态枚举
typedef enum {
STATE_IDLE,
STATE_CC_MODE,
STATE_CV_MODE,
STATE_CP_MODE,
STATE_MENU,
STATE_ERROR
} SystemStateTypeDef;

// 当前系统状态
static SystemStateTypeDef currentSystemState = STATE_IDLE;

// 按键事件处理函数 (示例)
void Button_EventHandler(uint8_t buttonId);

// 定时器中断回调函数 (示例)
void Timer_InterruptHandler(void);

int main() {
// 初始化 BSP
BSP_Init();

// 初始化各个服务模块
MeasurementService_Init();
ControlService_Init();
DisplayService_Init();
CommService_Init();
ProtectionService_Init();
FanControlService_Init();
ConfigService_Init();

// 初始化定时器,用于控制循环和显示刷新 (示例)
HAL_Timer_ConfigTypeDef timerConfig = {
.period = 10, // 示例:定时周期 10ms
.callback = Timer_InterruptHandler
};
HAL_Timer_Init(&timerConfig);
HAL_Timer_Start();

// 进入主循环
while (1) {
// 处理按键输入 (示例,实际项目中需要更完善的按键扫描和事件处理)
if (HAL_GPIO_ReadPin(GPIO_PORT_BUTTON, GPIO_PIN_KEY1) == GPIO_PIN_LOW) {
Button_EventHandler(BUTTON_KEY1);
}
if (HAL_GPIO_ReadPin(GPIO_PORT_BUTTON, GPIO_PIN_KEY2) == GPIO_PIN_LOW) {
Button_EventHandler(BUTTON_KEY2);
}
// ... 其他按键处理 ...

// 处理串口命令 (示例)
CommService_ProcessCommand();

// 状态机逻辑 (示例)
switch (currentSystemState) {
case STATE_IDLE:
// 显示待机界面
DisplayService_ShowIdleScreen();
break;
case STATE_CC_MODE:
// 显示恒流模式界面
DisplayService_ShowCCModeScreen();
break;
case STATE_CV_MODE:
// 显示恒压模式界面
DisplayService_ShowCVModeScreen();
break;
case STATE_CP_MODE:
// 显示恒功率模式界面
DisplayService_ShowCPModeScreen();
break;
case STATE_MENU:
// 显示菜单界面
DisplayService_ShowMenuScreen();
break;
case STATE_ERROR:
// 显示错误界面
DisplayService_ShowErrorScreen();
break;
default:
currentSystemState = STATE_IDLE;
break;
}

// 其他应用层逻辑 ...

// 延时 (可选,降低 CPU 占用率)
// HAL_Delay(1);
}
}

// 按键事件处理函数 (示例)
void Button_EventHandler(uint8_t buttonId) {
switch (buttonId) {
case BUTTON_KEY1: // 假设 KEY1 用于切换模式
if (currentSystemState == STATE_IDLE) {
currentSystemState = STATE_CC_MODE; // 进入恒流模式
ControlService_SetMode(CONTROL_MODE_CC);
DisplayService_ShowMessage("CC Mode");
} else if (currentSystemState == STATE_CC_MODE) {
currentSystemState = STATE_CV_MODE; // 切换到恒压模式
ControlService_SetMode(CONTROL_MODE_CV);
DisplayService_ShowMessage("CV Mode");
} else if (currentSystemState == STATE_CV_MODE) {
currentSystemState = STATE_CP_MODE; // 切换到恒功率模式
ControlService_SetMode(CONTROL_MODE_CP);
DisplayService_ShowMessage("CP Mode");
} else if (currentSystemState == STATE_CP_MODE) {
currentSystemState = STATE_IDLE; // 切换回待机模式
ControlService_SetMode(CONTROL_MODE_OFF);
DisplayService_ShowMessage("Idle Mode");
}
break;
case BUTTON_KEY2: // 假设 KEY2 用于进入菜单
currentSystemState = STATE_MENU;
DisplayService_ShowMessage("Menu");
break;
// ... 其他按键事件处理 ...
}
}

// 定时器中断回调函数 (示例)
void Timer_InterruptHandler(void) {
static uint32_t controlLoopCounter = 0;
static uint32_t displayRefreshCounter = 0;

controlLoopCounter++;
if (controlLoopCounter >= 1) { // 每 10ms 执行控制循环
ControlService_ControlLoop();
controlLoopCounter = 0;
}

displayRefreshCounter++;
if (displayRefreshCounter >= 50) { // 每 500ms 刷新显示
MeasurementDataTypeDef data = MeasurementService_GetData();
DisplayService_UpdateMeasurementData(data);
displayRefreshCounter = 0;
}

// 保护服务周期性检测 (例如过压、过流、过温等)
ProtectionService_CheckProtection();

// 风扇温控 (可选)
FanControlService_TemperatureControl();
}
  • state_machine.h, state_machine.c, button_handler.h, button_handler.c, command_parser.h, command_parser.c, error_handler.h, error_handler.c 等应用层模块的头文件和源文件,代码结构类似,实现各自的功能。 * (此处省略代码,实际项目中需要根据具体需求实现) *

实践验证和维护升级

  • 实践验证
    • 单元测试:对每个模块进行单元测试,验证模块功能的正确性。
    • 集成测试:将各个模块集成在一起进行测试,验证模块之间的协同工作。
    • 系统测试:进行全面的系统测试,包括功能测试、性能测试、稳定性测试、可靠性测试、精度测试、保护功能测试等。
    • **硬件在环测试 (HIL)**:使用硬件在环仿真平台进行测试,模拟实际工作环境,验证系统在各种工况下的性能。
    • 实际负载测试:连接实际负载进行测试,验证电子负载的实际性能和指标。
  • 维护升级
    • 模块化设计:模块化设计使得系统易于维护和升级,可以独立修改和更新某个模块,而不会影响其他模块。
    • 清晰的代码结构和注释:提高代码可读性和可维护性,方便后续维护人员理解和修改代码。
    • 版本控制:使用版本控制工具管理代码,方便代码回溯和版本管理。
    • 预留升级接口:预留软件升级接口 (例如 UART 升级、OTA 升级),方便后续功能升级和固件更新。
    • 日志记录和错误诊断:添加日志记录功能,方便记录系统运行状态和错误信息,用于故障诊断和问题排查。

总结

以上代码示例提供了一个基于分层架构的嵌入式软件框架,用于 P150C Pro-D 系列直流恒流型数控电子负载的开发。实际项目中,需要根据具体硬件平台、功能需求和性能指标,进一步完善各个模块的代码实现,并进行充分的测试和验证。通过模块化设计、分层架构、状态机、中断驱动、PID 控制等技术和方法,可以构建一个可靠、高效、可扩展的嵌入式系统平台,满足数控电子负载的应用需求。

请注意,以上代码仅为示例框架,实际项目代码量会远超 3000 行,需要根据具体需求进行详细设计和实现。例如,更完善的 HAL 驱动、更复杂的 UI 界面、更精细的 PID 参数调优、更全面的保护功能、更丰富的通信协议、更详细的错误处理机制等都会增加代码量。

希望以上详细的架构设计和代码示例能够帮助您理解嵌入式系统开发流程和代码架构设计。

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