编程技术分享

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

0%

简介:12V输入,0~28v,0~10A,220w开关电源,使用服务器电源输入或者电脑电源。

当然,作为一名高级嵌入式软件开发工程师,我非常乐意为您详细阐述这个嵌入式开关电源项目的设计架构和C代码实现,并确保内容详尽、实践性强,总字数超过3000字。
关注微信公众号,提前获取相关推文

项目概述:高性能可调开关电源

本项目旨在开发一款高性能、高可靠性的可调开关电源,输入电压为12V,输出电压范围为028V,输出电流范围为010A,最大输出功率为220W。该电源可以采用服务器电源或电脑电源作为输入源,具有恒压(CV)和恒流(CC)两种工作模式,并配备用户友好的操作界面和完善的保护功能。

系统设计架构

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

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

    • 作用:提供统一的硬件访问接口,屏蔽底层硬件差异,使上层软件能够独立于具体的硬件平台。
    • 模块:GPIO驱动、ADC驱动、DAC/PWM驱动、定时器驱动、显示屏驱动、按键/编码器驱动、通信接口驱动(如UART、I2C、SPI)等。
  2. **驱动层 (Driver Layer)**:

    • 作用:实现HAL层定义的硬件接口,直接操作底层硬件寄存器,完成具体的硬件功能。
    • 模块:对应于HAL层的模块,例如GPIO驱动程序、ADC驱动程序、DAC/PWM驱动程序、定时器驱动程序、显示屏驱动程序、按键/编码器驱动程序、通信接口驱动程序等。
  3. **控制层 (Control Layer)**:

    • 作用:实现电源的核心控制逻辑,包括电压和电流的闭环控制、模式切换、保护功能、参数配置等。
    • 模块:
      • **电源控制模块 (Power Control Module)**:实现CV/CC模式切换、输出电压/电流设定、PWM控制信号生成、闭环控制算法(PID等)、软启动、输出使能控制等。
      • **保护模块 (Protection Module)**:实现过压保护(OVP)、过流保护(OCP)、过温保护(OTP)、短路保护(SCP)、输入欠压保护(UVP)等。
      • **参数配置模块 (Parameter Configuration Module)**:负责存储和加载电源的配置参数,如电压电流设定值、保护阈值、校准参数等。
  4. **应用层 (Application Layer)**:

    • 作用:提供用户界面交互、系统状态监控、参数显示和设置等功能,实现用户与电源系统的交互。
    • 模块:
      • **用户界面模块 (User Interface Module)**:负责显示电源的电压、电流、功率等信息,处理按键/编码器输入,实现菜单导航和参数设置。
      • **状态监控模块 (Status Monitoring Module)**:实时监控电源的电压、电流、温度等状态,并将状态信息显示在用户界面上,同时触发保护机制。
      • **通信模块 (Communication Module)**:实现与上位机或其他设备的通信,用于远程监控、参数配置、固件升级等(可选)。
  5. **系统层 (System Layer)**:

    • 作用:负责系统的初始化、任务调度、资源管理、错误处理等系统级功能。
    • 模块:
      • **初始化模块 (Initialization Module)**:完成系统启动时的硬件初始化、模块初始化、参数加载等。
      • **任务调度模块 (Task Scheduling Module)**:管理系统中的各个任务,例如控制环任务、UI刷新任务、状态监控任务等(可以使用RTOS或简单的轮询方式)。
      • **错误处理模块 (Error Handling Module)**:处理系统运行过程中发生的错误,例如硬件错误、参数错误、保护动作等,并进行相应的错误处理和日志记录。

代码实现 (C语言)

以下是用C语言实现的各个模块的详细代码,代码中包含详细的注释,并考虑了代码的可读性、可维护性和可扩展性。为了满足3000行代码的要求,我会尽可能详细地展开各个模块的实现细节,并加入一些常用的设计模式和技巧。

1. 硬件抽象层 (HAL)

hal.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
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
#ifndef HAL_H
#define HAL_H

#include <stdint.h>
#include <stdbool.h>

// GPIO 定义
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_8,
GPIO_PIN_9,
GPIO_PIN_10,
GPIO_PIN_11,
GPIO_PIN_12,
GPIO_PIN_13,
GPIO_PIN_14,
GPIO_PIN_15,
// ... 可以根据具体MCU扩展
GPIO_PIN_MAX
} GPIO_PinTypeDef;

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

typedef enum {
GPIO_OUTPUT_PP, // Push-Pull
GPIO_OUTPUT_OD // Open-Drain
} 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 outputType, GPIO_PullTypeDef pull);
void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, bool pinState);
bool HAL_GPIO_ReadPin(GPIO_PinTypeDef pin);

// ADC 定义
typedef enum {
ADC_CHANNEL_0,
ADC_CHANNEL_1,
ADC_CHANNEL_2,
// ... 可以根据具体MCU扩展
ADC_CHANNEL_MAX
} ADC_ChannelTypeDef;

typedef enum {
ADC_RESOLUTION_8BIT,
ADC_RESOLUTION_10BIT,
ADC_RESOLUTION_12BIT
} ADC_ResolutionTypeDef;

// ADC 函数声明
void HAL_ADC_Init(ADC_ChannelTypeDef channel, ADC_ResolutionTypeDef resolution);
uint16_t HAL_ADC_Read(ADC_ChannelTypeDef channel);

// PWM 定义
typedef enum {
PWM_CHANNEL_0,
PWM_CHANNEL_1,
PWM_CHANNEL_2,
// ... 可以根据具体MCU扩展
PWM_CHANNEL_MAX
} PWM_ChannelTypeDef;

// PWM 函数声明
void HAL_PWM_Init(PWM_ChannelTypeDef channel, uint32_t frequency);
void HAL_PWM_SetDutyCycle(PWM_ChannelTypeDef channel, float dutyCycle); // Duty cycle 0.0 - 1.0

// 定时器 定义 (简单示例,可以根据需求扩展)
typedef enum {
TIMER_ID_0,
TIMER_ID_1,
TIMER_ID_MAX
} Timer_IDTypeDef;

// 定时器 函数声明
void HAL_Timer_Init(Timer_IDTypeDef timerId, uint32_t period_ms);
void HAL_Timer_Start(Timer_IDTypeDef timerId);
void HAL_Timer_Stop(Timer_IDTypeDef timerId);
void HAL_Timer_RegisterCallback(Timer_IDTypeDef timerId, void (*callback)(void)); // 中断回调函数注册

// UART 定义 (简单示例)
typedef enum {
UART_ID_0,
UART_ID_1,
UART_ID_MAX
} UART_IDTypeDef;

typedef enum {
UART_BAUDRATE_9600,
UART_BAUDRATE_115200,
// ...
} UART_BaudRateTypeDef;

// UART 函数声明
void HAL_UART_Init(UART_IDTypeDef uartId, UART_BaudRateTypeDef baudRate);
void HAL_UART_Transmit(UART_IDTypeDef uartId, uint8_t *data, uint32_t size);
void HAL_UART_Receive(UART_IDTypeDef uartId, uint8_t *data, uint32_t size);
void HAL_UART_RegisterReceiveCallback(UART_IDTypeDef uartId, void (*callback)(uint8_t data)); // 接收回调函数注册

// LCD 接口 (假设使用SPI接口的LCD)
void HAL_LCD_Init(void);
void HAL_LCD_WriteString(const char *str);
void HAL_LCD_Clear(void);
void HAL_LCD_SetCursor(uint8_t row, uint8_t col);
void HAL_LCD_WriteChar(char c);

// 编码器 接口 (假设使用GPIO中断)
void HAL_Encoder_Init(void);
int32_t HAL_Encoder_ReadCount(void);
void HAL_Encoder_ResetCount(void);
void HAL_Encoder_RegisterCallback(void (*callback)(int32_t increment)); // 编码器增量回调

// 按键 接口 (假设使用GPIO)
void HAL_Button_Init(GPIO_PinTypeDef buttonPin);
bool HAL_Button_IsPressed(GPIO_PinTypeDef buttonPin);

#endif // HAL_H

hal_stm32f4xx.c (假设使用 STM32F4xx 系列 MCU,需要根据实际MCU修改)

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
#include "hal.h"
#include "stm32f4xx.h" // 包含具体的 MCU 头文件

// --- GPIO 驱动实现 ---
void HAL_GPIO_Init(GPIO_PinTypeDef pin, GPIO_ModeTypeDef mode, GPIO_OutputTypeTypeDef outputType, GPIO_PullTypeDef pull) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;

// 根据 GPIO_PinTypeDef 获取 GPIOx 和 GPIO_Pin (需要根据实际 MCU 的 GPIO 映射关系实现)
// ... (此处省略 GPIO 端口和引脚映射的实现,需要根据具体的 MCU 手册)
// 示例,假设 GPIO_PIN_0 对应 GPIOA Pin 0
if (pin == GPIO_PIN_0) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_0; }
else if (pin == GPIO_PIN_1) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_1; }
// ... 其他引脚映射

// 使能 GPIO 时钟 (需要根据实际 MCU 的 RCC 配置实现)
// ... (此处省略 RCC 时钟使能的实现,需要根据具体的 MCU 手册)
// 示例,假设 GPIOA 时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin;

if (mode == GPIO_MODE_INPUT) {
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
} else if (mode == GPIO_MODE_OUTPUT) {
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
if (outputType == GPIO_OUTPUT_PP) {
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
} else if (outputType == GPIO_OUTPUT_OD) {
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
}
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 可根据需求调整速度
} else if (mode == GPIO_MODE_AF) {
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
// ... 配置 AF 功能 (需要根据实际 MCU 的 AF 功能映射关系实现)
}

if (pull == GPIO_PULL_NONE) {
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
} else if (pull == GPIO_PULL_UP) {
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
} else if (pull == GPIO_PULL_DOWN) {
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
}

GPIO_Init(GPIOx, &GPIO_InitStruct);
}

void HAL_GPIO_WritePin(GPIO_PinTypeDef pin, bool pinState) {
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;
// 获取 GPIOx 和 GPIO_Pin (同 HAL_GPIO_Init)
if (pin == GPIO_PIN_0) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_0; }
else if (pin == GPIO_PIN_1) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_1; }

if (pinState) {
GPIO_SetBits(GPIOx, GPIO_Pin);
} else {
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
}

bool HAL_GPIO_ReadPin(GPIO_PinTypeDef pin) {
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;
// 获取 GPIOx 和 GPIO_Pin (同 HAL_GPIO_Init)
if (pin == GPIO_PIN_0) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_0; }
else if (pin == GPIO_PIN_1) { GPIOx = GPIOA; GPIO_Pin = GPIO_PIN_1; }

return GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == Bit_SET;
}

// --- ADC 驱动实现 ---
void HAL_ADC_Init(ADC_ChannelTypeDef channel, ADC_ResolutionTypeDef resolution) {
ADC_InitTypeDef ADC_InitStruct;
ADC_CommonInitTypeDef ADC_CommonInitStruct;

// 使能 ADC 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 假设使用 ADC1

// ADC 通用配置
ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2; // 预分频器
ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStruct);

// ADC 初始化配置
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; // 默认 12 位,可根据 resolution 参数调整
if (resolution == ADC_RESOLUTION_8BIT) ADC_InitStruct.ADC_Resolution = ADC_Resolution_8b;
else if (resolution == ADC_RESOLUTION_10BIT) ADC_InitStruct.ADC_Resolution = ADC_Resolution_10b;
else if (resolution == ADC_RESOLUTION_12BIT) ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;

ADC_InitStruct.ADC_ScanConvMode = DISABLE; // 单通道模式
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // 软件触发
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStruct); // 假设使用 ADC1

// 配置 ADC 通道 (需要根据 ADC_ChannelTypeDef 映射到实际的 ADC 通道)
// ... (此处省略 ADC 通道映射的实现,需要根据具体的 MCU 手册)
// 示例,假设 ADC_CHANNEL_0 对应 ADC1_IN0 (GPIOA Pin 0)
if (channel == ADC_CHANNEL_0) {
// 配置 GPIOA Pin 0 为模拟输入
HAL_GPIO_Init(GPIO_PIN_0, GPIO_MODE_INPUT, GPIO_OUTPUT_PP, GPIO_PULL_NONE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);
}
// ... 其他通道配置

// 使能 ADC
ADC_Cmd(ADC1, ENABLE);

// 启动 ADC 转换
ADC_SoftwareStartConv(ADC1);
}

uint16_t HAL_ADC_Read(ADC_ChannelTypeDef channel) {
// 等待转换完成
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
// 获取 ADC 值
return ADC_GetConversionValue(ADC1);
}

// --- PWM 驱动实现 ---
void HAL_PWM_Init(PWM_ChannelTypeDef channel, uint32_t frequency) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TypeDef *TIMx;
uint16_t TIM_Channel;
uint32_t GPIO_AF_TIMx;
GPIO_TypeDef *GPIOx_PWM;
uint16_t GPIO_Pin_PWM;

// 根据 PWM_ChannelTypeDef 获取 TIMx, TIM_Channel, GPIO_AF_TIMx, GPIOx_PWM, GPIO_Pin_PWM (需要根据实际 MCU 的 TIM 和 GPIO 映射关系实现)
// ... (此处省略 TIM 和 GPIO 映射的实现,需要根据具体的 MCU 手册)
// 示例,假设 PWM_CHANNEL_0 对应 TIM3_CH1 (GPIOA Pin 6)
if (channel == PWM_CHANNEL_0) {
TIMx = TIM3; TIM_Channel = TIM_Channel_1; GPIO_AF_TIMx = GPIO_AF_TIM3; GPIOx_PWM = GPIOA; GPIO_Pin_PWM = GPIO_Pin_6;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能 TIM3 时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能 GPIOA 时钟
}
// ... 其他通道映射

// 配置 PWM 输出引脚 GPIO
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_PWM;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOx_PWM, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOx_PWM, GPIO_PinSource6, GPIO_AF_TIMx); // GPIO 复用功能配置

// 配置 定时器时基单元
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / frequency / 10000) - 1; // 计算预分频值,假设目标 PWM 频率为 frequency,精度 1/10000
TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1; // PWM 周期,决定 PWM 分辨率
TIM_TimeBaseInitStruct.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStruct);

// 配置 PWM 输出模式
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 0; // 初始占空比为 0
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // 高电平有效

if (TIM_Channel == TIM_Channel_1) TIM_OC1Init(TIMx, &TIM_OCInitStruct);
else if (TIM_Channel == TIM_Channel_2) TIM_OC2Init(TIMx, &TIM_OCInitStruct);
// ... 其他通道配置

TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_ENABLE); // 使能预装载寄存器

TIM_ARRPreloadConfig(TIMx, ENABLE); // ARR 预装载使能

TIM_Cmd(TIMx, ENABLE); // 使能 TIMx
}

void HAL_PWM_SetDutyCycle(PWM_ChannelTypeDef channel, float dutyCycle) {
TIM_TypeDef *TIMx;
uint16_t TIM_Channel;
// 获取 TIMx 和 TIM_Channel (同 HAL_PWM_Init)
if (channel == PWM_CHANNEL_0) { TIMx = TIM3; TIM_Channel = TIM_Channel_1; }

if (dutyCycle < 0.0f) dutyCycle = 0.0f;
if (dutyCycle > 1.0f) dutyCycle = 1.0f;

uint16_t pulseValue = (uint16_t)(dutyCycle * 10000); // 假设周期为 10000
if (TIM_Channel == TIM_Channel_1) TIM_SetCompare1(TIMx, pulseValue);
else if (TIM_Channel == TIM_Channel_2) TIM_SetCompare2(TIMx, pulseValue);
// ... 其他通道配置
}

// --- 定时器 驱动实现 ---
void HAL_Timer_Init(Timer_IDTypeDef timerId, uint32_t period_ms) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TypeDef *TIMx;
IRQn_Type TIMx_IRQn;
uint32_t TIMx_RCC_Periph;

// 根据 Timer_IDTypeDef 获取 TIMx, TIMx_IRQn, TIMx_RCC_Periph (需要根据实际 MCU 的 TIM 映射关系实现)
// ... (此处省略 TIM 映射的实现,需要根据具体的 MCU 手册)
// 示例,假设 TIMER_ID_0 对应 TIM2
if (timerId == TIMER_ID_0) { TIMx = TIM2; TIMx_IRQn = TIM2_IRQn; TIMx_RCC_Periph = RCC_APB1Periph_TIM2; }

// 使能 定时器 时钟
RCC_APB1PeriphClockCmd(TIMx_RCC_Periph, ENABLE);

TIM_TimeBaseInitStruct.TIM_Period = period_ms * 1000 - 1; // 周期,单位 us (假设时钟频率为 1MHz)
TIM_TimeBaseInitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1; // 预分频,使计数器时钟为 1MHz
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStruct);

// 使能 定时器 中断
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);

// 配置 NVIC 中断控制器
NVIC_InitStruct.NVIC_IRQChannel = TIMx_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}

void HAL_Timer_Start(Timer_IDTypeDef timerId) {
TIM_TypeDef *TIMx;
// 获取 TIMx (同 HAL_Timer_Init)
if (timerId == TIMER_ID_0) { TIMx = TIM2; }

TIM_Cmd(TIMx, ENABLE);
}

void HAL_Timer_Stop(Timer_IDTypeDef timerId) {
TIM_TypeDef *TIMx;
// 获取 TIMx (同 HAL_Timer_Init)
if (timerId == TIMER_ID_0) { TIMx = TIM2; }

TIM_Cmd(TIMx, DISABLE);
}

// 中断回调函数指针数组,用于存储不同定时器的回调函数
static void (*timer_callbacks[TIMER_ID_MAX])(void) = {NULL};

void HAL_Timer_RegisterCallback(Timer_IDTypeDef timerId, void (*callback)(void)) {
if (timerId < TIMER_ID_MAX) {
timer_callbacks[timerId] = callback;
}
}

// 定时器 中断服务例程 (需要根据实际 MCU 的中断向量表修改)
void TIM2_IRQHandler(void) { // 示例,假设 TIMER_ID_0 对应 TIM2
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if (timer_callbacks[TIMER_ID_0] != NULL) {
timer_callbacks[TIMER_ID_0](); // 调用注册的回调函数
}
}
}

// --- UART 驱动实现 (简单示例) ---
void HAL_UART_Init(UART_IDTypeDef uartId, UART_BaudRateTypeDef baudRate) {
// ... (UART 初始化实现,包括 GPIO 配置、UART 寄存器配置、波特率设置等,类似于 GPIO 和 PWM 的初始化)
// 需要根据实际 MCU 的 UART 模块和 GPIO 映射关系实现
// 省略具体实现,框架类似 GPIO 和 PWM
}

void HAL_UART_Transmit(UART_IDTypeDef uartId, uint8_t *data, uint32_t size) {
// ... (UART 发送数据实现,轮询或 DMA 方式)
// 省略具体实现
}

void HAL_UART_Receive(UART_IDTypeDef uartId, uint8_t *data, uint32_t size) {
// ... (UART 接收数据实现,轮询或 DMA 方式)
// 省略具体实现
}

static void (*uart_receive_callbacks[UART_ID_MAX])(uint8_t data) = {NULL};

void HAL_UART_RegisterReceiveCallback(UART_IDTypeDef uartId, void (*callback)(uint8_t data)) {
if (uartId < UART_ID_MAX) {
uart_receive_callbacks[uartId] = callback;
}
}

// UART 中断服务例程 (需要根据实际 MCU 的中断向量表修改)
void USART1_IRQHandler(void) { // 示例,假设 UART_ID_0 对应 USART1
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t received_data = USART_ReceiveData(USART1);
if (uart_receive_callbacks[UART_ID_0] != NULL) {
uart_receive_callbacks[UART_ID_0](received_data); // 调用注册的回调函数
}
}
}


// --- LCD 驱动实现 (假设 SPI 接口) ---
void HAL_LCD_Init(void) {
// ... (LCD 初始化序列,包括 SPI 初始化、LCD 控制引脚初始化、LCD 初始化命令发送等,需要参考 LCD 驱动芯片手册)
// 省略具体实现,需要根据具体的 LCD 驱动芯片和接口实现
}

void HAL_LCD_WriteString(const char *str) {
// ... (向 LCD 写入字符串,循环调用 HAL_LCD_WriteChar)
while (*str) {
HAL_LCD_WriteChar(*str++);
}
}

void HAL_LCD_Clear(void) {
// ... (清屏命令发送,具体命令参考 LCD 驱动芯片手册)
// 省略具体实现
}

void HAL_LCD_SetCursor(uint8_t row, uint8_t col) {
// ... (设置光标位置命令发送,具体命令参考 LCD 驱动芯片手册)
// 省略具体实现
}

void HAL_LCD_WriteChar(char c) {
// ... (向 LCD 写入一个字符,通过 SPI 发送数据,具体 SPI 通信过程和数据格式参考 LCD 驱动芯片手册)
// 省略具体实现
}

// --- 编码器 驱动实现 (假设 GPIO 中断) ---
// 假设编码器 A 相和 B 相连接到 GPIO_PIN_ENCODER_A 和 GPIO_PIN_ENCODER_B
#define GPIO_PIN_ENCODER_A GPIO_PIN_8
#define GPIO_PIN_ENCODER_B GPIO_PIN_9

static volatile int32_t encoder_count = 0;
static void (*encoder_callback_func)(int32_t increment) = NULL;

void HAL_Encoder_Init(void) {
// 初始化 GPIO_PIN_ENCODER_A 和 GPIO_PIN_ENCODER_B 为输入模式,并使能外部中断
HAL_GPIO_Init(GPIO_PIN_ENCODER_A, GPIO_MODE_INPUT, GPIO_OUTPUT_PP, GPIO_PULL_UP);
HAL_GPIO_Init(GPIO_PIN_ENCODER_B, GPIO_MODE_INPUT, GPIO_OUTPUT_PP, GPIO_PULL_UP);

// 配置外部中断,例如使用 EXTI (External Interrupt/Event Controller)
// ... (此处省略 EXTI 配置,需要根据具体的 MCU 手册配置 GPIO 中断)
// 示例,假设 GPIO_PIN_ENCODER_A 和 GPIO_PIN_ENCODER_B 连接到 EXTI8 和 EXTI9
// 使能 EXTI8 和 EXTI9 中断,配置触发边沿为上升沿和下降沿
// ... (具体 EXTI 配置代码)

// 使能 NVIC 中断
// ... (具体 NVIC 配置代码,配置 EXTI8_IRQn 和 EXTI9_IRQn 中断)
}

int32_t HAL_Encoder_ReadCount(void) {
return encoder_count;
}

void HAL_Encoder_ResetCount(void) {
encoder_count = 0;
}

void HAL_Encoder_RegisterCallback(void (*callback)(int32_t increment)) {
encoder_callback_func = callback;
}

// 编码器 中断服务例程 (需要根据实际 MCU 的中断向量表修改)
void EXTI9_5_IRQHandler(void) { // 示例,假设 GPIO_PIN_ENCODER_A 和 GPIO_PIN_ENCODER_B 在 EXTI9_5 中断线
if (EXTI_GetITStatus(EXTI_Line8) != RESET) { // GPIO_PIN_ENCODER_A 中断
EXTI_ClearITPendingBit(EXTI_Line8);
bool pinA_state = HAL_GPIO_ReadPin(GPIO_PIN_ENCODER_A);
bool pinB_state = HAL_GPIO_ReadPin(GPIO_PIN_ENCODER_B);
if (pinA_state) { // 上升沿
if (pinB_state) { // B 相高电平,反向
encoder_count--;
if (encoder_callback_func != NULL) encoder_callback_func(-1);
} else { // B 相低电平,正向
encoder_count++;
if (encoder_callback_func != NULL) encoder_callback_func(1);
}
} else { // 下降沿
if (pinB_state) { // B 相高电平,正向
encoder_count++;
if (encoder_callback_func != NULL) encoder_callback_func(1);
} else { // B 相低电平,反向
encoder_count--;
if (encoder_callback_func != NULL) encoder_callback_func(-1);
}
}
}
if (EXTI_GetITStatus(EXTI_Line9) != RESET) { // GPIO_PIN_ENCODER_B 中断
EXTI_ClearITPendingBit(EXTI_Line9);
// 编码器 B 相中断处理逻辑,与 A 相类似,但需要根据编码器类型和接线方式调整逻辑
// ... (省略具体实现,与 EXTI_Line8 中断处理类似)
}
}

// --- 按键 驱动实现 ---
void HAL_Button_Init(GPIO_PinTypeDef buttonPin) {
HAL_GPIO_Init(buttonPin, GPIO_MODE_INPUT, GPIO_OUTPUT_PP, GPIO_PULL_UP); // 假设按键默认高电平,按下后低电平
}

bool HAL_Button_IsPressed(GPIO_PinTypeDef buttonPin) {
return !HAL_GPIO_ReadPin(buttonPin); // 按下返回 true
}

2. 驱动层 (Driver Layer)

这部分代码将直接调用 hal.h 中定义的 HAL 函数,并根据具体的硬件平台进行初始化和配置。由于驱动层代码高度依赖于具体的硬件平台,这里只提供框架示例。

adc_driver.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "adc_driver.h"
#include "hal.h"

void ADC_Driver_Init(void) {
// 初始化 ADC 外设,例如选择 ADC 通道、分辨率等
HAL_ADC_Init(ADC_CHANNEL_0, ADC_RESOLUTION_12BIT); // 例如,使用 ADC 通道 0,12 位分辨率
HAL_ADC_Init(ADC_CHANNEL_1, ADC_RESOLUTION_12BIT); // 例如,使用 ADC 通道 1,12 位分辨率
// ... 初始化其他 ADC 通道
}

uint16_t ADC_Driver_ReadChannel(ADC_ChannelTypeDef channel) {
// 读取指定 ADC 通道的值
return HAL_ADC_Read(channel);
}

pwm_driver.c

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "pwm_driver.h"
#include "hal.h"

void PWM_Driver_Init(void) {
// 初始化 PWM 外设,例如选择 PWM 通道、频率等
HAL_PWM_Init(PWM_CHANNEL_0, 50000); // 例如,使用 PWM 通道 0,频率 50kHz
// ... 初始化其他 PWM 通道
}

void PWM_Driver_SetDutyCycle(PWM_ChannelTypeDef channel, float dutyCycle) {
// 设置 PWM 通道的占空比
HAL_PWM_SetDutyCycle(channel, dutyCycle);
}

lcd_driver.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "lcd_driver.h"
#include "hal.h"

void LCD_Driver_Init(void) {
// 初始化 LCD 驱动,例如 SPI 初始化、LCD 初始化序列等
HAL_LCD_Init();
}

void LCD_Driver_WriteString(const char *str) {
HAL_LCD_WriteString(str);
}

void LCD_Driver_Clear(void) {
HAL_LCD_Clear();
}

void LCD_Driver_SetCursor(uint8_t row, uint8_t col) {
HAL_LCD_SetCursor(row, col);
}

void LCD_Driver_WriteChar(char c) {
HAL_LCD_WriteChar(c);
}

encoder_driver.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "encoder_driver.h"
#include "hal.h"

static int32_t encoder_count_driver = 0;

void Encoder_Driver_Init(void) {
HAL_Encoder_Init();
HAL_Encoder_RegisterCallback(Encoder_Driver_Callback); // 注册编码器回调函数
}

int32_t Encoder_Driver_GetCount(void) {
return encoder_count_driver;
}

void Encoder_Driver_ResetCount(void) {
encoder_count_driver = 0;
HAL_Encoder_ResetCount();
}

// 编码器回调函数,在 HAL 层中断服务例程中被调用
void Encoder_Driver_Callback(int32_t increment) {
encoder_count_driver += increment;
}

button_driver.c

1
2
3
4
5
6
7
8
9
10
#include "button_driver.h"
#include "hal.h"

void Button_Driver_Init(GPIO_PinTypeDef buttonPin) {
HAL_Button_Init(buttonPin);
}

bool Button_Driver_IsPressed(GPIO_PinTypeDef buttonPin) {
return HAL_Button_IsPressed(buttonPin);
}

3. 控制层 (Control Layer)

power_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
24
25
26
27
28
29
30
31
32
#ifndef POWER_CONTROL_H
#define POWER_CONTROL_H

#include <stdint.h>
#include <stdbool.h>

// 电源模式
typedef enum {
POWER_MODE_CV, // 恒压模式
POWER_MODE_CC // 恒流模式
} PowerModeTypeDef;

// 电源状态
typedef enum {
POWER_STATE_OFF,
POWER_STATE_CV,
POWER_STATE_CC,
POWER_STATE_PROTECTION // 保护状态
} PowerStateTypeDef;

// 电源控制函数声明
void PowerControl_Init(void);
void PowerControl_SetOutputVoltage(float voltage); // 设置输出电压 (V)
void PowerControl_SetOutputCurrent(float current); // 设置输出电流 (A)
void PowerControl_EnableOutput(bool enable); // 使能/禁用 输出
PowerStateTypeDef PowerControl_GetPowerState(void); // 获取电源状态
float PowerControl_GetOutputVoltageFeedback(void); // 获取电压反馈值 (V)
float PowerControl_GetOutputCurrentFeedback(void); // 获取电流反馈值 (A)
float PowerControl_GetOutputPower(void); // 获取输出功率 (W)
PowerModeTypeDef PowerControl_GetCurrentPowerMode(void); // 获取当前电源模式 (CV/CC)

#endif // POWER_CONTROL_H

power_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
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "power_control.h"
#include "adc_driver.h"
#include "pwm_driver.h"
#include "timer_driver.h" // 用于定时采样和控制环
#include "protection.h" // 保护模块
#include "parameter_config.h" // 参数配置模块

#define VOLTAGE_FEEDBACK_CHANNEL ADC_CHANNEL_0 // 电压反馈 ADC 通道
#define CURRENT_FEEDBACK_CHANNEL ADC_CHANNEL_1 // 电流反馈 ADC 通道
#define PWM_CONTROL_CHANNEL PWM_CHANNEL_0 // PWM 控制通道

#define CONTROL_LOOP_PERIOD_MS 10 // 控制环周期 (ms)

// PID 控制器参数 (电压环)
#define PID_VOLTAGE_KP 1.0f
#define PID_VOLTAGE_KI 0.1f
#define PID_VOLTAGE_KD 0.01f

// PID 控制器参数 (电流环)
#define PID_CURRENT_KP 0.5f
#define PID_CURRENT_KI 0.05f
#define PID_CURRENT_KD 0.005f

static float target_voltage = 0.0f; // 目标输出电压 (V)
static float target_current = 0.0f; // 目标输出电流 (A)
static bool output_enabled = false; // 输出使能标志
static PowerStateTypeDef power_state = POWER_STATE_OFF; // 电源状态
static PowerModeTypeDef current_power_mode = POWER_MODE_CV; // 当前电源模式

// PID 控制器状态变量 (电压环)
static float voltage_integral_error = 0.0f;
static float voltage_prev_error = 0.0f;

// PID 控制器状态变量 (电流环)
static float current_integral_error = 0.0f;
static float current_prev_error = 0.0f;

void PowerControl_Init(void) {
ADC_Driver_Init();
PWM_Driver_Init();
Timer_Driver_Init(TIMER_ID_0, CONTROL_LOOP_PERIOD_MS); // 初始化定时器,用于控制环
Timer_Driver_RegisterCallback(TIMER_ID_0, ControlLoop_Callback); // 注册控制环回调函数
Protection_Init();
ParameterConfig_LoadParameters(); // 加载参数配置

PowerControl_EnableOutput(false); // 初始禁用输出
Timer_Driver_Start(TIMER_ID_0); // 启动控制环定时器
}

void PowerControl_SetOutputVoltage(float voltage) {
target_voltage = voltage;
if (target_voltage < 0.0f) target_voltage = 0.0f;
if (target_voltage > 28.0f) target_voltage = 28.0f; // 限制最大输出电压
}

void PowerControl_SetOutputCurrent(float current) {
target_current = current;
if (target_current < 0.0f) target_current = 0.0f;
if (target_current > 10.0f) target_current = 10.0f; // 限制最大输出电流
}

void PowerControl_EnableOutput(bool enable) {
output_enabled = enable;
if (!output_enabled) {
PWM_Driver_SetDutyCycle(PWM_CONTROL_CHANNEL, 0.0f); // 禁用输出时,PWM 占空比设为 0
power_state = POWER_STATE_OFF;
}
}

PowerStateTypeDef PowerControl_GetPowerState(void) {
return power_state;
}

float PowerControl_GetOutputVoltageFeedback(void) {
uint16_t adc_value = ADC_Driver_ReadChannel(VOLTAGE_FEEDBACK_CHANNEL);
// ADC 值转换为电压值 (需要根据实际硬件电路和 ADC 分辨率进行校准和转换)
// 假设 ADC 满量程值为 4095 (12 位 ADC),电压反馈比例为 1/10 (分压电阻)
return (float)adc_value / 4095.0f * 3.3f * 10.0f; // 示例转换公式,需要根据实际情况调整
}

float PowerControl_GetOutputCurrentFeedback(void) {
uint16_t adc_value = ADC_Driver_ReadChannel(CURRENT_FEEDBACK_CHANNEL);
// ADC 值转换为电流值 (需要根据实际硬件电路和 ADC 分辨率进行校准和转换)
// 假设 ADC 满量程值为 4095 (12 位 ADC),电流采样电阻为 0.01 Ohm,运放放大倍数为 20
return (float)adc_value / 4095.0f * 3.3f / 0.01f / 20.0f; // 示例转换公式,需要根据实际情况调整
}

float PowerControl_GetOutputPower(void) {
return PowerControl_GetOutputVoltageFeedback() * PowerControl_GetOutputCurrentFeedback();
}

PowerModeTypeDef PowerControl_GetCurrentPowerMode(void) {
return current_power_mode;
}

// PID 控制器计算函数 (电压环)
static float Voltage_PID_Controller(float setpoint, float feedback) {
float error = setpoint - feedback;
voltage_integral_error += error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 积分项
float derivative_error = (error - voltage_prev_error) / (CONTROL_LOOP_PERIOD_MS / 1000.0f); // 微分项
voltage_prev_error = error;

float output = PID_VOLTAGE_KP * error + PID_VOLTAGE_KI * voltage_integral_error + PID_VOLTAGE_KD * derivative_error;

// 积分饱和限制 (Anti-windup)
if (output > 1.0f) {
output = 1.0f;
voltage_integral_error -= error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 限制积分累积
} else if (output < 0.0f) {
output = 0.0f;
voltage_integral_error -= error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 限制积分累积
}

return output; // PWM 占空比 (0.0 - 1.0)
}

// PID 控制器计算函数 (电流环)
static float Current_PID_Controller(float setpoint, float feedback) {
float error = setpoint - feedback;
current_integral_error += error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 积分项
float derivative_error = (error - current_prev_error) / (CONTROL_LOOP_PERIOD_MS / 1000.0f); // 微分项
current_prev_error = error;

float output = PID_CURRENT_KP * error + PID_CURRENT_KI * current_integral_error + PID_CURRENT_KD * derivative_error;

// 积分饱和限制 (Anti-windup)
if (output > 1.0f) {
output = 1.0f;
current_integral_error -= error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 限制积分累积
} else if (output < 0.0f) {
output = 0.0f;
current_integral_error -= error * CONTROL_LOOP_PERIOD_MS / 1000.0f; // 限制积分累积
}
return output; // PWM 占空比 (0.0 - 1.0)
}

// 控制环 回调函数 (定时器中断中调用)
void ControlLoop_Callback(void) {
if (output_enabled) {
float voltage_feedback = PowerControl_GetOutputVoltageFeedback();
float current_feedback = PowerControl_GetOutputCurrentFeedback();

// 保护检测
if (Protection_CheckProtection(voltage_feedback, current_feedback)) {
PowerControl_EnableOutput(false); // 触发保护,禁用输出
power_state = POWER_STATE_PROTECTION;
return; // 保护触发,退出控制环
}

float pwm_duty_cycle;

// 模式切换和控制
if (current_power_mode == POWER_MODE_CV) { // 恒压模式
if (current_feedback >= target_current) { // 实际电流超过设定电流,切换到 CC 模式
current_power_mode = POWER_MODE_CC;
power_state = POWER_STATE_CC;
voltage_integral_error = 0.0f; // 切换模式时,清空积分项,避免积分饱和
voltage_prev_error = 0.0f;
} else {
pwm_duty_cycle = Voltage_PID_Controller(target_voltage, voltage_feedback);
power_state = POWER_STATE_CV;
}
} else { // 恒流模式 (POWER_MODE_CC)
if (voltage_feedback >= target_voltage) { // 实际电压超过设定电压,切换回 CV 模式 (可选,根据实际需求决定是否切换回 CV)
current_power_mode = POWER_MODE_CV;
power_state = POWER_STATE_CV;
current_integral_error = 0.0f; // 切换模式时,清空积分项,避免积分饱和
current_prev_error = 0.0f;
} else {
pwm_duty_cycle = Current_PID_Controller(target_current, current_feedback);
power_state = POWER_STATE_CC;
}
}

PWM_Driver_SetDutyCycle(PWM_CONTROL_CHANNEL, pwm_duty_cycle);
}
}

protection.h

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

#include <stdbool.h>

// 保护功能函数声明
void Protection_Init(void);
bool Protection_CheckProtection(float voltage_feedback, float current_feedback);

#endif // PROTECTION_H

protection.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
#include "protection.h"
#include "parameter_config.h" // 读取保护阈值

// 保护阈值 (可以从参数配置模块加载)
static float ovp_threshold = 30.0f; // 过压保护阈值 (V)
static float ocp_threshold = 11.0f; // 过流保护阈值 (A)
static float otp_threshold = 80.0f; // 过温保护阈值 (°C) - 假设有温度传感器

void Protection_Init(void) {
// 从参数配置模块加载保护阈值
ovp_threshold = ParameterConfig_GetOVPThreshold();
ocp_threshold = ParameterConfig_GetOCPThreshold();
otp_threshold = ParameterConfig_GetOTPThreshold();
// ... 初始化其他保护功能,例如温度传感器初始化
}

bool Protection_CheckProtection(float voltage_feedback, float current_feedback) {
if (voltage_feedback > ovp_threshold) {
// 过压保护 (OVP)
// 可以添加保护动作,例如关闭 PWM 输出、报警等
return true;
}
if (current_feedback > ocp_threshold) {
// 过流保护 (OCP)
// 可以添加保护动作
return true;
}
// ... 其他保护检测,例如过温保护 (OTP)、短路保护 (SCP)、输入欠压保护 (UVP)

return false; // 没有保护触发
}

parameter_config.h

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

// 参数配置函数声明
void ParameterConfig_LoadParameters(void);
void ParameterConfig_SaveParameters(void);

float ParameterConfig_GetOVPThreshold(void);
void ParameterConfig_SetOVPThreshold(float threshold);

float ParameterConfig_GetOCPThreshold(void);
void ParameterConfig_SetOCPThreshold(float threshold);

float ParameterConfig_GetOTPThreshold(void);
void ParameterConfig_SetOTPThreshold(float threshold);

// ... 其他参数配置项

#endif // PARAMETER_CONFIG_H

parameter_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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "parameter_config.h"
// #include "eeprom_driver.h" // 如果使用 EEPROM 存储参数

// 默认参数值
#define DEFAULT_OVP_THRESHOLD 30.0f
#define DEFAULT_OCP_THRESHOLD 11.0f
#define DEFAULT_OTP_THRESHOLD 80.0f

// 参数变量
static float ovp_threshold_config = DEFAULT_OVP_THRESHOLD;
static float ocp_threshold_config = DEFAULT_OCP_THRESHOLD;
static float otp_threshold_config = DEFAULT_OTP_THRESHOLD;

void ParameterConfig_LoadParameters(void) {
// 从 EEPROM 或 Flash 中加载参数
// 如果没有存储参数,则使用默认值
// ... (从 EEPROM 读取参数的代码,如果使用 EEPROM)
// 示例,假设使用 EEPROM 驱动
// ovp_threshold_config = EEPROM_ReadFloat(EEPROM_ADDR_OVP_THRESHOLD, DEFAULT_OVP_THRESHOLD);
// ocp_threshold_config = EEPROM_ReadFloat(EEPROM_ADDR_OCP_THRESHOLD, DEFAULT_OCP_THRESHOLD);
// otp_threshold_config = EEPROM_ReadFloat(EEPROM_ADDR_OTP_THRESHOLD, DEFAULT_OTP_THRESHOLD);

// 临时使用默认值
ovp_threshold_config = DEFAULT_OVP_THRESHOLD;
ocp_threshold_config = DEFAULT_OCP_THRESHOLD;
otp_threshold_config = DEFAULT_OTP_THRESHOLD;
}

void ParameterConfig_SaveParameters(void) {
// 将参数保存到 EEPROM 或 Flash 中
// ... (将参数写入 EEPROM 的代码,如果使用 EEPROM)
// 示例,假设使用 EEPROM 驱动
// EEPROM_WriteFloat(EEPROM_ADDR_OVP_THRESHOLD, ovp_threshold_config);
// EEPROM_WriteFloat(EEPROM_ADDR_OCP_THRESHOLD, ocp_threshold_config);
// EEPROM_WriteFloat(EEPROM_ADDR_OTP_THRESHOLD, otp_threshold_config);
}

float ParameterConfig_GetOVPThreshold(void) {
return ovp_threshold_config;
}

void ParameterConfig_SetOVPThreshold(float threshold) {
ovp_threshold_config = threshold;
}

float ParameterConfig_GetOCPThreshold(void) {
return ocp_threshold_config;
}

void ParameterConfig_SetOCPThreshold(float threshold) {
ocp_threshold_config = threshold;
}

float ParameterConfig_GetOTPThreshold(void) {
return otp_threshold_config;
}

void ParameterConfig_SetOTPThreshold(float threshold) {
otp_threshold_config = threshold;
}

// ... 其他参数 Get/Set 函数

4. 应用层 (Application Layer)

user_interface.h

1
2
3
4
5
6
7
8
#ifndef USER_INTERFACE_H
#define USER_INTERFACE_H

void UI_Init(void);
void UI_UpdateDisplay(void);
void UI_ProcessInput(void); // 处理按键和编码器输入

#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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "user_interface.h"
#include "lcd_driver.h"
#include "encoder_driver.h"
#include "button_driver.h"
#include "power_control.h"
#include <stdio.h> // sprintf

#define ENCODER_BUTTON_PIN GPIO_PIN_0 // 编码器按键引脚
#define MENU_BUTTON_PIN GPIO_PIN_1 // 菜单按键引脚

// 菜单项
typedef enum {
MENU_ITEM_VOLTAGE_SET,
MENU_ITEM_CURRENT_SET,
MENU_ITEM_PROTECTION_SET,
MENU_ITEM_OUTPUT_ENABLE,
MENU_ITEM_COUNT // 菜单项数量
} MenuItemTypeDef;

static MenuItemTypeDef current_menu_item = MENU_ITEM_VOLTAGE_SET; // 当前菜单项
static bool in_menu = false; // 是否在菜单中
static float voltage_set_value_ui = 0.0f; // UI 上显示的电压设定值
static float current_set_value_ui = 0.0f; // UI 上显示的电流设定值
static bool output_enable_ui = false; // UI 上显示输出使能状态

void UI_Init(void) {
LCD_Driver_Init();
Encoder_Driver_Init();
Button_Driver_Init(ENCODER_BUTTON_PIN);
Button_Driver_Init(MENU_BUTTON_PIN);

voltage_set_value_ui = PowerControl_GetOutputVoltageFeedback(); // 初始显示当前反馈值
current_set_value_ui = PowerControl_GetOutputCurrentFeedback();
output_enable_ui = PowerControl_GetPowerState() != POWER_STATE_OFF;

UI_UpdateDisplay(); // 初始化显示
}

void UI_UpdateDisplay(void) {
LCD_Driver_Clear();
LCD_Driver_SetCursor(0, 0);

char buffer[20]; // 显示缓冲区

if (!in_menu) {
// 主界面显示
sprintf(buffer, "V_Set: %.2fV", target_voltage); // 使用全局 target_voltage
LCD_Driver_WriteString(buffer);
LCD_Driver_SetCursor(1, 0);
sprintf(buffer, "I_Set: %.2fA", target_current); // 使用全局 target_current
LCD_Driver_WriteString(buffer);
LCD_Driver_SetCursor(2, 0);
sprintf(buffer, "V_Out: %.2fV", PowerControl_GetOutputVoltageFeedback());
LCD_Driver_WriteString(buffer);
LCD_Driver_SetCursor(3, 0);
sprintf(buffer, "I_Out: %.2fA", PowerControl_GetOutputCurrentFeedback());
LCD_Driver_WriteString(buffer);
LCD_Driver_SetCursor(0, 10);
PowerStateTypeDef state = PowerControl_GetPowerState();
if (state == POWER_STATE_OFF) LCD_Driver_WriteString("OFF");
else if (state == POWER_STATE_CV) LCD_Driver_WriteString("CV");
else if (state == POWER_STATE_CC) LCD_Driver_WriteString("CC");
else if (state == POWER_STATE_PROTECTION) LCD_Driver_WriteString("PROTECT");
} else {
// 菜单界面显示
LCD_Driver_WriteString("Menu:");
LCD_Driver_SetCursor(1, 0);
if (current_menu_item == MENU_ITEM_VOLTAGE_SET) LCD_Driver_WriteString(">Set Voltage"); else LCD_Driver_WriteString(" Set Voltage");
LCD_Driver_SetCursor(2, 0);
if (current_menu_item == MENU_ITEM_CURRENT_SET) LCD_Driver_WriteString(">Set Current"); else LCD_Driver_WriteString(" Set Current");
LCD_Driver_SetCursor(3, 0);
if (current_menu_item == MENU_ITEM_PROTECTION_SET) LCD_Driver_WriteString(">Protection"); else LCD_Driver_WriteString(" Protection");
LCD_Driver_SetCursor(4, 0);
if (current_menu_item == MENU_ITEM_OUTPUT_ENABLE) LCD_Driver_WriteString(">Output En/Dis"); else LCD_Driver_WriteString(" Output En/Dis");
}
}

void UI_ProcessInput(void) {
static int32_t encoder_prev_count = 0;
int32_t encoder_current_count = Encoder_Driver_GetCount();
int32_t encoder_increment = encoder_current_count - encoder_prev_count;

if (!in_menu) {
// 主界面输入处理
if (encoder_increment != 0) {
if (Button_Driver_IsPressed(ENCODER_BUTTON_PIN)) { // 长按编码器按键进入菜单
in_menu = true;
Encoder_Driver_ResetCount(); // 进入菜单时重置编码器计数
} else {
// 调整设定值 (例如电压或电流,根据当前焦点)
if (current_menu_item == MENU_ITEM_VOLTAGE_SET) { // 假设菜单项和主界面焦点复用
target_voltage += encoder_increment * 0.1f; // 调整步进 0.1V
PowerControl_SetOutputVoltage(target_voltage);
} else if (current_menu_item == MENU_ITEM_CURRENT_SET) {
target_current += encoder_increment * 0.01f; // 调整步进 0.01A
PowerControl_SetOutputCurrent(target_current);
}
UI_UpdateDisplay();
}
}
if (Button_Driver_IsPressed(MENU_BUTTON_PIN)) { // 菜单按键,切换焦点 (例如电压/电流设定)
current_menu_item++;
if (current_menu_item >= MENU_ITEM_COUNT) {
current_menu_item = MENU_ITEM_VOLTAGE_SET;
}
UI_UpdateDisplay();
}

} else {
// 菜单界面输入处理
if (encoder_increment != 0) {
current_menu_item += encoder_increment;
if (current_menu_item < 0) current_menu_item = MENU_ITEM_COUNT - 1;
if (current_menu_item >= MENU_ITEM_COUNT) current_menu_item = 0;
UI_UpdateDisplay();
}
if (Button_Driver_IsPressed(ENCODER_BUTTON_PIN)) { // 编码器按键,确认选择菜单项
if (current_menu_item == MENU_ITEM_OUTPUT_ENABLE) {
output_enable_ui = !output_enable_ui;
PowerControl_EnableOutput(output_enable_ui);
} else if (current_menu_item == MENU_ITEM_VOLTAGE_SET) {
// 进入电压设定子菜单 (可以进一步细化菜单结构)
// 这里简化处理,直接回到主界面,电压设定已在主界面完成
in_menu = false;
} else if (current_menu_item == MENU_ITEM_CURRENT_SET) {
// 进入电流设定子菜单
in_menu = false;
} else if (current_menu_item == MENU_ITEM_PROTECTION_SET) {
// 进入保护设置子菜单
in_menu = false;
}
UI_UpdateDisplay();
}
if (Button_Driver_IsPressed(MENU_BUTTON_PIN)) { // 菜单按键,退出菜单
in_menu = false;
UI_UpdateDisplay();
}
}

encoder_prev_count = encoder_current_count;
}

5. 系统层 (System Layer)

system_init.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
#include "system_init.h"
#include "hal.h"
#include "power_control.h"
#include "user_interface.h"
#include "timer_driver.h" // 用于系统定时任务

#define SYSTEM_TICK_PERIOD_MS 10 // 系统 Tick 周期 (ms)

void System_Init(void) {
// 硬件初始化 (HAL 层初始化已经在各个驱动模块中完成)

PowerControl_Init();
UI_Init();

Timer_Driver_Init(TIMER_ID_1, SYSTEM_TICK_PERIOD_MS); // 初始化系统 Tick 定时器
Timer_Driver_RegisterCallback(TIMER_ID_1, SystemTick_Callback); // 注册系统 Tick 回调函数
Timer_Driver_Start(TIMER_ID_1); // 启动系统 Tick 定时器
}

// 系统 Tick 回调函数 (定时器中断中调用)
void SystemTick_Callback(void) {
UI_ProcessInput(); // 处理用户输入 (按键、编码器)
UI_UpdateDisplay(); // 更新显示
// ... 其他系统定时任务,例如状态监控、数据记录、通信处理等
}

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "system_init.h"
#include "power_control.h"
#include "user_interface.h"
#include "delay.h" // 简单延时函数

int main(void) {
System_Init(); // 系统初始化

while (1) {
// 主循环中可以添加一些低优先级的任务,或者让 CPU 进入低功耗模式
// UI_ProcessInput() 和 UI_UpdateDisplay() 在定时器中断中处理,这里不需要重复调用
// 可以添加其他后台任务,例如数据记录、远程通信等

// 示例:简单延时,降低 CPU 占用率
Delay_ms(10);
}
}

测试验证和维护升级

  1. 单元测试:对每个模块进行单元测试,例如HAL层的驱动函数、控制层的PID算法、UI层的显示和输入处理等,确保每个模块的功能正确。
  2. 集成测试:将各个模块组合起来进行集成测试,验证模块之间的接口和协作是否正常。
  3. 系统测试:进行全面的系统测试,包括功能测试、性能测试、可靠性测试、保护功能测试、用户界面测试等,确保整个电源系统满足设计要求。
  4. 长期运行测试:进行长时间的运行测试,模拟各种工作条件,验证系统的稳定性和可靠性。
  5. 维护升级
    • 模块化设计:采用模块化设计,方便后期维护和升级。
    • 版本控制:使用版本控制系统(如Git)管理代码,方便跟踪和回溯代码修改。
    • 固件升级:预留固件升级接口(如UART、USB、OTA等),方便后期升级固件,修复bug或添加新功能。
    • 日志记录:添加日志记录功能,方便记录系统运行状态和错误信息,用于故障排查和性能分析。

总结

以上代码提供了一个完整的嵌入式开关电源系统的软件框架,涵盖了硬件抽象层、驱动层、控制层、应用层和系统层,并详细实现了各个模块的功能。代码中使用了分层架构、模块化设计、PID控制算法、保护机制、用户界面等关键技术和方法,并加入了详细的注释和代码示例。

请注意,这只是一个代码框架和示例,实际的项目开发还需要根据具体的硬件平台、外围器件、功能需求和性能指标进行详细的设计和实现。代码中很多硬件相关的部分(如HAL层的具体实现、LCD驱动、编码器驱动等)需要根据实际的MCU型号和外围芯片进行适配和编写。 PID参数也需要根据实际的电源硬件电路进行调试和优化,才能达到最佳的控制效果。

希望这个详细的解答能够帮助您理解嵌入式开关电源系统的软件设计和实现过程。如果您有任何进一步的问题或需要更详细的代码实现,请随时提出。

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