我将为您详细阐述基于立创天空星开发板制作的耗材干燥箱的嵌入式系统设计,并提供相应的C代码实现。本项目旨在构建一个可靠、高效、可扩展的系统平台,涵盖从需求分析到系统实现、测试验证和维护升级的全流程。
关注微信公众号,提前获取相关推文
1. 项目概述与需求分析
1.1 项目背景
本项目旨在开发一款用于干燥 3D 打印耗材或其他对湿度敏感材料的干燥箱。潮湿的耗材会严重影响 3D 打印质量,甚至导致打印失败。因此,一个能够精确控制温度和时间的耗材干燥箱对于提高打印成功率和保证打印质量至关重要。
1.2 项目目标
- 核心功能:
- 加热烘干: 提供可控的热源,将干燥箱内部温度提升至设定值。
- 温湿度实时检测: 实时监测箱内温湿度,为温度控制和用户显示提供数据基础。
- 温度调节: 用户可设定干燥箱内部温度,范围为 45℃-70℃。
- 干燥时间设置: 用户可设定干燥时间,范围为 0-72 小时。
- 实时显示: 在显示屏上实时显示当前温度、湿度、设定温度、剩余干燥时间等信息。
- 性能指标:
- 温度控制精度: ±1℃
- 湿度检测精度: ±5%RH (相对湿度)
- 系统可靠性: 长时间稳定运行,故障率低。
- 用户友好性: 操作简单易懂,界面清晰直观。
- 开发平台: 立创天空星开发板 (具体型号需根据实际硬件确定,以下代码示例将基于常见的 STM32F 系列 MCU 进行适配,如 STM32F103 或 STM32F407)。
1.3 需求分析
基于以上项目目标,我们可以进一步细化需求:
- 硬件需求:
- 立创天空星开发板: 作为主控芯片,负责系统逻辑控制和数据处理。
- 温湿度传感器: 例如 DHT22 或 SHT3x 系列传感器,用于采集箱内温湿度数据。
- 加热元件: 例如陶瓷加热片或加热丝,提供热源。
- 加热控制模块: 例如固态继电器 (SSR) 或 PWM 控制电路,用于控制加热元件的开关或功率。
- 显示屏: 例如 LCD1602, LCD12864 或 OLED 屏幕,用于显示系统状态和用户交互界面。
- 按键/编码器: 用于用户输入,设置温度、时间和启动/停止干燥过程。
- 电源模块: 为整个系统供电。
- 外壳: 用于封装所有硬件组件,并提供保温效果。
- 软件需求:
- 底层驱动: 编写温湿度传感器、显示屏、按键等硬件的驱动程序。
- 温度控制算法: 实现 PID 或其他合适的温度控制算法,保证温度控制精度和稳定性。
- 用户界面: 设计友好的用户界面,方便用户设置参数和查看状态。
- 定时功能: 实现干燥时间的定时功能,并在时间到达后自动停止加热。
- 错误处理: 处理传感器故障、温度异常等错误情况,并给出提示。
- 参数存储: 保存用户设置的温度和时间参数,断电后可恢复。
2. 系统架构设计
为了构建可靠、高效、可扩展的系统平台,我们采用分层架构进行代码设计。分层架构将系统划分为不同的层次,每一层负责特定的功能,层与层之间通过清晰定义的接口进行通信,降低了模块之间的耦合度,提高了代码的可维护性和可扩展性。
2.1 系统层次结构
本系统可以划分为以下几个层次:
- 硬件抽象层 (HAL - Hardware Abstraction Layer): 位于最底层,直接与硬件交互。HAL 层封装了底层硬件的驱动细节,向上层提供统一的硬件接口。例如,GPIO 驱动、ADC 驱动、SPI/I2C 驱动、定时器驱动等。
- 驱动层 (Driver Layer): 基于 HAL 层,为上层应用提供更高级的设备驱动接口。例如,温湿度传感器驱动、显示屏驱动、加热控制驱动、按键驱动等。
- 核心服务层 (Core Service Layer): 实现系统的核心业务逻辑,例如温度控制、定时管理、用户界面逻辑、配置管理等。
- 应用层 (Application Layer): 构建用户界面,处理用户输入,调用核心服务层提供的功能,实现耗材干燥箱的完整功能。
2.2 模块划分
基于分层架构,我们可以进一步将系统划分为以下模块:
- HAL 模块:
hal_gpio.c/h
: GPIO 初始化、输入输出控制。hal_adc.c/h
: ADC 初始化、数据采集。hal_spi.c/h
: SPI 初始化、数据传输。hal_i2c.c/h
: I2C 初始化、数据传输。hal_timer.c/h
: 定时器初始化、中断处理。
- 驱动模块:
sensor_dhtxx.c/h
: DHT22 或类似温湿度传感器驱动。display_lcd12864.c/h
: LCD12864 或类似显示屏驱动。heater_control.c/h
: 加热控制模块驱动 (PWM 或 SSR)。keypad.c/h
: 按键或编码器驱动。
- 核心服务模块:
temperature_control.c/h
: 温度 PID 控制算法实现。timer_manager.c/h
: 定时器管理,实现干燥时间计时。ui_logic.c/h
: 用户界面逻辑,状态机管理。config_manager.c/h
: 配置参数管理,EEPROM 或 Flash 存储。
- 应用模块:
main.c
: 主程序入口,系统初始化,任务调度,用户交互。app_display.c/h
: 显示界面管理,数据格式化显示。
2.3 模块间交互
各模块之间的交互关系如下:
- 应用层 (main.c, app_display.c): 调用核心服务层提供的接口,例如
temperature_control_set_target_temp()
,timer_manager_set_duration()
,ui_logic_handle_key_input()
,config_manager_load_config()
,app_display_update_screen()
等。 - 核心服务层 (temperature_control.c, timer_manager.c, ui_logic.c, config_manager.c): 调用驱动层提供的接口,例如
sensor_dhtxx_read()
,heater_control_set_pwm_duty()
,display_lcd12864_display_string()
,keypad_get_key_value()
,hal_timer_start()
,hal_timer_stop()
,hal_eeprom_write()
,hal_flash_read()
等。 - 驱动层 (sensor_dhtxx.c, display_lcd12864.c, heater_control.c, keypad.c): 调用 HAL 层提供的接口,例如
hal_gpio_init()
,hal_adc_read()
,hal_spi_transmit()
,hal_timer_set_callback()
,hal_delay_ms()
等。 - HAL 层 (hal_gpio.c, hal_adc.c, hal_spi.c, hal_timer.c): 直接操作 MCU 寄存器,实现底层硬件控制。
2.4 系统架构图
+---------------------+
| 应用层 (Application Layer) |
| (main.c, app_display.c) |
+---------------------+
|
| 调用接口
V
+---------------------+
| 核心服务层 (Core Service Layer) |
| (temperature_control.c, timer_manager.c, |
| ui_logic.c, config_manager.c) |
+---------------------+
|
| 调用接口
V
+---------------------+
| 驱动层 (Driver Layer) |
| (sensor_dhtxx.c, display_lcd12864.c, |
| heater_control.c, keypad.c) |
+---------------------+
|
| 调用接口
V
+---------------------+
| 硬件抽象层 (HAL - Hardware Abstraction Layer) |
| (hal_gpio.c, hal_adc.c, hal_spi.c, hal_timer.c) |
+---------------------+
|
| 直接硬件操作
V
+---------------------+
| 硬件 (Hardware) |
| (MCU, Sensor, Display, Heater, Keypad) |
+---------------------+
3. 硬件与软件平台
3.1 硬件平台
- 开发板: 立创天空星开发板 (假设使用 STM32F103C8T6 核心板)
- 温湿度传感器: DHT22
- 加热元件: 陶瓷加热片 (12V, 50W)
- 加热控制模块: PWM 控制 MOSFET 或 固态继电器 (SSR)
- 显示屏: LCD12864 (SPI 接口)
- 按键: 4 个独立按键 (UP, DOWN, OK, CANCEL)
- 电源: 12V DC 电源适配器
3.2 软件平台
- 开发环境: Keil MDK 或 STM32CubeIDE
- 编程语言: C 语言
- 操作系统: 裸机开发 (No RTOS) 或 FreeRTOS (可选,如果系统复杂度增加)
- 调试工具: J-Link 或 ST-Link 调试器
4. 详细代码设计与实现 (C 代码)
以下代码示例将分为各个模块进行展示,力求代码清晰易懂,注释详尽。为了达到 3000 行代码的要求,代码将包含详细的函数实现和必要的注释,并且会包含一些错误处理和边界条件考虑。
4.1 HAL 模块 (hal_gpio.c/h, hal_adc.c/h, hal_spi.c/h, hal_timer.c/h)
由于 HAL 层的代码高度依赖于具体的 MCU 型号,这里只给出 hal_gpio.h
和 hal_gpio.c
的示例,其他 HAL 模块的实现思路类似。
hal_gpio.h:
#ifndef __HAL_GPIO_H__
#define __HAL_GPIO_H__
#include <stdint.h>
#include "stm32f10x.h" // 假设使用 STM32F103
// GPIO 端口定义 (根据实际硬件连接修改)
#define GPIO_HEATER_PIN GPIO_Pin_0
#define GPIO_HEATER_PORT GPIOA
#define GPIO_DHT22_PIN GPIO_Pin_1
#define GPIO_DHT22_PORT GPIOA
#define GPIO_LCD_CS_PIN GPIO_Pin_2
#define GPIO_LCD_CS_PORT GPIOA
#define GPIO_LCD_RST_PIN GPIO_Pin_3
#define GPIO_LCD_RST_PORT GPIOA
#define GPIO_LCD_DC_PIN GPIO_Pin_4
#define GPIO_LCD_DC_PORT GPIOA
#define GPIO_LCD_CLK_PIN GPIO_Pin_5
#define GPIO_LCD_CLK_PORT GPIOA
#define GPIO_LCD_DIN_PIN GPIO_Pin_7
#define GPIO_LCD_DIN_PORT GPIOA
#define GPIO_KEY_UP_PIN GPIO_Pin_8
#define GPIO_KEY_UP_PORT GPIOA
#define GPIO_KEY_DOWN_PIN GPIO_Pin_9
#define GPIO_KEY_DOWN_PORT GPIOA
#define GPIO_KEY_OK_PIN GPIO_Pin_10
#define GPIO_KEY_OK_PORT GPIOA
#define GPIO_KEY_CANCEL_PIN GPIO_Pin_11
#define GPIO_KEY_CANCEL_PORT GPIOA
// GPIO 初始化函数
void hal_gpio_init(void);
// 设置 GPIO 输出高电平
void hal_gpio_set_output_high(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
// 设置 GPIO 输出低电平
void hal_gpio_set_output_low(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
// 读取 GPIO 输入电平
uint8_t hal_gpio_read_input(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
#endif // __HAL_GPIO_H__
hal_gpio.c:
#include "hal_gpio.h"
void hal_gpio_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能 GPIOA 时钟
// Heater Pin 初始化
GPIO_InitStructure.GPIO_Pin = GPIO_HEATER_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_HEATER_PORT, &GPIO_InitStructure);
hal_gpio_set_output_low(GPIO_HEATER_PORT, GPIO_HEATER_PIN); // 初始关闭加热
// DHT22 Pin 初始化 (设置为输入,需要外部上拉电阻)
GPIO_InitStructure.GPIO_Pin = GPIO_DHT22_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIO_DHT22_PORT, &GPIO_InitStructure);
// LCD 控制引脚初始化 (SPI)
GPIO_InitStructure.GPIO_Pin = GPIO_LCD_CS_PIN | GPIO_LCD_RST_PIN | GPIO_LCD_DC_PIN | GPIO_LCD_CLK_PIN | GPIO_LCD_DIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_LCD_PORT, &GPIO_InitStructure);
// 按键引脚初始化 (上拉输入)
GPIO_InitStructure.GPIO_Pin = GPIO_KEY_UP_PIN | GPIO_KEY_DOWN_PIN | GPIO_KEY_OK_PIN | GPIO_KEY_CANCEL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIO_KEY_UP_PORT, &GPIO_InitStructure);
// 更多 GPIO 初始化... (ADC, SPI, Timer 等相关引脚)
}
void hal_gpio_set_output_high(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
GPIO_SetBits(GPIOx, GPIO_Pin);
}
void hal_gpio_set_output_low(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
uint8_t hal_gpio_read_input(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
return GPIO_ReadInputDataBit(GPIOx, GPIO_Pin);
}
其他 HAL 模块 (hal_adc.c/h, hal_spi.c/h, hal_timer.c/h) 的代码实现思路:
- hal_adc.c/h: 配置 ADC 外设时钟,初始化 ADC 通道,实现 ADC 单次转换和连续转换,提供 ADC 读取函数。
- hal_spi.c/h: 配置 SPI 外设时钟,初始化 SPI 模式 (主/从,速率,极性等),实现 SPI 数据发送和接收函数。
- hal_timer.c/h: 配置定时器时钟,初始化定时器模式 (计数模式,预分频,周期等),实现定时器启动、停止、设置回调函数等功能。
4.2 驱动模块 (sensor_dhtxx.c/h, display_lcd12864.c/h, heater_control.c/h, keypad.c/h)
sensor_dhtxx.h:
#ifndef __SENSOR_DHTXX_H__
#define __SENSOR_DHTXX_H__
#include <stdint.h>
typedef struct {
float temperature;
float humidity;
uint8_t status; // 0: 成功, 其他: 错误代码
} dhtxx_data_t;
#define DHTXX_OK 0
#define DHTXX_ERROR_CHECKSUM 1
#define DHTXX_ERROR_TIMEOUT 2
#define DHTXX_ERROR_DATA 3
#define DHTXX_ERROR_INIT 4
// 初始化 DHTXX 传感器
uint8_t sensor_dhtxx_init(void);
// 读取 DHTXX 传感器数据
dhtxx_data_t sensor_dhtxx_read_data(void);
#endif // __SENSOR_DHTXX_H__
sensor_dhtxx.c:
#include "sensor_dhtxx.h"
#include "hal_gpio.h"
#include "hal_delay.h" // 需要实现一个简单的延时函数,例如基于 SysTick
#define DHT_DATA_BITS 40
#define DHT_TIMEOUT_US 1000 // 1ms timeout
uint8_t sensor_dhtxx_init(void) {
// DHT22 初始化不需要特殊操作,GPIO 初始化在 hal_gpio_init 中完成
return DHTXX_OK;
}
dhtxx_data_t sensor_dhtxx_read_data(void) {
dhtxx_data_t data;
uint8_t raw_data[5] = {
0};
uint8_t checksum;
uint8_t i, j;
// 1. 发送起始信号
hal_gpio_set_output_low(GPIO_DHT22_PORT, GPIO_DHT22_PIN); // 拉低总线
hal_delay_ms(1); // 至少 1ms
hal_gpio_set_output_high(GPIO_DHT22_PORT, GPIO_DHT22_PIN); // 拉高总线
hal_delay_us(30); // 20-40us
// 2. 设置为输入,等待传感器响应
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_DHT22_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIO_DHT22_PORT, &GPIO_InitStructure);
// 等待低电平响应 (约 80us)
uint32_t timeout_start = hal_get_current_us();
while (hal_gpio_read_input(GPIO_DHT22_PORT, GPIO_DHT22_PIN)) {
if (hal_get_current_us() - timeout_start > DHT_TIMEOUT_US) {
data.status = DHTXX_ERROR_TIMEOUT;
return data;
}
}
// 等待高电平响应 (约 80us)
timeout_start = hal_get_current_us();
while (!hal_gpio_read_input(GPIO_DHT22_PORT, GPIO_DHT22_PIN)