本项目基于立创·天空星开发板-GD32F407VET6-青春版,开发一款手持热成像仪。该设备将采集热红外传感器的数据,经过处理后在LCD屏幕上显示热图像,并提供用户交互界面。
一、需求分析
核心功能:
性能指标:
硬件平台:
二、系统架构设计
为了实现可靠、高效、可扩展的系统平台,我将采用分层架构和基于RTOS (Real-Time Operating System) 的设计。
1. 分层架构:
分层架构将系统划分为不同的层次,每一层只与相邻的上下层交互,降低了模块之间的耦合度,提高了系统的可维护性和可扩展性。本项目可以分为以下几层:
硬件抽象层 (HAL - Hardware Abstraction Layer):
板级支持包 (BSP - Board Support Package):
操作系统层 (OS - Operating System):
中间件层 (Middleware):
应用层 (Application):
2. 基于RTOS的设计:
采用RTOS可以实现以下优势:
系统架构图:
+-----------------------+
| 应用层 (Application) |
| (热图像采集, 图像处理, 显示, UI) |
+-----------------------+
| 中间件层 (Middleware) |
| (图像处理库, UI库) |
+-----------------------+
| 操作系统层 (OS) |
| (RTOS - FreeRTOS) |
+-----------------------+
| 板级支持包 (BSP) |
| (传感器驱动, LCD驱动, 按键驱动) |
+-----------------------+
| 硬件抽象层 (HAL) |
| (GPIO, SPI, I2C, ADC, LCD, Timer) |
+-----------------------+
| 硬件平台 (Hardware) |
| (GD32F407VET6, 热红外传感器, LCD) |
+-----------------------+
三、代码实现 (C语言)
以下代码将逐步实现各个层次的关键模块,并展示如何构建手持热成像仪的软件系统。为了达到3000行代码的目标,代码将包含详细的注释、错误处理、以及一些常用的功能模块。
1. 硬件抽象层 (HAL)
hal_gpio.h:
#ifndef HAL_GPIO_H
#define HAL_GPIO_H
#include "gd32f4xx.h" // 引入GD32F4xx头文件
typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF, // Alternate Function
GPIO_MODE_ANALOG
} gpio_mode_t;
typedef enum {
GPIO_OUTPUT_PP, // Push-Pull
GPIO_OUTPUT_OD // Open-Drain
} gpio_output_type_t;
typedef enum {
GPIO_PUPD_NONE, // No Pull-up/Pull-down
GPIO_PUPD_PULLUP,
GPIO_PUPD_PULLDOWN
} gpio_pupd_t;
typedef enum {
GPIO_SPEED_FREQ_LOW,
GPIO_SPEED_FREQ_MEDIUM,
GPIO_SPEED_FREQ_HIGH,
GPIO_SPEED_FREQ_VERY_HIGH
} gpio_speed_t;
void hal_gpio_init(uint32_t gpio_periph, uint32_t pin, gpio_mode_t mode, gpio_output_type_t otype, gpio_pupd_t pupd, gpio_speed_t speed);
void hal_gpio_write_pin(uint32_t gpio_periph, uint32_t pin, uint8_t pin_state);
uint8_t hal_gpio_read_pin(uint32_t gpio_periph, uint32_t pin);
#endif // HAL_GPIO_H
hal_gpio.c:
#include "hal_gpio.h"
void hal_gpio_init(uint32_t gpio_periph, uint32_t pin, gpio_mode_t mode, gpio_output_type_t otype, gpio_pupd_t pupd, gpio_speed_t speed) {
/* 使能GPIO时钟 */
rcu_periph_clock_enable(gpio_periph);
/* 初始化GPIO结构体 */
gpio_init(gpio_periph, GPIO_MODE_OUTPUT, GPIO_OTYPE_PP, GPIO_PIN_0); // 占位符,实际配置会被覆盖
gpio_mode_set(gpio_periph, (uint32_t)mode, (uint32_t)pupd, pin);
gpio_output_options_set(gpio_periph, (uint32_t)otype, (uint32_t)speed, pin);
}
void hal_gpio_write_pin(uint32_t gpio_periph, uint32_t pin, uint8_t pin_state) {
if (pin_state == 0) {
gpio_bit_reset(gpio_periph, pin);
} else {
gpio_bit_set(gpio_periph, pin);
}
}
uint8_t hal_gpio_read_pin(uint32_t gpio_periph, uint32_t pin) {
return gpio_input_bit_get(gpio_periph, pin);
}
hal_spi.h:
#ifndef HAL_SPI_H
#define HAL_SPI_H
#include "gd32f4xx.h"
typedef enum {
SPI_MODE_MASTER,
SPI_MODE_SLAVE
} spi_mode_t;
typedef enum {
SPI_POLARITY_LOW,
SPI_POLARITY_HIGH
} spi_polarity_t;
typedef enum {
SPI_PHASE_1EDGE,
SPI_PHASE_2EDGE
} spi_phase_t;
typedef enum {
SPI_DATASIZE_8BIT,
SPI_DATASIZE_16BIT
} spi_datasize_t;
typedef enum {
SPI_FRAMESIZE_8BIT,
SPI_FRAMESIZE_16BIT
} spi_framesize_t;
void hal_spi_init(uint32_t spi_periph, spi_mode_t mode, spi_polarity_t polarity, spi_phase_t phase, spi_datasize_t datasize, uint32_t baudrate_prescaler);
void hal_spi_transmit_byte(uint32_t spi_periph, uint8_t data);
uint8_t hal_spi_receive_byte(uint32_t spi_periph);
void hal_spi_transmit_data(uint32_t spi_periph, uint8_t *tx_data, uint32_t length);
void hal_spi_receive_data(uint32_t spi_periph, uint8_t *rx_data, uint32_t length);
#endif // HAL_SPI_H
hal_spi.c:
#include "hal_spi.h"
void hal_spi_init(uint32_t spi_periph, spi_mode_t mode, spi_polarity_t polarity, spi_phase_t phase, spi_datasize_t datasize, uint32_t baudrate_prescaler) {
spi_parameter_struct spi_init_struct;
/* 使能SPI时钟 */
if (SPI0 == spi_periph) {
rcu_periph_clock_enable(RCU_SPI0);
} else if (SPI1 == spi_periph) {
rcu_periph_clock_enable(RCU_SPI1);
} else if (SPI2 == spi_periph) {
rcu_periph_clock_enable(RCU_SPI2);
}
/* SPI配置 */
spi_struct_para_init(&spi_init_struct);
spi_init_struct.transmode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.spi_mode = (uint32_t)mode;
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init_struct.prescaler = baudrate_prescaler;
spi_init_struct.clock_polarity_phase = 0; // 默认 CPOL=0 CPHA=0
if (polarity == SPI_POLARITY_HIGH) {
spi_init_struct.clock_polarity_phase |= SPI_CK_PL_HIGH;
}
if (phase == SPI_PHASE_2EDGE) {
spi_init_struct.clock_polarity_phase |= SPI_CK_PH_2EDGE;
}
spi_init_struct.frame_size = (uint32_t)datasize;
spi_init(spi_periph, &spi_init_struct);
/* 使能SPI */
spi_enable(spi_periph);
}
void hal_spi_transmit_byte(uint32_t spi_periph, uint8_t data) {
spi_i2s_data_transmit(spi_periph, data);
while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); // 等待发送缓冲区为空
}
uint8_t hal_spi_receive_byte(uint32_t spi_periph) {
while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); // 等待接收缓冲区非空
return spi_i2s_data_receive(spi_periph);
}
void hal_spi_transmit_data(uint32_t spi_periph, uint8_t *tx_data, uint32_t length) {
for (uint32_t i = 0; i < length; i++) {
hal_spi_transmit_byte(spi_periph, tx_data[i]);
}
}
void hal_spi_receive_data