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

项目背景与需求分析
项目名称: 智能UV固化灯
项目目标: 设计并实现一款时间亮度可控的智能UV固化灯,具备可靠、高效、可扩展的嵌入式系统平台。
核心需求:
- UV亮度可控: 能够精确控制UV灯的亮度,实现不同固化强度的需求。
- 固化时间可控: 能够精确设定固化时间,满足不同材料和工艺的固化要求。
- 智能控制: 具备用户友好的操作界面,可以通过按键、旋钮或触摸屏等方式进行参数设置和模式切换。
- 实时监控: 能够实时监控系统状态,如UV灯工作状态、温度等,并提供必要的报警机制。
- 安全可靠: 系统运行稳定可靠,具备过温保护、过流保护等安全机制,确保设备和人员安全。
- 易于维护和升级: 系统架构设计应具备良好的可维护性和可扩展性,方便后续的功能升级和维护。
扩展需求 (可选):
- 远程控制: 支持通过网络或蓝牙等方式进行远程控制和监控。
- 数据记录: 记录UV灯的工作时间和固化参数,方便工艺追溯和数据分析。
- 预设模式: 支持预设多种固化模式,方便用户快速选择。
- 环境光感应: 根据环境光强度自动调整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驱动电路、传感器、用户界面硬件 +-----------------------+
|
各层功能详细描述:
硬件平台层 (Hardware Platform):
- 微控制器 (MCU): 系统的核心控制单元,负责运行软件、处理数据、控制硬件。
- UV LED驱动电路: 负责驱动UV LED灯,提供可调的电流或电压,实现亮度控制。
- UV LED灯: 产生UV光的发光器件。
- 用户界面硬件: 例如按键、旋钮、触摸屏、LCD显示屏等,用于用户交互。
- 传感器: 例如温度传感器、光强度传感器等,用于系统状态监控。
- 电源管理: 负责系统的电源供电和管理。
硬件驱动层 (Driver Layer):
- GPIO驱动: 控制MCU的通用输入输出引脚,用于控制UV LED开关、按键检测、指示灯等。
- PWM驱动: 控制MCU的脉冲宽度调制模块,用于控制UV LED驱动电路,实现亮度调节。
- ADC驱动: 控制MCU的模数转换模块,用于读取传感器数据,如温度、光强度等。
- Timer驱动: 控制MCU的定时器模块,用于实现精确的定时功能,如固化时间控制、周期性任务调度。
- UART驱动: 控制MCU的通用异步收发传输器模块,用于串口通信,例如调试信息输出、远程控制等。
- 其他外设驱动: 根据具体硬件平台,可能包含SPI、I2C、CAN等总线驱动,以及LCD、触摸屏等显示驱动。
硬件抽象层 (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()
等。
服务层 (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灯、报警等。
应用层 (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"
typedef enum { GPIO_PIN_RESET = 0, GPIO_PIN_SET } HAL_GPIO_PinStateTypeDef;
typedef enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF_PP, GPIO_MODE_AF_OD } HAL_GPIO_ModeTypeDef;
typedef enum { GPIO_PULL_NONE, GPIO_PULLUP, GPIO_PULLDOWN } HAL_GPIO_PullTypeDef;
typedef struct { GPIO_TypeDef* GPIOx; uint16_t GPIO_Pin; HAL_GPIO_ModeTypeDef GPIO_Mode; HAL_GPIO_PullTypeDef GPIO_Pull; } HAL_GPIO_InitTypeDef;
void HAL_GPIO_Init(HAL_GPIO_InitTypeDef* GPIO_InitStruct);
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, HAL_GPIO_PinStateTypeDef PinState);
HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
#endif
|
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;
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); }
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); }
HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { return (HAL_GPIO_ReadPin_LL(GPIOx, GPIO_Pin)); }
|
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"
typedef struct { TIM_TypeDef* TIMx; uint32_t PWM_Channel; uint32_t PWM_Prescaler; uint32_t PWM_Period; uint32_t PWM_Pulse; } HAL_PWM_InitTypeDef;
void HAL_PWM_Init(HAL_PWM_InitTypeDef* PWM_InitStruct);
void HAL_PWM_SetDutyCycle(TIM_TypeDef* TIMx, uint32_t PWM_Channel, uint32_t DutyCycle);
void HAL_PWM_Start(TIM_TypeDef* TIMx, uint32_t PWM_Channel);
void HAL_PWM_Stop(TIM_TypeDef* TIMx, uint32_t PWM_Channel);
#endif
|
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;
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);
TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; 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; if (PWM_Channel == TIM_CHANNEL_1) { TIMx->CCR1 = pulse; } 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); }
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"
typedef struct { ADC_TypeDef* ADCx; uint32_t ADC_Channel; uint32_t ADC_Resolution; uint32_t ADC_SampleTime; } HAL_ADC_InitTypeDef;
void HAL_ADC_Init(HAL_ADC_InitTypeDef* ADC_InitStruct);
void HAL_ADC_Start(ADC_TypeDef* ADCx);
uint32_t HAL_ADC_GetValue(ADC_TypeDef* ADCx);
void HAL_ADC_Stop(ADC_TypeDef* ADCx);
#endif
|
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;
if (adc_port == ADC1) { __HAL_RCC_ADC1_CLK_ENABLE(); } else if (adc_port == ADC2) { __HAL_RCC_ADC2_CLK_ENABLE(); }
hadc.Instance = adc_port; hadc.Init.Resolution = adc_resolution; 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);
ADC_ChannelConfTypeDef sConfig; sConfig.Channel = adc_channel; sConfig.Rank = 1; sConfig.SamplingTime = adc_sample_time;
HAL_ADC_ConfigChannel(&hadc, &sConfig); }
void HAL_ADC_Start(ADC_TypeDef* ADCx) { HAL_ADC_Start(&hadc_instance); }
uint32_t HAL_ADC_GetValue(ADC_TypeDef* ADCx) { HAL_ADC_PollForConversion(&hadc_instance, 10); 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"
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);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif
|
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;
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);
HAL_TIM_Base_Start_IT(&htim);
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); } }
void HAL_Timer_Start(TIM_TypeDef* TIMx) { HAL_TIM_Base_Start_IT(&htim_instance); }
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); }
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM6 || htim->Instance == TIM7 ) { if (global_timer_callback != NULL) { global_timer_callback(); } } }
|
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.c:
1 2 3 4 5 6 7 8 9 10 11
| #include "hal_delay.h" #include "stm32f4xx_hal.h"
void HAL_Delay_ms(uint32_t ms) { HAL_Delay(ms); }
void HAL_Delay_us(uint32_t us) { 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"
typedef struct { GPIO_TypeDef* Enable_GPIO_Port; uint16_t Enable_GPIO_Pin; TIM_TypeDef* PWM_TIM; uint32_t PWM_Channel; } UV_LED_Driver_InitTypeDef;
void UV_LED_Driver_Init(UV_LED_Driver_InitTypeDef* init_config);
void UV_LED_Driver_SetBrightness(uint32_t brightness);
void UV_LED_Driver_Enable(void);
void UV_LED_Driver_Disable(void);
#endif
|
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;
void UV_LED_Driver_Init(UV_LED_Driver_InitTypeDef* init_config) { uv_led_config = *init_config;
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);
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; pwm_init.PWM_Period = 100 - 1; pwm_init.PWM_Pulse = 0; HAL_PWM_Init(&pwm_init);
UV_LED_Driver_Disable(); }
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); }
|
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; uint16_t GPIO_Pin; uint8_t ActiveLevel; uint32_t DebounceTime; } Button_InitTypeDef;
typedef enum { BUTTON_RELEASED, BUTTON_PRESSED } ButtonState;
void Button_Init(Button_InitTypeDef* button_config);
ButtonState Button_GetState(void);
#endif
|
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;
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; uint32_t ADC_Channel; float Vref; float R_series; float Beta; float T0; float R0; } TemperatureSensor_InitTypeDef;
void TemperatureSensor_Init(TemperatureSensor_InitTypeDef* init_config);
float TemperatureSensor_ReadTemperature(void);
#endif
|
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;
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; 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); } else { r_ntc = v_sensor * 1000.0f; }
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"
void UVControl_Init(UV_LED_Driver_InitTypeDef* uv_led_driver_config);
void UVControl_SetBrightness(uint32_t brightness);
uint32_t UVControl_GetBrightness(void);
void UVControl_Enable(void);
void UVControl_Disable(void);
uint8_t UVControl_GetStatus(void);
#endif
|
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; static uint8_t uv_lamp_status = 0;
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);
uint32_t TimerControl_GetRemainingTime(void);
void TimerControl_SetDuration(uint32_t duration_ms);
#endif
|
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; static uint32_t remaining_time_ms = 0; static uint8_t timer_running = 0; static CureCompleteCallback cure_complete_callback = NULL;
static TIM_TypeDef* timer_port_instance;
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; 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);
float StatusMonitor_GetTemperature(void);
uint8_t StatusMonitor_GetUVLampStatus(void);
void StatusMonitor_CheckOverTemperature(float max_temp);
#endif
|
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(); }
void StatusMonitor_CheckOverTemperature(float max_temp) { float temperature = StatusMonitor_GetTemperature(); if (temperature > max_temp) { UVControl_Disable(); } }
|
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);
void Config_SetBrightnessPreset(uint32_t brightness);
uint32_t Config_GetBrightnessPreset(void);
void Config_SaveConfig(void);
void Config_LoadConfig(void);
#endif
|
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"
#define DEFAULT_CURE_TIME_SEC 60 #define DEFAULT_BRIGHTNESS_PRESET 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) { HAL_Delay_ms(100); }
void Config_LoadConfig(void) { HAL_Delay_ms(100); }
|
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);
void UserInterface_UpdateDisplay(void);
#endif
|
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
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;
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(); }
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; 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);
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(); timer_running_flag = 0; } else { TimerControl_StartTimer(TimerControl_GetRemainingTime(), Cure_Complete_Callback); UVControl_SetBrightness(brightness_setting); UVControl_Enable(); timer_running_flag = 1; } } } break;
case STATE_COMPLETE: if (start_button_state == BUTTON_PRESSED) { current_cure_state = STATE_IDLE; } break;
case STATE_ERROR: break;
default: current_cure_state = STATE_IDLE; break; } UserInterface_UpdateDisplay(); }
void UserInterface_UpdateDisplay(void) { 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" #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"
UV_LED_Driver_InitTypeDef uv_led_driver_init_config = { .Enable_GPIO_Port = GPIOB, .Enable_GPIO_Pin = GPIO_PIN_12, .PWM_TIM = TIM3, .PWM_Channel = TIM_CHANNEL_1 };
TemperatureSensor_InitTypeDef temp_sensor_init_config = { .ADC_Port = ADC1, .ADC_Channel = ADC_CHANNEL_0, .Vref = 3.3f, .R_series = 10000.0f, .Beta = 3950.0f, .T0 = 298.15f, .R0 = 10000.0f };
#define TIMER_FOR_CURE_TIME TIM6 #define TIMER_PRESCALER_CURE_TIME 1000 - 1
int main(void) { HAL_Init();
UVControl_Init(&uv_led_driver_init_config); TimerControl_Init(TIMER_FOR_CURE_TIME, TIMER_PRESCALER_CURE_TIME, 72 - 1); 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); } }
|
实践验证的技术和方法:
- 模块化设计: 采用分层架构和模块化设计,提高代码可读性、可维护性和可扩展性。
- 硬件抽象层 (HAL): 使用 HAL 屏蔽硬件差异,方便代码移植和复用。
- 驱动层封装: 将硬件驱动封装成独立的模块,例如 UV LED 驱动、按键驱动、温度传感器驱动等,提高代码的内聚性。
- 服务层封装: 将业务逻辑封装成服务模块,例如 UV 控制服务、定时控制服务、状态监控服务等,提高代码的抽象层次。
- 状态机: 在用户界面管理中使用状态机,清晰地管理系统状态和状态转换逻辑。
- 回调函数: 使用回调函数实现定时器中断处理和固化完成事件通知,提高代码的灵活性。
- 配置管理: 使用配置服务模块管理系统配置参数,方便参数设置和持久化存储。
- 错误处理: 在各个模块中加入必要的错误处理代码,提高系统的鲁棒性。
- 代码注释: 代码中加入详细的注释,提高代码可读性和可维护性。
- 单元测试: 对各个模块进行单元测试 (虽然代码示例中未包含单元测试代码,但在实际项目中应进行单元测试)。
- 集成测试: 进行系统集成测试,验证各个模块之间的协同工作是否正常。
- 实际硬件测试: 在实际硬件平台上进行测试,验证系统的功能和性能是否符合需求。
总结:
这款智能UV固化灯嵌入式系统采用了分层架构设计,从硬件抽象层到应用层,各层职责清晰,模块化程度高,具有良好的可靠性、高效性和可扩展性。代码示例提供了HAL层、驱动层、服务层和应用层的基本框架和关键功能实现,并结合了实践验证的技术和方法,可以作为您开发智能UV固化灯嵌入式系统的参考。
后续工作:
- 完善硬件驱动: 根据实际硬件平台,完善各个硬件驱动的实现,例如 LCD 显示驱动、触摸屏驱动、编码器驱动、串口通信驱动等。
- 完善用户界面: 根据用户需求,设计更友好的用户界面,例如使用 LCD 显示屏、触摸屏等,提供更丰富的交互功能。
- 实现远程控制: 如果需要远程控制功能,需要添加网络或蓝牙通信协议栈,并实现远程控制命令解析和执行逻辑。
- 实现数据记录: 如果需要数据记录功能,需要设计数据存储格式,并实现数据采集、存储和读取功能。
- 优化系统性能: 根据实际应用场景,对系统性能进行优化,例如优化 PWM 控制算法、ADC 采样速度、定时器精度等。
- 进行充分的测试和验证: 在实际硬件平台上进行充分的测试和验证,确保系统的功能、性能和可靠性满足需求。
希望这份详细的代码设计架构和C代码示例能够帮助您完成智能UV固化灯嵌入式系统的开发!