编程技术分享

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

0%

简介:支持PD、QC等常见协议输入,支持DC5-20V输入,1-24V、0-5A可调数控稳压电源,并附带三组常用固定电压输出和5V的1C1A

好的,作为一名高级嵌入式软件开发工程师,我将为您详细阐述这款数控稳压电源嵌入式系统的代码设计架构,并提供具体的C代码示例。我们将从需求分析入手,逐步深入到系统实现、测试验证以及维护升级,确保构建一个可靠、高效且可扩展的系统平台。
关注微信公众号,提前获取相关推文

项目需求分析

首先,我们需要对这款数控稳压电源的功能需求进行深入分析,以便确定软件架构和模块划分。根据您的描述和图片,核心需求包括:

  1. 输入支持:

    • 支持PD (Power Delivery) 协议输入。
    • 支持QC (Quick Charge) 协议输入。
    • 支持DC 5-20V 宽范围直流输入。
  2. 输出特性:

    • 1-24V 可调输出电压范围。
    • 0-5A 可调输出电流范围。
    • 数控精确调节电压和电流。
    • 三组常用固定电压输出(例如,3.3V, 5V, 12V 可自定义)。
    • 一个 5V 1C1A USB 输出端口(支持标准 USB 充电协议)。
  3. 用户界面:

    • 彩色 LCD 显示屏,实时显示:
      • 输出电压和电流值。
      • 输入电压值。
      • 功率值 (W)。
      • 电量 (Wh)。
      • 工作状态(例如,恒压 CV, 恒流 CC, PD/QC 协议状态等)。
      • 系统设置菜单。
    • 旋转编码器或按键等用户输入设备,用于参数调节和菜单操作。
  4. 保护功能:

    • 过压保护 (OVP)。
    • 过流保护 (OCP)。
    • 过温保护 (OTP)。
    • 短路保护 (SCP)。
    • 输入欠压保护 (UVP)。
  5. 系统特性:

    • 高效的电源转换效率。
    • 稳定的输出性能。
    • 可扩展性,方便后续功能升级和维护。
    • 可靠性,保证系统长期稳定运行。

代码设计架构:分层模块化架构

为了构建一个可靠、高效、可扩展的嵌入式系统,我们采用分层模块化架构。这种架构将系统划分为若干个独立的模块,每个模块负责特定的功能,模块之间通过清晰定义的接口进行交互。分层架构能够有效降低系统复杂度,提高代码的可维护性和可重用性。

我们的系统架构可以分为以下几个主要层次和模块:

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

    • 功能: 直接与硬件交互,提供统一的硬件访问接口,屏蔽底层硬件差异。
    • 模块:
      • GPIO 驱动: 控制 GPIO 引脚,用于 LED 指示、按键输入、输出使能等。
      • ADC 驱动: 模数转换器驱动,用于电压、电流、温度等模拟信号的采集。
      • DAC 驱动: 数模转换器驱动,用于输出控制电压或电流(如果需要模拟控制)。
      • PWM 驱动: 脉冲宽度调制驱动,用于控制 Buck-Boost 电路的开关管。
      • Timer 驱动: 定时器驱动,用于 PWM 生成、定时中断、系统时钟等。
      • UART/SPI/I2C 驱动: 串口、SPI、I2C 通信驱动,用于与外部设备(如 LCD、传感器、协议芯片)通信。
      • Flash 驱动: Flash 存储器驱动,用于存储系统配置、校准数据、固件升级等。
      • USB 驱动 (Device/Host): USB 设备或主机驱动,用于 PD/QC 协议通信、USB 充电输出等。
      • Encoder 驱动: 旋转编码器驱动,用于用户输入。
    • 优势: 提高代码的可移植性,当更换硬件平台时,只需修改 HAL 层代码,上层应用代码无需改动。
  2. 协议层 (Protocol Layer):

    • 功能: 处理各种输入协议,包括 PD 和 QC 协议,以及 USB 充电协议。
    • 模块:
      • PD 协议模块: 实现 USB Power Delivery 协议的解析、协商和控制。
      • QC 协议模块: 实现 Qualcomm Quick Charge 协议的解析、协商和控制。
      • USB Charging 协议模块: 实现 USB BC1.2 等充电协议,用于 5V 1C1A 输出。
    • 优势: 将复杂的协议处理逻辑封装起来,上层应用只需调用协议层提供的接口,即可获取协议解析结果和控制信息。
  3. 电源管理层 (Power Management Layer):

    • 功能: 核心的电源控制逻辑,包括电压电流调节、输出管理、保护功能实现等。
    • 模块:
      • Buck-Boost 控制模块: 实现 Buck-Boost 电路的 PWM 控制,进行电压和电流调节。
      • PID 控制模块: 实现 PID (比例-积分-微分) 控制算法,精确控制输出电压和电流。
      • 输出管理模块: 管理可调输出、固定电压输出和 USB 输出,包括使能、禁用、参数设置等。
      • 保护模块: 实现过压、过流、过温、短路、欠压等保护功能,及时检测并采取保护措施。
      • 功率计算模块: 计算输出功率、电量等参数。
    • 优势: 将电源控制逻辑集中管理,方便参数调整和算法优化,提高系统性能和稳定性。
  4. 用户界面层 (UI Layer):

    • 功能: 负责用户交互,包括显示信息、处理用户输入、提供设置菜单等。
    • 模块:
      • LCD 驱动模块: 驱动 LCD 显示屏,实现文本、数字、图形显示。
      • 显示管理模块: 管理显示内容,包括实时数据、状态信息、菜单界面等。
      • 输入处理模块: 处理旋转编码器或按键输入,解析用户操作。
      • 菜单系统模块: 实现菜单导航、参数设置、系统配置等功能。
    • 优势: 提供友好的用户交互界面,方便用户操作和监控电源状态。
  5. 应用层 (Application Layer):

    • 功能: 系统的主程序,负责初始化各个模块,协调各模块工作,实现整体系统功能。
    • 模块:
      • 系统初始化模块: 初始化 HAL、协议层、电源管理层、UI 层等模块。
      • 主循环模块: 循环执行系统任务,例如:
        • 读取用户输入。
        • 处理协议事件。
        • 控制电源输出。
        • 更新显示信息。
        • 检测保护状态。
      • 配置管理模块: 加载和保存系统配置参数(例如,固定电压值、用户设置)。
      • 固件升级模块 (可选): 实现固件在线升级功能。
    • 优势: 作为系统的顶层,协调各模块协同工作,实现完整的系统功能。

C 代码实现示例 (框架及关键模块)

为了展示代码架构,我们提供一些关键模块的 C 代码框架和示例代码片段。由于篇幅限制,无法提供完整的 3000 行代码,但您可以根据这些示例代码框架进行扩展和完善。

1. 硬件抽象层 (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
#ifndef __GPIO_H__
#define __GPIO_H__

typedef enum {
GPIO_PIN_0,
GPIO_PIN_1,
// ... more pins
GPIO_PIN_MAX
} GPIO_PinTypeDef;

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT
} GPIO_ModeTypeDef;

typedef enum {
GPIO_STATE_RESET,
GPIO_STATE_SET
} GPIO_StateTypeDef;

void HAL_GPIO_Init(GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode);
void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, GPIO_StateTypeDef state);
GPIO_StateTypeDef HAL_GPIO_ReadPin(GPIO_PinTypeDef pin);

#endif // __GPIO_H__

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
#include "gpio.h"
// ... 包含硬件平台相关的头文件,例如寄存器定义 ...

void HAL_GPIO_Init(GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode) {
// ... 根据 pin 和 mode 配置 GPIO 寄存器 ...
if (mode == GPIO_MODE_OUTPUT) {
// 设置为输出模式
} else {
// 设置为输入模式
}
}

void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, GPIO_StateTypeDef state) {
// ... 根据 pin 和 state 设置 GPIO 输出电平 ...
if (state == GPIO_STATE_SET) {
// 输出高电平
} else {
// 输出低电平
}
}

GPIO_StateTypeDef HAL_GPIO_ReadPin(GPIO_PinTypeDef pin) {
// ... 读取 GPIO 输入电平 ...
// ... 返回 GPIO_STATE_SET 或 GPIO_STATE_RESET ...
return GPIO_STATE_RESET; // 示例
}

adc.h

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

typedef enum {
ADC_CHANNEL_VOLTAGE_IN,
ADC_CHANNEL_CURRENT_OUT,
ADC_CHANNEL_TEMPERATURE,
// ... more channels
ADC_CHANNEL_MAX
} ADC_ChannelTypeDef;

void HAL_ADC_Init(ADC_ChannelTypeDef channel);
uint16_t HAL_ADC_GetValue(ADC_ChannelTypeDef channel); // 返回 12 位 ADC 值

#endif // __ADC_H__

adc.c (针对具体硬件平台实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "adc.h"
// ... 包含硬件平台相关的 ADC 寄存器定义 ...

void HAL_ADC_Init(ADC_ChannelTypeDef channel) {
// ... 初始化 ADC 模块,配置通道、采样率等 ...
// ... 使能 ADC 时钟 ...
// ... 配置 ADC 寄存器 ...
}

uint16_t HAL_ADC_GetValue(ADC_ChannelTypeDef channel) {
// ... 选择 ADC 通道 ...
// ... 启动 ADC 转换 ...
// ... 等待转换完成 ...
// ... 读取 ADC 数据寄存器 ...
return 0; // 示例返回值
}

类似地,您可以创建 dac.h, pwm.h, timer.h, uart.h, spi.h, i2c.h, flash.h, usb.h, encoder.h 等头文件和对应的 .c 文件,实现 HAL 层驱动。

2. 协议层 (Protocol Layer)

protocol_pd.h

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

typedef enum {
PD_STATE_IDLE,
PD_STATE_NEGOTIATING,
PD_STATE_POWER_DELIVERED,
PD_STATE_ERROR
} PD_StateTypeDef;

typedef struct {
uint16_t voltage_mv; // 电压,单位 mV
uint16_t current_ma; // 电流,单位 mA
} PD_PowerRequestTypeDef;

PD_StateTypeDef PD_Init();
PD_StateTypeDef PD_Process(); // 处理 PD 协议事件,例如接收数据
PD_PowerRequestTypeDef PD_GetPowerRequest(); // 获取 PD 协商的电源请求

#endif // __PROTOCOL_PD_H__

protocol_pd.c (简化的协议处理示例 - 实际 PD 协议非常复杂)

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
#include "protocol_pd.h"
#include "usb.h" // 假设 USB 驱动在 usb.h 中

PD_StateTypeDef pd_state = PD_STATE_IDLE;
PD_PowerRequestTypeDef pd_power_request = {0, 0};

PD_StateTypeDef PD_Init() {
// ... 初始化 PD 协议相关硬件,例如 USB PHY ...
pd_state = PD_STATE_IDLE;
return pd_state;
}

PD_StateTypeDef PD_Process() {
// ... 接收 USB 数据 ...
// ... 解析 PD 消息 ...
// ... 根据 PD 协议状态机进行状态转换 ...

if (pd_state == PD_STATE_IDLE) {
// ... 检测到 PD 设备连接 ...
pd_state = PD_STATE_NEGOTIATING;
// ... 发送 PD Capability Request ...
} else if (pd_state == PD_STATE_NEGOTIATING) {
// ... 接收 PD Capability Response ...
// ... 解析支持的电压和电流 ...
// ... 选择合适的电压和电流 ...
pd_power_request.voltage_mv = 12000; // 示例:请求 12V
pd_power_request.current_ma = 3000; // 示例:请求 3A
pd_state = PD_STATE_POWER_DELIVERED;
// ... 发送 Power Request 消息 ...
} else if (pd_state == PD_STATE_POWER_DELIVERED) {
// ... 接收 ACK 消息 ...
// ... PD 供电成功 ...
}

return pd_state;
}

PD_PowerRequestTypeDef PD_GetPowerRequest() {
return pd_power_request;
}

类似地,您可以创建 protocol_qc.h, protocol_qc.c, protocol_usb_charging.h, protocol_usb_charging.c 等文件,实现 QC 和 USB 充电协议处理。

3. 电源管理层 (Power Management Layer)

regulator.h

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

typedef enum {
REGULATOR_MODE_CV, // 恒压模式
REGULATOR_MODE_CC // 恒流模式
} RegulatorModeTypeDef;

void Regulator_Init();
void Regulator_SetVoltage(float voltage); // 设置输出电压,单位 V
void Regulator_SetCurrent(float current); // 设置输出电流,单位 A
void Regulator_EnableOutput();
void Regulator_DisableOutput();
RegulatorModeTypeDef Regulator_GetMode();
float Regulator_GetOutputVoltage(); // 获取实际输出电压
float Regulator_GetOutputCurrent(); // 获取实际输出电流

#endif // __REGULATOR_H__

regulator.c (简化的 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "regulator.h"
#include "pwm.h"
#include "adc.h"
#include "timer.h"

#define PWM_FREQUENCY 100000 // 100kHz PWM 频率
#define PID_SAMPLE_TIME 0.001 // 1ms PID 采样时间

float target_voltage = 5.0f; // 目标电压
float target_current = 1.0f; // 目标电流
RegulatorModeTypeDef current_mode = REGULATOR_MODE_CV;

float kp = 0.1f; // 比例系数
float ki = 0.01f; // 积分系数
float kd = 0.001f;// 微分系数

float integral_error = 0.0f;
float last_error = 0.0f;

void Regulator_Init() {
HAL_PWM_Init(PWM_FREQUENCY);
HAL_Timer_Init(PID_SAMPLE_TIME);
HAL_Timer_Start(); // 启动 PID 定时器
// ... 其他初始化 ...
}

void Regulator_SetVoltage(float voltage) {
target_voltage = voltage;
current_mode = REGULATOR_MODE_CV;
}

void Regulator_SetCurrent(float current) {
target_current = current;
current_mode = REGULATOR_MODE_CC;
}

void Regulator_EnableOutput() {
// ... 使能 Buck-Boost 电路输出 ...
}

void Regulator_DisableOutput() {
// ... 禁用 Buck-Boost 电路输出 ...
}

RegulatorModeTypeDef Regulator_GetMode() {
return current_mode;
}

float Regulator_GetOutputVoltage() {
return (float)HAL_ADC_GetValue(ADC_CHANNEL_VOLTAGE_OUT) * VOLTAGE_SCALE_FACTOR; // 假设电压转换系数
}

float Regulator_GetOutputCurrent() {
return (float)HAL_ADC_GetValue(ADC_CHANNEL_CURRENT_OUT) * CURRENT_SCALE_FACTOR; // 假设电流转换系数
}

// PID 控制定时器中断处理函数 (假设每 1ms 调用一次)
void PID_Control_Handler() {
float current_voltage = Regulator_GetOutputVoltage();
float current_current = Regulator_GetOutputCurrent();
float error;

if (current_mode == REGULATOR_MODE_CV) {
error = target_voltage - current_voltage;
} else {
error = target_current - current_current;
}

integral_error += error * PID_SAMPLE_TIME;
float derivative_error = (error - last_error) / PID_SAMPLE_TIME;
last_error = error;

float pwm_duty_cycle = kp * error + ki * integral_error + kd * derivative_error;

// 限制 PWM 占空比范围,例如 0-100%
if (pwm_duty_cycle < 0) pwm_duty_cycle = 0;
if (pwm_duty_cycle > 100) pwm_duty_cycle = 100;

HAL_PWM_SetDutyCycle(pwm_duty_cycle); // 设置 PWM 占空比
}

// ... 需要在 Timer 驱动中配置 PID_Control_Handler 为定时器中断回调函数 ...

您需要根据实际的 Buck-Boost 电路拓扑、PWM 控制方式、PID 参数整定等进行详细设计和调整 regulator.c 代码。

4. 用户界面层 (UI Layer)

display.h

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

void Display_Init();
void Display_ClearScreen();
void Display_SetCursor(uint8_t x, uint8_t y);
void Display_WriteString(const char *str);
void Display_WriteNumber(float number, uint8_t decimal_places);
void Display_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
// ... 其他显示函数 ...

#endif // __DISPLAY_H__

display.c (针对具体 LCD 驱动芯片实现)

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 "display.h"
#include "spi.h" // 假设 LCD 通过 SPI 通信

void Display_Init() {
// ... 初始化 LCD 控制器,例如配置 SPI, 初始化序列 ...
Display_ClearScreen();
}

void Display_ClearScreen() {
// ... 发送清屏指令 ...
}

void Display_SetCursor(uint8_t x, uint8_t y) {
// ... 设置光标位置 ...
}

void Display_WriteString(const char *str) {
// ... 逐个字符发送到 LCD 驱动 ...
}

void Display_WriteNumber(float number, uint8_t decimal_places) {
// ... 将浮点数转换为字符串,并调用 Display_WriteString 显示 ...
}

void Display_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
// ... 绘制直线 ...
}

5. 应用层 (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
#include "hal.h"      // HAL 层头文件集合
#include "protocol.h" // 协议层头文件集合
#include "regulator.h"
#include "display.h"
#include "ui.h"
#include "config.h"
#include "fault_protection.h"

int main() {
// 系统初始化
HAL_Init(); // 初始化 HAL 层
Protocol_Init(); // 初始化协议层
Regulator_Init(); // 初始化电源调节器
Display_Init(); // 初始化显示屏
UI_Init(); // 初始化用户界面
Config_Load(); // 加载配置参数
FaultProtection_Init(); // 初始化保护模块

Display_WriteString("System Booting...");
delay_ms(1000); // 延时 1 秒

while (1) {
UI_ProcessInput(); // 处理用户输入
Protocol_Process(); // 处理协议事件
Regulator_Control(); // 电源调节控制 (PID 控制在定时器中断中)
Display_Update(); // 更新显示信息
FaultProtection_Check(); // 检测保护状态

// ... 其他系统任务 ...
}

return 0;
}

ui.h, ui.c, config.h, config.c, fault_protection.h, fault_protection.c 等文件可以根据您的具体需求进行设计和实现,包括菜单系统、参数设置、配置加载/保存、保护功能逻辑等。

项目中采用的技术和方法

  • 分层模块化架构: 提高代码可维护性、可重用性和可移植性。
  • 硬件抽象层 (HAL): 屏蔽硬件差异,简化上层应用开发。
  • 状态机: 用于协议处理、UI 逻辑等,清晰描述系统状态和状态转换。
  • PID 控制算法: 实现精确的电压和电流调节。
  • 定时器中断: 用于 PID 控制采样、周期性任务执行等。
  • 事件驱动编程: 例如协议事件处理、用户输入事件处理。
  • 错误处理和异常处理: 完善的错误处理机制,提高系统鲁棒性。
  • 代码注释和文档: 清晰的代码注释和文档,方便代码理解和维护。
  • 版本控制 (Git): 使用版本控制工具管理代码,方便团队协作和版本管理。
  • 单元测试和集成测试: 进行充分的测试,保证系统功能和稳定性。

实践验证

在实际项目开发中,上述架构和技术方法都经过了广泛的实践验证,能够有效地构建可靠、高效、可扩展的嵌入式系统。

  • 分层架构: 在各种规模的嵌入式项目中都得到了应用,证明其有效性。
  • HAL 层: 是跨平台嵌入式开发的基础,例如 FreeRTOS, Linux 等操作系统都采用了 HAL 概念。
  • PID 控制: 是工业控制领域最常用的控制算法之一,在电源控制、电机控制等领域有广泛应用。
  • 状态机: 是嵌入式系统设计中常用的建模方法,尤其适用于协议和 UI 逻辑。
  • 测试驱动开发 (TDD) 和持续集成 (CI): 现代软件开发流程中不可或缺的部分,能够提高软件质量和开发效率。

维护升级

  • 模块化设计: 方便功能升级和模块替换,例如升级协议模块、优化 PID 算法等。
  • 清晰的接口: 模块之间通过接口交互,修改模块内部实现不会影响其他模块。
  • 固件升级功能: 通过 USB 或其他方式实现固件在线升级,方便修复 bug 和添加新功能。
  • 日志记录和远程调试: 方便问题定位和远程维护。

总结

这款数控稳压电源嵌入式系统采用分层模块化架构,结合 HAL、协议层、电源管理层、UI 层和应用层,能够有效地实现各项功能需求。代码示例展示了关键模块的框架和基本实现思路,您可以根据实际硬件平台和具体需求进行详细设计和代码编写。在开发过程中,请注重代码质量、测试验证和文档编写,确保构建一个可靠、高效、可扩展的嵌入式系统平台。

希望以上详细的架构说明和代码示例能够帮助您理解和开发这款数控稳压电源嵌入式系统。如果您有任何进一步的问题,请随时提出。

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