编程技术分享

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

0%

简介:一款时间亮度可控的智能UV固化灯

我将为您详细阐述这款智能UV固化灯嵌入式系统的代码设计架构,并提供相应的C代码示例,以满足您对可靠性、高效性、可扩展性的要求,并结合实践验证的技术和方法。
关注微信公众号,提前获取相关推文

项目背景与需求分析

项目名称: 智能UV固化灯

项目目标: 设计并实现一款时间亮度可控的智能UV固化灯,具备可靠、高效、可扩展的嵌入式系统平台。

核心需求:

  1. UV亮度可控: 能够精确控制UV灯的亮度,实现不同固化强度的需求。
  2. 固化时间可控: 能够精确设定固化时间,满足不同材料和工艺的固化要求。
  3. 智能控制: 具备用户友好的操作界面,可以通过按键、旋钮或触摸屏等方式进行参数设置和模式切换。
  4. 实时监控: 能够实时监控系统状态,如UV灯工作状态、温度等,并提供必要的报警机制。
  5. 安全可靠: 系统运行稳定可靠,具备过温保护、过流保护等安全机制,确保设备和人员安全。
  6. 易于维护和升级: 系统架构设计应具备良好的可维护性和可扩展性,方便后续的功能升级和维护。

扩展需求 (可选):

  1. 远程控制: 支持通过网络或蓝牙等方式进行远程控制和监控。
  2. 数据记录: 记录UV灯的工作时间和固化参数,方便工艺追溯和数据分析。
  3. 预设模式: 支持预设多种固化模式,方便用户快速选择。
  4. 环境光感应: 根据环境光强度自动调整UV灯亮度,实现更智能的控制。

系统架构设计

为了满足上述需求,我们采用分层架构作为这款智能UV固化灯嵌入式系统的代码设计架构。分层架构具有以下优点:

  • 模块化: 将系统划分为不同的功能模块,每个模块负责特定的任务,降低了系统的复杂性,提高了代码的可读性和可维护性。
  • 高内聚低耦合: 模块内部功能高度相关,模块之间依赖性低,修改一个模块不会影响其他模块,提高了系统的稳定性和可扩展性。
  • 易于复用: 通用模块可以被多个项目复用,减少了开发工作量,提高了开发效率。
  • 方便测试: 可以对每个模块进行独立的单元测试,提高了代码的质量。

系统架构图:

1
2
3
4
5
6
7
8
9
10
11
+-----------------------+
| 应用层 (Application Layer) | // 用户界面、固化逻辑、模式管理
+-----------------------+
| 服务层 (Service Layer) | // UV亮度控制、定时控制、状态监控、参数配置
+-----------------------+
| 硬件抽象层 (HAL - Hardware Abstraction Layer) | // 统一硬件接口,屏蔽硬件差异
+-----------------------+
| 硬件驱动层 (Driver Layer) | // 具体硬件驱动,如GPIO、PWM、ADC、Timer、UART等
+-----------------------+
| 硬件平台 (Hardware Platform) | // 微控制器 (MCU)、UV LED驱动电路、传感器、用户界面硬件
+-----------------------+

各层功能详细描述:

  1. 硬件平台层 (Hardware Platform):

    • 微控制器 (MCU): 系统的核心控制单元,负责运行软件、处理数据、控制硬件。
    • UV LED驱动电路: 负责驱动UV LED灯,提供可调的电流或电压,实现亮度控制。
    • UV LED灯: 产生UV光的发光器件。
    • 用户界面硬件: 例如按键、旋钮、触摸屏、LCD显示屏等,用于用户交互。
    • 传感器: 例如温度传感器、光强度传感器等,用于系统状态监控。
    • 电源管理: 负责系统的电源供电和管理。
  2. 硬件驱动层 (Driver Layer):

    • GPIO驱动: 控制MCU的通用输入输出引脚,用于控制UV LED开关、按键检测、指示灯等。
    • PWM驱动: 控制MCU的脉冲宽度调制模块,用于控制UV LED驱动电路,实现亮度调节。
    • ADC驱动: 控制MCU的模数转换模块,用于读取传感器数据,如温度、光强度等。
    • Timer驱动: 控制MCU的定时器模块,用于实现精确的定时功能,如固化时间控制、周期性任务调度。
    • UART驱动: 控制MCU的通用异步收发传输器模块,用于串口通信,例如调试信息输出、远程控制等。
    • 其他外设驱动: 根据具体硬件平台,可能包含SPI、I2C、CAN等总线驱动,以及LCD、触摸屏等显示驱动。
  3. 硬件抽象层 (HAL - Hardware Abstraction Layer):

    • GPIO HAL: 提供统一的GPIO接口函数,例如HAL_GPIO_Init(), HAL_GPIO_WritePin(), HAL_GPIO_ReadPin()等,屏蔽不同MCU平台GPIO寄存器的差异。
    • PWM HAL: 提供统一的PWM接口函数,例如HAL_PWM_Init(), HAL_PWM_SetDutyCycle(), HAL_PWM_Start(), HAL_PWM_Stop()等。
    • ADC HAL: 提供统一的ADC接口函数,例如HAL_ADC_Init(), HAL_ADC_Start(), HAL_ADC_GetValue(), HAL_ADC_Stop()等。
    • Timer HAL: 提供统一的Timer接口函数,例如HAL_Timer_Init(), HAL_Timer_Start(), HAL_Timer_Stop(), HAL_Timer_SetPeriod()等。
    • UART HAL: 提供统一的UART接口函数,例如HAL_UART_Init(), HAL_UART_Transmit(), HAL_UART_Receive()等。
    • 延迟函数: 提供统一的延迟函数,例如HAL_Delay_ms(), HAL_Delay_us()等。
  4. 服务层 (Service Layer):

    • UV亮度控制服务: 封装UV亮度控制的逻辑,提供接口函数给应用层调用,例如UVControl_SetBrightness(), UVControl_GetBrightness()等。底层调用PWM HAL和GPIO HAL实现。
    • 定时控制服务: 封装定时控制的逻辑,提供接口函数给应用层调用,例如TimerControl_StartTimer(), TimerControl_StopTimer(), TimerControl_SetDuration()等。底层调用Timer HAL实现。
    • 状态监控服务: 封装系统状态监控的逻辑,例如温度监控、UV灯状态监控等,提供接口函数给应用层调用,例如StatusMonitor_GetTemperature(), StatusMonitor_GetUVLampStatus()等。底层调用ADC HAL和GPIO HAL实现。
    • 参数配置服务: 封装系统参数配置的逻辑,例如固化时间、亮度预设值等,提供接口函数给应用层调用,例如Config_SetCureTime(), Config_GetBrightnessPreset()等。可以使用Flash存储或EEPROM存储配置参数。
    • 安全管理服务: 封装安全相关的逻辑,例如过温保护、过流保护等,当检测到异常状态时,自动采取保护措施,例如关闭UV灯、报警等。
  5. 应用层 (Application Layer):

    • 用户界面管理: 处理用户交互逻辑,例如按键扫描、旋钮读取、触摸屏事件处理、LCD显示更新等。
    • 固化逻辑管理: 实现固化流程控制,根据用户设定的参数,启动UV灯、控制亮度、计时、停止UV灯等。
    • 模式管理: 实现不同固化模式的管理,例如预设模式、自定义模式等。
    • 错误处理: 处理系统运行过程中出现的错误,例如硬件故障、参数错误等,并提供友好的错误提示或报警。
    • 远程控制接口 (可选): 如果支持远程控制,则需要实现网络或蓝牙通信协议,接收远程控制指令,并反馈系统状态。

代码实现 (C语言)

为了满足3000行代码的要求,我们将详细展开各个模块的代码实现,并加入必要的注释和说明。以下代码示例基于常见的嵌入式开发环境,并假设使用STM32系列MCU (可以根据实际使用的MCU进行调整)。

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

hal_gpio.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef HAL_GPIO_H
#define HAL_GPIO_H

#include "stm32f4xx.h" // 根据实际MCU型号修改

typedef enum {
GPIO_PIN_RESET = 0,
GPIO_PIN_SET
} HAL_GPIO_PinStateTypeDef;

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF_PP, // Alternate Function Push Pull
GPIO_MODE_AF_OD // Alternate Function Open Drain
} HAL_GPIO_ModeTypeDef;

typedef enum {
GPIO_PULL_NONE,
GPIO_PULLUP,
GPIO_PULLDOWN
} HAL_GPIO_PullTypeDef;

typedef struct {
GPIO_TypeDef* GPIOx; // GPIO 端口基地址
uint16_t GPIO_Pin; // GPIO 引脚号
HAL_GPIO_ModeTypeDef GPIO_Mode; // GPIO 模式
HAL_GPIO_PullTypeDef GPIO_Pull; // 上拉/下拉配置
} HAL_GPIO_InitTypeDef;

// 初始化 GPIO
void HAL_GPIO_Init(HAL_GPIO_InitTypeDef* GPIO_InitStruct);

// 设置 GPIO 引脚输出电平
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, HAL_GPIO_PinStateTypeDef PinState);

// 读取 GPIO 引脚输入电平
HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

#endif // HAL_GPIO_H

hal_gpio.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "hal_gpio.h"

void HAL_GPIO_Init(HAL_GPIO_InitTypeDef* GPIO_InitStruct) {
GPIO_TypeDef* gpio_port = GPIO_InitStruct->GPIOx;
uint16_t gpio_pin = GPIO_InitStruct->GPIO_Pin;
HAL_GPIO_ModeTypeDef gpio_mode = GPIO_InitStruct->GPIO_Mode;
HAL_GPIO_PullTypeDef gpio_pull = GPIO_InitStruct->GPIO_Pull;

GPIO_InitTypeDef GPIO_InitStruct_LL; // 使用 STM32 LL 库的 GPIO 初始化结构体

// 使能 GPIO 时钟 (根据实际端口选择)
if (gpio_port == GPIOA) {
__HAL_RCC_GPIOA_CLK_ENABLE();
} else if (gpio_port == GPIOB) {
__HAL_RCC_GPIOB_CLK_ENABLE();
} // ... 其他端口时钟使能

GPIO_InitStruct_LL.Pin = gpio_pin;

if (gpio_mode == GPIO_MODE_INPUT) {
GPIO_InitStruct_LL.Mode = GPIO_MODE_INPUT;
} else if (gpio_mode == GPIO_MODE_OUTPUT) {
GPIO_InitStruct_LL.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
} else if (gpio_mode == GPIO_MODE_AF_PP) {
GPIO_InitStruct_LL.Mode = GPIO_MODE_AF_PP;
} else if (gpio_mode == GPIO_MODE_AF_OD) {
GPIO_InitStruct_LL.Mode = GPIO_MODE_AF_OD;
}

if (gpio_pull == GPIO_PULL_NONE) {
GPIO_InitStruct_LL.Pull = GPIO_NOPULL;
} else if (gpio_pull == GPIO_PULLUP) {
GPIO_InitStruct_LL.Pull = GPIO_PULLUP;
} else if (gpio_pull == GPIO_PULLDOWN) {
GPIO_InitStruct_LL.Pull = GPIO_PULLDOWN;
}

GPIO_InitStruct_LL.Speed = GPIO_SPEED_FREQ_LOW; // 根据需要选择速度

HAL_GPIO_Init_LL(gpio_port, &GPIO_InitStruct_LL); // 调用 STM32 HAL 库的 GPIO 初始化函数
}

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, HAL_GPIO_PinStateTypeDef PinState) {
HAL_GPIO_WritePin_LL(GPIOx, GPIO_Pin, (GPIO_PinState)PinState); // 调用 STM32 HAL 库的 GPIO 写引脚函数
}

HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
return (HAL_GPIO_ReadPin_LL(GPIOx, GPIO_Pin)); // 调用 STM32 HAL 库的 GPIO 读引脚函数
}

hal_pwm.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 HAL_PWM_H
#define HAL_PWM_H

#include "stm32f4xx.h" // 根据实际MCU型号修改

typedef struct {
TIM_TypeDef* TIMx; // 定时器基地址
uint32_t PWM_Channel; // PWM 通道
uint32_t PWM_Prescaler; // 预分频值
uint32_t PWM_Period; // 计数周期
uint32_t PWM_Pulse; // 初始脉冲宽度 (占空比)
} HAL_PWM_InitTypeDef;

// 初始化 PWM
void HAL_PWM_Init(HAL_PWM_InitTypeDef* PWM_InitStruct);

// 设置 PWM 占空比 (0-100%)
void HAL_PWM_SetDutyCycle(TIM_TypeDef* TIMx, uint32_t PWM_Channel, uint32_t DutyCycle);

// 启动 PWM 输出
void HAL_PWM_Start(TIM_TypeDef* TIMx, uint32_t PWM_Channel);

// 停止 PWM 输出
void HAL_PWM_Stop(TIM_TypeDef* TIMx, uint32_t PWM_Channel);

#endif // HAL_PWM_H

hal_pwm.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
#include "hal_pwm.h"

void HAL_PWM_Init(HAL_PWM_InitTypeDef* PWM_InitStruct) {
TIM_TypeDef* tim_port = PWM_InitStruct->TIMx;
uint32_t pwm_channel = PWM_InitStruct->PWM_Channel;
uint32_t pwm_prescaler = PWM_InitStruct->PWM_Prescaler;
uint32_t pwm_period = PWM_InitStruct->PWM_Period;
uint32_t pwm_pulse = PWM_InitStruct->PWM_Pulse;

TIM_HandleTypeDef htim; // 使用 STM32 HAL 库的定时器句柄

// 使能 定时器 时钟 (根据实际定时器选择)
if (tim_port == TIM1) {
__HAL_RCC_TIM1_CLK_ENABLE();
} else if (tim_port == TIM2) {
__HAL_RCC_TIM2_CLK_ENABLE();
} // ... 其他定时器时钟使能

htim.Instance = tim_port;
htim.Init.Prescaler = pwm_prescaler;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = pwm_period;
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim.Init.RepetitionCounter = 0; // 高级定时器可能需要

HAL_TIM_PWM_Init(&htim); // 调用 STM32 HAL 库的 PWM 初始化函数

TIM_OC_InitTypeDef sConfigOC; // PWM 输出比较配置结构体
sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM 模式 1
sConfigOC.Pulse = pwm_pulse;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 高电平有效
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

if (pwm_channel == TIM_CHANNEL_1) {
HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1);
} else if (pwm_channel == TIM_CHANNEL_2) {
HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2);
} // ... 其他通道配置
}

void HAL_PWM_SetDutyCycle(TIM_TypeDef* TIMx, uint32_t PWM_Channel, uint32_t DutyCycle) {
uint32_t pulse = (DutyCycle * (TIMx->ARR + 1)) / 100; // 计算脉冲宽度,ARR 是自动重装载寄存器
if (PWM_Channel == TIM_CHANNEL_1) {
TIMx->CCR1 = pulse; // CCRx 是捕获/比较寄存器
} else if (PWM_Channel == TIM_CHANNEL_2) {
TIMx->CCR2 = pulse;
} // ... 其他通道设置
}

void HAL_PWM_Start(TIM_TypeDef* TIMx, uint32_t PWM_Channel) {
HAL_TIM_PWM_Start( &htim_instance, pwm_channel); // 假设在初始化时保存了 htim 实例
}

void HAL_PWM_Stop(TIM_TypeDef* TIMx, uint32_t PWM_Channel) {
HAL_TIM_PWM_Stop( &htim_instance, pwm_channel);
}

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
23
24
25
#ifndef HAL_ADC_H
#define HAL_ADC_H

#include "stm32f4xx.h" // 根据实际MCU型号修改

typedef struct {
ADC_TypeDef* ADCx; // ADC 基地址
uint32_t ADC_Channel; // ADC 通道
uint32_t ADC_Resolution; // ADC 分辨率
uint32_t ADC_SampleTime; // ADC 采样时间
} HAL_ADC_InitTypeDef;

// 初始化 ADC
void HAL_ADC_Init(HAL_ADC_InitTypeDef* ADC_InitStruct);

// 启动 ADC 转换
void HAL_ADC_Start(ADC_TypeDef* ADCx);

// 获取 ADC 转换值
uint32_t HAL_ADC_GetValue(ADC_TypeDef* ADCx);

// 停止 ADC 转换
void HAL_ADC_Stop(ADC_TypeDef* ADCx);

#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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "hal_adc.h"

void HAL_ADC_Init(HAL_ADC_InitTypeDef* ADC_InitStruct) {
ADC_TypeDef* adc_port = ADC_InitStruct->ADCx;
uint32_t adc_channel = ADC_InitStruct->ADC_Channel;
uint32_t adc_resolution = ADC_InitStruct->ADC_Resolution;
uint32_t adc_sample_time = ADC_InitStruct->ADC_SampleTime;

ADC_HandleTypeDef hadc; // 使用 STM32 HAL 库的 ADC 句柄

// 使能 ADC 时钟 (根据实际 ADC 选择)
if (adc_port == ADC1) {
__HAL_RCC_ADC1_CLK_ENABLE();
} else if (adc_port == ADC2) {
__HAL_RCC_ADC2_CLK_ENABLE();
} // ... 其他 ADC 时钟使能

hadc.Instance = adc_port;
hadc.Init.Resolution = adc_resolution; // 例如 ADC_RESOLUTION_12B
hadc.Init.ScanConvMode = DISABLE; // 单通道模式
hadc.Init.ContinuousConvMode = DISABLE; // 单次转换模式
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; // 软件触发
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.NbrOfConversion = 1;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

HAL_ADC_Init(&hadc); // 调用 STM32 HAL 库的 ADC 初始化函数

ADC_ChannelConfTypeDef sConfig; // ADC 通道配置结构体
sConfig.Channel = adc_channel; // 例如 ADC_CHANNEL_0
sConfig.Rank = 1; // 转换序列中的rank
sConfig.SamplingTime = adc_sample_time; // 例如 ADC_SAMPLETIME_3CYCLES

HAL_ADC_ConfigChannel(&hadc, &sConfig); // 配置 ADC 通道
}

void HAL_ADC_Start(ADC_TypeDef* ADCx) {
HAL_ADC_Start(&hadc_instance); // 假设在初始化时保存了 hadc 实例
}

uint32_t HAL_ADC_GetValue(ADC_TypeDef* ADCx) {
HAL_ADC_PollForConversion(&hadc_instance, 10); // 等待转换完成,超时时间 10ms
return HAL_ADC_GetValue(&hadc_instance);
}

void HAL_ADC_Stop(ADC_TypeDef* ADCx) {
HAL_ADC_Stop(&hadc_instance);
}

hal_timer.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef HAL_TIMER_H
#define HAL_TIMER_H

#include "stm32f4xx.h" // 根据实际MCU型号修改

typedef void (*TimerCallbackFunction)(void); // 定时器回调函数类型定义

typedef struct {
TIM_TypeDef* TIMx; // 定时器基地址
uint32_t Timer_Prescaler; // 预分频值
uint32_t Timer_Period; // 计数周期
TimerCallbackFunction Callback; // 定时器回调函数指针
} HAL_Timer_InitTypeDef;

// 初始化 定时器
void HAL_Timer_Init(HAL_Timer_InitTypeDef* Timer_InitStruct);

// 启动 定时器
void HAL_Timer_Start(TIM_TypeDef* TIMx);

// 停止 定时器
void HAL_Timer_Stop(TIM_TypeDef* TIMx);

// 设置 定时器 周期 (重新加载自动重装载寄存器)
void HAL_Timer_SetPeriod(TIM_TypeDef* TIMx, uint32_t Period);

// 定时器 中断处理函数 (需要在 STM32 中断服务函数中调用)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

#endif // HAL_TIMER_H

hal_timer.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
#include "hal_timer.h"

static TimerCallbackFunction global_timer_callback = NULL; // 全局定时器回调函数指针

void HAL_Timer_Init(HAL_Timer_InitTypeDef* Timer_InitStruct) {
TIM_TypeDef* tim_port = Timer_InitStruct->TIMx;
uint32_t timer_prescaler = Timer_InitStruct->Timer_Prescaler;
uint32_t timer_period = Timer_InitStruct->Timer_Period;
global_timer_callback = Timer_InitStruct->Callback; // 保存回调函数

TIM_HandleTypeDef htim; // 使用 STM32 HAL 库的定时器句柄

// 使能 定时器 时钟 (根据实际定时器选择)
if (tim_port == TIM6) {
__HAL_RCC_TIM6_CLK_ENABLE();
} else if (tim_port == TIM7) {
__HAL_RCC_TIM7_CLK_ENABLE();
} // ... 其他定时器时钟使能

htim.Instance = tim_port;
htim.Init.Prescaler = timer_prescaler;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = timer_period;
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim.Init.RepetitionCounter = 0;

HAL_TIM_Base_Init(&htim); // 调用 STM32 HAL 库的定时器初始化函数

// 使能 定时器 中断
HAL_TIM_Base_Start_IT(&htim);

// 使能 定时器 中断 NVIC (根据实际定时器选择中断号)
if (tim_port == TIM6) {
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0); // 设置中断优先级
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
} else if (tim_port == TIM7) {
HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
} // ... 其他定时器中断 NVIC 配置
}

void HAL_Timer_Start(TIM_TypeDef* TIMx) {
HAL_TIM_Base_Start_IT(&htim_instance); // 假设在初始化时保存了 htim 实例
}

void HAL_Timer_Stop(TIM_TypeDef* TIMx) {
HAL_TIM_Base_Stop_IT(&htim_instance);
}

void HAL_Timer_SetPeriod(TIM_TypeDef* TIMx, uint32_t Period) {
__HAL_TIM_SET_AUTORELOAD(&htim_instance, Period); // 修改自动重装载寄存器值
}

// 定时器 中断处理回调函数 (在 STM32 中断服务函数中调用)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM6 || htim->Instance == TIM7 /*或其他定时器*/) {
if (global_timer_callback != NULL) {
global_timer_callback(); // 调用用户自定义的回调函数
}
}
}

// 例如 STM32F4xx_it.c 文件中需要添加以下中断服务函数 (以 TIM6 为例)
// void TIM6_DAC_IRQHandler(void)
// {
// HAL_TIM_IRQHandler(&htim6); // 调用 HAL 库定时器中断处理函数
// }

hal_delay.h:

1
2
3
4
5
6
7
#ifndef HAL_DELAY_H
#define HAL_DELAY_H

void HAL_Delay_ms(uint32_t ms);
void HAL_Delay_us(uint32_t us);

#endif // HAL_DELAY_H

hal_delay.c:

1
2
3
4
5
6
7
8
9
10
11
#include "hal_delay.h"
#include "stm32f4xx_hal.h" // 引入 STM32 HAL 库头文件

void HAL_Delay_ms(uint32_t ms) {
HAL_Delay(ms); // 直接调用 STM32 HAL 库的延时函数
}

void HAL_Delay_us(uint32_t us) {
// 可以使用 SysTick 定时器实现更精确的微秒级延时,这里简化直接使用毫秒延时
HAL_Delay((us + 999) / 1000); // 向上取整到毫秒
}

2. 硬件驱动层 (Driver Layer)

uv_led_driver.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
#ifndef UV_LED_DRIVER_H
#define UV_LED_DRIVER_H

#include "hal_gpio.h"
#include "hal_pwm.h"

// UV LED 驱动初始化配置结构体
typedef struct {
GPIO_TypeDef* Enable_GPIO_Port; // UV LED 使能 GPIO 端口
uint16_t Enable_GPIO_Pin; // UV LED 使能 GPIO 引脚
TIM_TypeDef* PWM_TIM; // PWM 定时器
uint32_t PWM_Channel; // PWM 通道
} UV_LED_Driver_InitTypeDef;

// 初始化 UV LED 驱动
void UV_LED_Driver_Init(UV_LED_Driver_InitTypeDef* init_config);

// 设置 UV LED 亮度 (0-100%)
void UV_LED_Driver_SetBrightness(uint32_t brightness);

// 开启 UV LED
void UV_LED_Driver_Enable(void);

// 关闭 UV LED
void UV_LED_Driver_Disable(void);

#endif // UV_LED_DRIVER_H

uv_led_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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "uv_led_driver.h"

static UV_LED_Driver_InitTypeDef uv_led_config; // 保存 UV LED 驱动配置

void UV_LED_Driver_Init(UV_LED_Driver_InitTypeDef* init_config) {
uv_led_config = *init_config; // 复制配置参数

// 初始化 使能 GPIO
HAL_GPIO_InitTypeDef enable_gpio_init;
enable_gpio_init.GPIOx = uv_led_config.Enable_GPIO_Port;
enable_gpio_init.GPIO_Pin = uv_led_config.Enable_GPIO_Pin;
enable_gpio_init.GPIO_Mode = GPIO_MODE_OUTPUT;
enable_gpio_init.GPIO_Pull = GPIO_PULL_NONE;
HAL_GPIO_Init(&enable_gpio_init);

// 初始化 PWM
HAL_PWM_InitTypeDef pwm_init;
pwm_init.TIMx = uv_led_config.PWM_TIM;
pwm_init.PWM_Channel = uv_led_config.PWM_Channel;
pwm_init.PWM_Prescaler = 72 - 1; // 假设系统时钟 72MHz,预分频 72,PWM 计数器时钟 1MHz
pwm_init.PWM_Period = 100 - 1; // PWM 周期 100,频率 10kHz
pwm_init.PWM_Pulse = 0; // 初始占空比 0%
HAL_PWM_Init(&pwm_init);

UV_LED_Driver_Disable(); // 初始状态关闭 UV LED
}

void UV_LED_Driver_SetBrightness(uint32_t brightness) {
if (brightness > 100) brightness = 100;
HAL_PWM_SetDutyCycle(uv_led_config.PWM_TIM, uv_led_config.PWM_Channel, brightness);
}

void UV_LED_Driver_Enable(void) {
HAL_GPIO_WritePin(uv_led_config.Enable_GPIO_Port, uv_led_config.Enable_GPIO_Pin, GPIO_PIN_SET);
HAL_PWM_Start(uv_led_config.PWM_TIM, uv_led_config.PWM_Channel);
}

void UV_LED_Driver_Disable(void) {
HAL_GPIO_WritePin(uv_led_config.Enable_GPIO_Port, uv_led_config.Enable_GPIO_Pin, GPIO_PIN_RESET);
HAL_PWM_Stop(uv_led_config.PWM_TIM, uv_led_config.PWM_Channel);
UV_LED_Driver_SetBrightness(0); // 关闭时亮度设置为 0%
}

button_driver.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
#ifndef BUTTON_DRIVER_H
#define BUTTON_DRIVER_H

#include "hal_gpio.h"

typedef struct {
GPIO_TypeDef* GPIO_Port; // 按键 GPIO 端口
uint16_t GPIO_Pin; // 按键 GPIO 引脚
uint8_t ActiveLevel; // 按键有效电平 (0: 低电平有效, 1: 高电平有效)
uint32_t DebounceTime; // 按键消抖时间 (ms)
} Button_InitTypeDef;

typedef enum {
BUTTON_RELEASED,
BUTTON_PRESSED
} ButtonState;

// 初始化 按键
void Button_Init(Button_InitTypeDef* button_config);

// 获取 按键状态
ButtonState Button_GetState(void);

#endif // BUTTON_DRIVER_H

button_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
24
25
26
27
28
29
30
31
32
33
34
35
#include "button_driver.h"
#include "hal_delay.h"

static Button_InitTypeDef button_config; // 保存按键配置
static ButtonState current_button_state = BUTTON_RELEASED; // 当前按键状态
static uint32_t last_debounce_time = 0; // 上次消抖时间

void Button_Init(Button_InitTypeDef* button_config_in) {
button_config = *button_config_in;

// 初始化 GPIO
HAL_GPIO_InitTypeDef gpio_init;
gpio_init.GPIOx = button_config.GPIO_Port;
gpio_init.GPIO_Pin = button_config.GPIO_Pin;
gpio_init.GPIO_Mode = GPIO_MODE_INPUT;
gpio_init.GPIO_Pull = (button_config.ActiveLevel == 0) ? GPIO_PULLUP : GPIO_PULLDOWN; // 根据有效电平配置上拉/下拉
HAL_GPIO_Init(&gpio_init);
}

ButtonState Button_GetState(void) {
HAL_GPIO_PinStateTypeDef pin_state = HAL_GPIO_ReadPin(button_config.GPIO_Port, button_config.GPIO_Pin);
ButtonState raw_state = (pin_state == GPIO_PIN_SET) ? BUTTON_RELEASED : BUTTON_PRESSED; // 默认高电平释放,低电平按下

if (button_config.ActiveLevel == 1) { // 高电平有效时,状态反转
raw_state = (raw_state == BUTTON_PRESSED) ? BUTTON_RELEASED : BUTTON_PRESSED;
}

if (raw_state != current_button_state) { // 状态发生变化,进行消抖
if ((HAL_GetTick() - last_debounce_time) >= button_config.DebounceTime) {
current_button_state = raw_state;
last_debounce_time = HAL_GetTick();
}
}
return current_button_state;
}

temperature_sensor_driver.h:

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

#include "hal_adc.h"

// 温度传感器驱动初始化配置结构体
typedef struct {
ADC_TypeDef* ADC_Port; // ADC 端口
uint32_t ADC_Channel; // ADC 通道
float Vref; // 参考电压 (V)
float R_series; // 串联电阻阻值 (Ω) (如果使用电阻分压)
float Beta; // NTC 热敏电阻 B 值
float T0; // 参考温度 (K) 通常为 298.15K (25℃)
float R0; // 参考温度下的电阻值 (Ω)
} TemperatureSensor_InitTypeDef;

// 初始化 温度传感器驱动
void TemperatureSensor_Init(TemperatureSensor_InitTypeDef* init_config);

// 读取 温度值 (摄氏度 °C)
float TemperatureSensor_ReadTemperature(void);

#endif // TEMPERATURE_SENSOR_DRIVER_H

temperature_sensor_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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "temperature_sensor_driver.h"
#include <math.h>

static TemperatureSensor_InitTypeDef temp_sensor_config; // 保存温度传感器配置

void TemperatureSensor_Init(TemperatureSensor_InitTypeDef* init_config) {
temp_sensor_config = *init_config;

// 初始化 ADC
HAL_ADC_InitTypeDef adc_init;
adc_init.ADCx = temp_sensor_config.ADC_Port;
adc_init.ADC_Channel = temp_sensor_config.ADC_Channel;
adc_init.ADC_Resolution = ADC_RESOLUTION_12B; // 12 位分辨率
adc_init.ADC_SampleTime = ADC_SAMPLETIME_480CYCLES; // 较长的采样时间,提高精度
HAL_ADC_Init(&adc_init);
}

float TemperatureSensor_ReadTemperature(void) {
HAL_ADC_Start(temp_sensor_config.ADC_Port);
uint32_t adc_value = HAL_ADC_GetValue(temp_sensor_config.ADC_Port);
HAL_ADC_Stop(temp_sensor_config.ADC_Port);

float v_sensor = (float)adc_value * temp_sensor_config.Vref / 4095.0f; // 计算传感器电压

float r_ntc;
if (temp_sensor_config.R_series > 0) {
r_ntc = temp_sensor_config.R_series * (temp_sensor_config.Vref / v_sensor - 1.0f); // 计算 NTC 热敏电阻阻值 (电阻分压)
} else {
// 如果没有串联电阻,需要根据传感器 datasheet 确定电压-电阻转换关系,这里简化处理,假设电压与温度线性关系 (仅供示例)
r_ntc = v_sensor * 1000.0f; // 假设 1mV 对应 1Ω
}

// 使用 Steinhart-Hart 方程或 B 值方程计算温度 (这里使用 B 值方程简化计算)
float t_kelvin = temp_sensor_config.T0 * temp_sensor_config.Beta / (temp_sensor_config.Beta * log(r_ntc / temp_sensor_config.R0) + temp_sensor_config.T0 * log(temp_sensor_config.R0 / r_ntc));
float t_celsius = t_kelvin - 273.15f; // 转换为摄氏度

return t_celsius;
}

3. 服务层 (Service Layer)

uv_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
#ifndef UV_CONTROL_SERVICE_H
#define UV_CONTROL_SERVICE_H

#include "uv_led_driver.h"

// 初始化 UV 控制服务
void UVControl_Init(UV_LED_Driver_InitTypeDef* uv_led_driver_config);

// 设置 UV 亮度 (0-100%)
void UVControl_SetBrightness(uint32_t brightness);

// 获取当前 UV 亮度
uint32_t UVControl_GetBrightness(void);

// 开启 UV 灯
void UVControl_Enable(void);

// 关闭 UV 灯
void UVControl_Disable(void);

// 获取 UV 灯状态 (开启/关闭)
uint8_t UVControl_GetStatus(void);

#endif // UV_CONTROL_SERVICE_H

uv_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
#include "uv_control_service.h"

static uint32_t current_brightness = 0; // 当前 UV 亮度
static uint8_t uv_lamp_status = 0; // UV 灯状态 (0: 关闭, 1: 开启)

void UVControl_Init(UV_LED_Driver_InitTypeDef* uv_led_driver_config) {
UV_LED_Driver_Init(uv_led_driver_config);
}

void UVControl_SetBrightness(uint32_t brightness) {
current_brightness = brightness;
UV_LED_Driver_SetBrightness(brightness);
}

uint32_t UVControl_GetBrightness(void) {
return current_brightness;
}

void UVControl_Enable(void) {
UV_LED_Driver_Enable();
uv_lamp_status = 1;
}

void UVControl_Disable(void) {
UV_LED_Driver_Disable();
uv_lamp_status = 0;
}

uint8_t UVControl_GetStatus(void) {
return uv_lamp_status;
}

timer_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
#ifndef TIMER_CONTROL_SERVICE_H
#define TIMER_CONTROL_SERVICE_H

#include "hal_timer.h"

typedef void (*CureCompleteCallback)(void); // 固化完成回调函数类型定义

// 初始化 定时控制服务
void TimerControl_Init(TIM_TypeDef* timer_port, uint32_t timer_prescaler, uint32_t timer_period);

// 启动 定时器,开始固化计时
void TimerControl_StartTimer(uint32_t duration_ms, CureCompleteCallback callback);

// 停止 定时器
void TimerControl_StopTimer(void);

// 获取剩余固化时间 (ms)
uint32_t TimerControl_GetRemainingTime(void);

// 设置固化时间 (ms)
void TimerControl_SetDuration(uint32_t duration_ms);

#endif // TIMER_CONTROL_SERVICE_H

timer_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
#include "timer_control_service.h"

static uint32_t cure_duration_ms = 0; // 固化总时长 (ms)
static uint32_t remaining_time_ms = 0; // 剩余固化时间 (ms)
static uint8_t timer_running = 0; // 定时器运行状态 (0: 停止, 1: 运行)
static CureCompleteCallback cure_complete_callback = NULL; // 固化完成回调函数指针

static TIM_TypeDef* timer_port_instance; // 保存定时器端口实例

// 定时器中断回调函数 (在 HAL_TIM_PeriodElapsedCallback 中被调用)
static void Timer_InterruptCallback(void) {
if (timer_running) {
if (remaining_time_ms > 0) {
remaining_time_ms--;
} else {
TimerControl_StopTimer(); // 固化时间到,停止定时器
if (cure_complete_callback != NULL) {
cure_complete_callback(); // 调用固化完成回调函数
}
}
}
}

void TimerControl_Init(TIM_TypeDef* timer_port, uint32_t timer_prescaler, uint32_t timer_period) {
timer_port_instance = timer_port;

HAL_Timer_InitTypeDef timer_init;
timer_init.TIMx = timer_port;
timer_init.Timer_Prescaler = timer_prescaler;
timer_init.Timer_Period = timer_period; // 1ms 中断一次 (假设计数器时钟 1MHz)
timer_init.Callback = Timer_InterruptCallback;
HAL_Timer_Init(&timer_init);
}

void TimerControl_StartTimer(uint32_t duration_ms, CureCompleteCallback callback) {
cure_duration_ms = duration_ms;
remaining_time_ms = duration_ms;
cure_complete_callback = callback;
timer_running = 1;
HAL_Timer_Start(timer_port_instance);
}

void TimerControl_StopTimer(void) {
timer_running = 0;
HAL_Timer_Stop(timer_port_instance);
remaining_time_ms = 0; // 停止时剩余时间清零
}

uint32_t TimerControl_GetRemainingTime(void) {
return remaining_time_ms;
}

void TimerControl_SetDuration(uint32_t duration_ms) {
cure_duration_ms = duration_ms;
}

status_monitor_service.h:

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

#include "temperature_sensor_driver.h"
#include "uv_control_service.h"

// 初始化 状态监控服务
void StatusMonitor_Init(TemperatureSensor_InitTypeDef* temp_sensor_config);

// 获取 系统温度 (摄氏度 °C)
float StatusMonitor_GetTemperature(void);

// 获取 UV 灯状态 (开启/关闭)
uint8_t StatusMonitor_GetUVLampStatus(void);

// 检查系统是否过温,并进行保护
void StatusMonitor_CheckOverTemperature(float max_temp);

#endif // STATUS_MONITOR_SERVICE_H

status_monitor_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
#include "status_monitor_service.h"

static float current_temperature = 0.0f; // 当前温度

void StatusMonitor_Init(TemperatureSensor_InitTypeDef* temp_sensor_config) {
TemperatureSensor_Init(temp_sensor_config);
}

float StatusMonitor_GetTemperature(void) {
current_temperature = TemperatureSensor_ReadTemperature();
return current_temperature;
}

uint8_t StatusMonitor_GetUVLampStatus(void) {
return UVControl_GetStatus(); // 直接调用 UVControl 服务获取 UV 灯状态
}

void StatusMonitor_CheckOverTemperature(float max_temp) {
float temperature = StatusMonitor_GetTemperature();
if (temperature > max_temp) {
UVControl_Disable(); // 过温保护,关闭 UV 灯
// 可以添加报警提示代码,例如蜂鸣器、指示灯闪烁等
// ...
}
}

config_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
#ifndef CONFIG_SERVICE_H
#define CONFIG_SERVICE_H

// 初始化 配置服务
void Config_Init(void);

// 设置 固化时间 (秒)
void Config_SetCureTime(uint32_t time_sec);

// 获取 固化时间 (秒)
uint32_t Config_GetCureTime(void);

// 设置 亮度预设值 (0-100%)
void Config_SetBrightnessPreset(uint32_t brightness);

// 获取 亮度预设值 (0-100%)
uint32_t Config_GetBrightnessPreset(void);

// 保存配置到 Flash/EEPROM
void Config_SaveConfig(void);

// 加载配置从 Flash/EEPROM
void Config_LoadConfig(void);

#endif // CONFIG_SERVICE_H

config_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
#include "config_service.h"
#include "hal_delay.h" // 示例中使用延时模拟 Flash/EEPROM 操作

#define DEFAULT_CURE_TIME_SEC 60 // 默认固化时间 60 秒
#define DEFAULT_BRIGHTNESS_PRESET 80 // 默认亮度预设 80%

static uint32_t cure_time_sec_config = DEFAULT_CURE_TIME_SEC;
static uint32_t brightness_preset_config = DEFAULT_BRIGHTNESS_PRESET;

void Config_Init(void) {
Config_LoadConfig(); // 初始化时加载配置
}

void Config_SetCureTime(uint32_t time_sec) {
cure_time_sec_config = time_sec;
}

uint32_t Config_GetCureTime(void) {
return cure_time_sec_config;
}

void Config_SetBrightnessPreset(uint32_t brightness) {
brightness_preset_config = brightness;
}

uint32_t Config_GetBrightnessPreset(void) {
return brightness_preset_config;
}

void Config_SaveConfig(void) {
// 实际项目中需要实现 Flash/EEPROM 写入操作,这里使用延时模拟
HAL_Delay_ms(100); // 模拟 Flash 写入延时
// 将 cure_time_sec_config 和 brightness_preset_config 保存到 Flash/EEPROM
// ...
}

void Config_LoadConfig(void) {
// 实际项目中需要实现 Flash/EEPROM 读取操作,这里使用延时模拟
HAL_Delay_ms(100); // 模拟 Flash 读取延时
// 从 Flash/EEPROM 读取配置参数,如果读取失败或为空,则使用默认值
// ...
// 例如:
// cure_time_sec_config = Read_CureTime_From_Flash();
// if (cure_time_sec_config == INVALID_VALUE) { // 假设 INVALID_VALUE 表示读取失败
// cure_time_sec_config = DEFAULT_CURE_TIME_SEC;
// }
// ...
}

4. 应用层 (Application Layer)

user_interface.h:

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

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

// 处理 用户输入 (按键、旋钮等)
void UserInterface_ProcessInput(void);

// 更新 显示 (LCD 等)
void UserInterface_UpdateDisplay(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
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
#include "user_interface.h"
#include "button_driver.h"
#include "config_service.h"
#include "uv_control_service.h"
#include "timer_control_service.h"
#include "status_monitor_service.h"
#include "hal_delay.h" // 使用延时模拟显示更新

// 按键定义 (根据实际硬件连接修改)
#define BUTTON_START_PIN GPIO_PIN_0
#define BUTTON_START_PORT GPIOA
#define BUTTON_SET_TIME_PIN GPIO_PIN_1
#define BUTTON_SET_TIME_PORT GPIOA
#define BUTTON_SET_BRIGHTNESS_PIN GPIO_PIN_2
#define BUTTON_SET_BRIGHTNESS_PORT GPIOA

// 旋钮或编码器定义 (如果使用,需要添加驱动)
// ...

// LCD 显示屏定义 (如果使用,需要添加驱动)
// ...

// 固化状态枚举
typedef enum {
STATE_IDLE,
STATE_SETTING_TIME,
STATE_SETTING_BRIGHTNESS,
STATE_CURING,
STATE_COMPLETE,
STATE_ERROR
} CureState;

static CureState current_cure_state = STATE_IDLE; // 当前固化状态
static uint32_t cure_time_setting = 0; // 固化时间设置值 (秒)
static uint32_t brightness_setting = 0; // 亮度设置值 (0-100%)

static Button_InitTypeDef button_start_config;
static Button_InitTypeDef button_set_time_config;
static Button_InitTypeDef button_set_brightness_config;

// 固化完成回调函数
static void Cure_Complete_Callback(void) {
current_cure_state = STATE_COMPLETE;
UVControl_Disable(); // 固化完成后关闭 UV 灯
// 可以添加 固化完成提示音、指示灯等
// ...
}

void UserInterface_Init(void) {
// 初始化按键
button_start_config.GPIO_Port = BUTTON_START_PORT;
button_start_config.GPIO_Pin = BUTTON_START_PIN;
button_start_config.ActiveLevel = 0; // 低电平有效
button_start_config.DebounceTime = 50; // 50ms 消抖
Button_Init(&button_start_config);

button_set_time_config.GPIO_Port = BUTTON_SET_TIME_PORT;
button_set_time_config.GPIO_Pin = BUTTON_SET_TIME_PIN;
button_set_time_config.ActiveLevel = 0;
button_set_time_config.DebounceTime = 50;
Button_Init(&button_set_time_config);

button_set_brightness_config.GPIO_Port = BUTTON_SET_BRIGHTNESS_PORT;
button_set_brightness_config.GPIO_Pin = BUTTON_SET_BRIGHTNESS_PIN;
button_set_brightness_config.ActiveLevel = 0;
button_set_brightness_config.DebounceTime = 50;
Button_Init(&button_set_brightness_config);

// 初始化 LCD 显示屏 (如果使用)
// ...

// 加载配置参数
cure_time_setting = Config_GetCureTime();
brightness_setting = Config_GetBrightnessPreset();

UserInterface_UpdateDisplay(); // 初始更新显示
}

void UserInterface_ProcessInput(void) {
ButtonState start_button_state = Button_GetState(&button_start_config);
ButtonState set_time_button_state = Button_GetState(&button_set_time_config);
ButtonState set_brightness_button_state = Button_GetState(&button_set_brightness_config);

switch (current_cure_state) {
case STATE_IDLE:
if (start_button_state == BUTTON_PRESSED) {
current_cure_state = STATE_CURING;
UVControl_SetBrightness(brightness_setting);
UVControl_Enable();
TimerControl_StartTimer(cure_time_setting * 1000, Cure_Complete_Callback); // 启动固化定时器
} else if (set_time_button_state == BUTTON_PRESSED) {
current_cure_state = STATE_SETTING_TIME;
// 进入时间设置模式
// ...
} else if (set_brightness_button_state == BUTTON_PRESSED) {
current_cure_state = STATE_SETTING_BRIGHTNESS;
// 进入亮度设置模式
// ...
}
break;

case STATE_SETTING_TIME:
// 时间设置逻辑 (例如通过旋钮或按键增减时间)
// ...
if (set_time_button_state == BUTTON_PRESSED) { // 再次按下设置时间按钮确认并退出设置
current_cure_state = STATE_IDLE;
Config_SetCureTime(cure_time_setting); // 保存设置
Config_SaveConfig();
}
break;

case STATE_SETTING_BRIGHTNESS:
// 亮度设置逻辑 (例如通过旋钮或按键增减亮度)
// ...
if (set_brightness_button_state == BUTTON_PRESSED) { // 再次按下设置亮度按钮确认并退出设置
current_cure_state = STATE_IDLE;
Config_SetBrightnessPreset(brightness_setting); // 保存设置
Config_SaveConfig();
}
break;

case STATE_CURING:
// 固化过程中,可以添加暂停、取消等功能 (根据需要)
// ...
if (start_button_state == BUTTON_PRESSED) { // 按下开始按钮,可以实现暂停/继续功能
if (TimerControl_GetRemainingTime() > 0) { // 如果还有剩余时间,则暂停/继续
if (timer_running_flag) {
TimerControl_StopTimer();
UVControl_Disable(); // 暂停时关闭 UV 灯
timer_running_flag = 0;
} else {
TimerControl_StartTimer(TimerControl_GetRemainingTime(), Cure_Complete_Callback);
UVControl_SetBrightness(brightness_setting);
UVControl_Enable(); // 继续时开启 UV 灯
timer_running_flag = 1;
}
}
}
break;

case STATE_COMPLETE:
if (start_button_state == BUTTON_PRESSED) { // 固化完成后,按下开始按钮重新进入 IDLE 状态
current_cure_state = STATE_IDLE;
}
break;

case STATE_ERROR:
// 错误状态处理
// ...
break;

default:
current_cure_state = STATE_IDLE;
break;
}
UserInterface_UpdateDisplay(); // 每次输入处理后更新显示
}

void UserInterface_UpdateDisplay(void) {
// 更新 LCD 显示屏内容 (如果使用)
// ...
// 例如显示当前状态、固化时间、亮度等
// 简化示例,使用串口输出状态信息
printf("Current State: ");
switch (current_cure_state) {
case STATE_IDLE:
printf("IDLE\r\n");
break;
case STATE_SETTING_TIME:
printf("SETTING TIME\r\n");
break;
case STATE_SETTING_BRIGHTNESS:
printf("SETTING BRIGHTNESS\r\n");
break;
case STATE_CURING:
printf("CURING, Remaining Time: %lu seconds\r\n", TimerControl_GetRemainingTime() / 1000);
break;
case STATE_COMPLETE:
printf("COMPLETE\r\n");
break;
case STATE_ERROR:
printf("ERROR\r\n");
break;
default:
printf("UNKNOWN\r\n");
break;
}
printf("Cure Time: %lu seconds, Brightness: %lu%%\r\n", cure_time_setting, brightness_setting);

HAL_Delay_ms(100); // 模拟显示更新延时
}

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
#include "stm32f4xx_hal.h" // 引入 STM32 HAL 库头文件
#include "hal_delay.h"
#include "uv_control_service.h"
#include "timer_control_service.h"
#include "status_monitor_service.h"
#include "config_service.h"
#include "user_interface.h"
#include "stdio.h" // 引入标准输入输出库,用于串口 printf (调试用)

// 定义 UV LED 驱动配置参数 (根据实际硬件连接修改)
UV_LED_Driver_InitTypeDef uv_led_driver_init_config = {
.Enable_GPIO_Port = GPIOB, // 示例使用 GPIOB
.Enable_GPIO_Pin = GPIO_PIN_12,
.PWM_TIM = TIM3, // 示例使用 TIM3
.PWM_Channel = TIM_CHANNEL_1
};

// 定义 温度传感器配置参数 (根据实际硬件连接修改)
TemperatureSensor_InitTypeDef temp_sensor_init_config = {
.ADC_Port = ADC1, // 示例使用 ADC1
.ADC_Channel = ADC_CHANNEL_0,
.Vref = 3.3f, // 参考电压 3.3V
.R_series = 10000.0f, // 串联电阻 10kΩ
.Beta = 3950.0f, // NTC 热敏电阻 B 值
.T0 = 298.15f, // 参考温度 25℃ (298.15K)
.R0 = 10000.0f // 参考温度下电阻值 10kΩ
};

// 定义 定时器配置参数 (用于固化时间控制)
#define TIMER_FOR_CURE_TIME TIM6 // 示例使用 TIM6
#define TIMER_PRESCALER_CURE_TIME 1000 - 1 // 预分频 1000,计数器时钟 72kHz / 1000 = 72kHz

int main(void) {
HAL_Init(); // 初始化 HAL 库 (包括时钟、外设等)

// 初始化串口 (用于 printf 输出调试信息)
// ... (需要根据实际硬件配置 UART)
// 例如: UART_Init();

// 初始化各个服务模块
UVControl_Init(&uv_led_driver_init_config);
TimerControl_Init(TIMER_FOR_CURE_TIME, TIMER_PRESCALER_CURE_TIME, 72 - 1); // 假设计数器时钟 72kHz,周期 72,1ms 中断一次
StatusMonitor_Init(&temp_sensor_init_config);
Config_Init();
UserInterface_Init();

printf("Smart UV Curing Lamp System Initialized!\r\n");

while (1) {
UserInterface_ProcessInput(); // 处理用户输入
StatusMonitor_CheckOverTemperature(60.0f); // 检查是否过温,最大温度 60℃
// 可以添加其他周期性任务,例如数据记录、远程通信等
// ...
}
}

// **注意:** 以下为 STM32 中断服务函数示例 (需要在 stm32f4xx_it.c 文件中实现)
// 根据实际使用的定时器,修改中断服务函数名称 (例如 TIM6_DAC_IRQHandler, TIM7_IRQHandler 等)

// void TIM6_DAC_IRQHandler(void)
// {
// HAL_TIM_IRQHandler(&htim6); // 调用 HAL 库定时器中断处理函数
// }

// void SysTick_Handler(void)
// {
// HAL_IncTick(); // HAL 库 SysTick 计数器递增
// }

实践验证的技术和方法:

  • 模块化设计: 采用分层架构和模块化设计,提高代码可读性、可维护性和可扩展性。
  • 硬件抽象层 (HAL): 使用 HAL 屏蔽硬件差异,方便代码移植和复用。
  • 驱动层封装: 将硬件驱动封装成独立的模块,例如 UV LED 驱动、按键驱动、温度传感器驱动等,提高代码的内聚性。
  • 服务层封装: 将业务逻辑封装成服务模块,例如 UV 控制服务、定时控制服务、状态监控服务等,提高代码的抽象层次。
  • 状态机: 在用户界面管理中使用状态机,清晰地管理系统状态和状态转换逻辑。
  • 回调函数: 使用回调函数实现定时器中断处理和固化完成事件通知,提高代码的灵活性。
  • 配置管理: 使用配置服务模块管理系统配置参数,方便参数设置和持久化存储。
  • 错误处理: 在各个模块中加入必要的错误处理代码,提高系统的鲁棒性。
  • 代码注释: 代码中加入详细的注释,提高代码可读性和可维护性。
  • 单元测试: 对各个模块进行单元测试 (虽然代码示例中未包含单元测试代码,但在实际项目中应进行单元测试)。
  • 集成测试: 进行系统集成测试,验证各个模块之间的协同工作是否正常。
  • 实际硬件测试: 在实际硬件平台上进行测试,验证系统的功能和性能是否符合需求。

总结:

这款智能UV固化灯嵌入式系统采用了分层架构设计,从硬件抽象层到应用层,各层职责清晰,模块化程度高,具有良好的可靠性、高效性和可扩展性。代码示例提供了HAL层、驱动层、服务层和应用层的基本框架和关键功能实现,并结合了实践验证的技术和方法,可以作为您开发智能UV固化灯嵌入式系统的参考。

后续工作:

  • 完善硬件驱动: 根据实际硬件平台,完善各个硬件驱动的实现,例如 LCD 显示驱动、触摸屏驱动、编码器驱动、串口通信驱动等。
  • 完善用户界面: 根据用户需求,设计更友好的用户界面,例如使用 LCD 显示屏、触摸屏等,提供更丰富的交互功能。
  • 实现远程控制: 如果需要远程控制功能,需要添加网络或蓝牙通信协议栈,并实现远程控制命令解析和执行逻辑。
  • 实现数据记录: 如果需要数据记录功能,需要设计数据存储格式,并实现数据采集、存储和读取功能。
  • 优化系统性能: 根据实际应用场景,对系统性能进行优化,例如优化 PWM 控制算法、ADC 采样速度、定时器精度等。
  • 进行充分的测试和验证: 在实际硬件平台上进行充分的测试和验证,确保系统的功能、性能和可靠性满足需求。

希望这份详细的代码设计架构和C代码示例能够帮助您完成智能UV固化灯嵌入式系统的开发!

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