我将针对您提供的STC32G12K128核心开发板项目,详细阐述最适合的代码设计架构,并提供具体的C代码实现。这个项目旨在构建一个可靠、高效、可扩展的嵌入式系统平台,涵盖从需求分析到系统维护的完整开发流程。
关注微信公众号,提前获取相关推文

项目背景与需求分析
1. 项目背景
您提供的核心板基于STC32G12K128-35I-LQFP64 MCU,这是一款增强型8051内核的微控制器,具有丰富的片上资源和外设。核心板集成了RGB LED、板载LED、BLE5.0模块、I2C传感器模块,并提供标准的SPI和I2C接口拓展,以及完全引出的P0口。这些特性使得该核心板具有很高的通用性和可玩性,可以应用于各种嵌入式应用场景。
2. 需求分析
基于核心板的特性,我们可以初步分析出以下潜在的应用需求:
- 智能家居控制: 利用BLE5.0进行无线连接,控制家电设备;通过I2C传感器模块采集环境数据(如温湿度、光照等);使用RGB LED和板载LED进行状态指示和用户交互。
- 工业自动化: 利用SPI和I2C接口扩展连接各种工业传感器和执行器;通过UART或CAN总线进行数据通信;实现数据采集、处理和控制功能。
- 物联网设备: 利用BLE5.0进行低功耗无线通信,连接云平台;采集传感器数据并上传;接收云端指令并执行。
- 教育和开发平台: 核心板本身可以作为一个学习和开发的平台,方便用户学习嵌入式系统开发技术,进行各种创新实验。
3. 系统功能模块划分
为了构建一个模块化、可扩展的系统平台,我们将系统功能划分为以下几个主要模块:
- 硬件抽象层 (HAL - Hardware Abstraction Layer): 负责直接操作硬件外设,向上层提供统一的硬件接口。包括GPIO、定时器、UART、SPI、I2C、ADC、PWM、BLE等驱动。
- 板级支持包 (BSP - Board Support Package): 针对具体的开发板硬件配置进行初始化和配置,包括时钟配置、GPIO引脚配置、外设初始化等。BSP层依赖于HAL层,并为上层提供板级硬件资源的管理和访问接口。
- 中间件层 (Middleware): 提供一些常用的软件组件和服务,例如:
- 传感器驱动框架: 统一管理和访问各种I2C传感器模块。
- RGB LED 控制库: 提供便捷的RGB LED控制接口,实现颜色、亮度等调节。
- BLE 协议栈抽象层: 简化BLE协议栈的使用,提供易于使用的API接口。
- 数据处理模块: 实现数据滤波、数据转换、数据分析等功能。
- 通信协议栈: 例如MQTT、CoAP等,用于物联网应用。
- 文件系统 (可选): 如果需要存储配置信息或数据日志,可以考虑集成轻量级文件系统。
- RTOS (可选): 对于复杂应用,可以考虑引入实时操作系统 (RTOS) 以提高系统响应性和任务管理能力。
- 应用层 (Application Layer): 实现具体的应用逻辑,例如智能家居控制应用、工业数据采集应用等。应用层调用中间件层提供的服务,并最终实现用户的功能需求。
- 测试与验证模块: 包含单元测试、集成测试、系统测试等,确保系统的可靠性和稳定性。
- 维护与升级模块: 提供固件升级机制,方便后续的功能扩展和bug修复。
代码设计架构
基于上述模块划分,我们采用分层架构作为代码设计的基础架构。分层架构的优点在于:
- 模块化: 每个层次负责不同的功能,代码结构清晰,易于理解和维护。
- 可复用性: 底层模块 (HAL、BSP、中间件) 可以被不同的应用层复用。
- 可扩展性: 可以方便地添加新的模块或功能,而不会对现有系统造成大的影响。
- 可移植性: 通过HAL层和BSP层,可以更容易地将应用移植到不同的硬件平台。
详细代码实现 (C语言)
以下代码示例将涵盖HAL层、BSP层、部分中间件层(RGB LED控制、I2C传感器驱动框架)、以及一个简单的应用层示例。我们将详细实现各个模块,并添加必要的注释和说明。
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #ifndef HAL_GPIO_H #define HAL_GPIO_H
#include <stdint.h> #include <stdbool.h>
typedef enum { GPIO_PORT_P0, GPIO_PORT_P1, GPIO_PORT_P2, GPIO_PORT_P3, GPIO_PORT_P4, GPIO_PORT_P5, GPIO_PORT_P6, GPIO_PORT_P7 } GPIO_Port_t;
typedef uint8_t GPIO_Pin_t;
typedef enum { GPIO_DIR_INPUT, GPIO_DIR_OUTPUT } GPIO_Dir_t;
typedef enum { GPIO_OUTPUT_PP, GPIO_OUTPUT_OD } GPIO_OutputType_t;
typedef struct { GPIO_Port_t port; GPIO_Pin_t pin; GPIO_Dir_t direction; GPIO_OutputType_t output_type; } GPIO_InitTypeDef_t;
void HAL_GPIO_Init(GPIO_InitTypeDef_t *GPIO_InitStruct);
void HAL_GPIO_WritePin(GPIO_Port_t port, GPIO_Pin_t pin, bool PinState);
bool HAL_GPIO_ReadPin(GPIO_Port_t port, GPIO_Pin_t pin);
void HAL_GPIO_TogglePin(GPIO_Port_t port, GPIO_Pin_t 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 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
| #include "hal_gpio.h" #include "stc32g_registers.h"
#define P0_BASE (0x80) #define P1_BASE (0x90) #define P2_BASE (0xA0) #define P3_BASE (0xB0) #define P4_BASE (0xC0) #define P5_BASE (0xD0) #define P6_BASE (0xE0) #define P7_BASE (0xF0)
static volatile uint8_t *Get_GPIO_PortReg(GPIO_Port_t port) { switch (port) { case GPIO_PORT_P0: return (volatile uint8_t *)P0_BASE; case GPIO_PORT_P1: return (volatile uint8_t *)P1_BASE; case GPIO_PORT_P2: return (volatile uint8_t *)P2_BASE; case GPIO_PORT_P3: return (volatile uint8_t *)P3_BASE; case GPIO_PORT_P4: return (volatile uint8_t *)P4_BASE; case GPIO_PORT_P5: return (volatile uint8_t *)P5_BASE; case GPIO_PORT_P6: return (volatile uint8_t *)P6_BASE; case GPIO_PORT_P7: return (volatile uint8_t *)P7_BASE; default: return NULL; } }
void HAL_GPIO_Init(GPIO_InitTypeDef_t *GPIO_InitStruct) { volatile uint8_t *portReg = Get_GPIO_PortReg(GPIO_InitStruct->port); if (portReg == NULL) { return; }
if (GPIO_InitStruct->direction == GPIO_DIR_OUTPUT) { } else { }
if (GPIO_InitStruct->direction == GPIO_DIR_OUTPUT) { if (GPIO_InitStruct->output_type == GPIO_OUTPUT_OD) { } else { } } }
void HAL_GPIO_WritePin(GPIO_Port_t port, GPIO_Pin_t pin, bool PinState) { volatile uint8_t *portReg = Get_GPIO_PortReg(port); if (portReg == NULL) { return; }
if (PinState) { *portReg |= (1 << pin); } else { *portReg &= ~(1 << pin); } }
bool HAL_GPIO_ReadPin(GPIO_Port_t port, GPIO_Pin_t pin) { volatile uint8_t *portReg = Get_GPIO_PortReg(port); if (portReg == NULL) { return false; } return ((*portReg) & (1 << pin)) ? true : false; }
void HAL_GPIO_TogglePin(GPIO_Port_t port, GPIO_Pin_t pin) { volatile uint8_t *portReg = Get_GPIO_PortReg(port); if (portReg == NULL) { return; } *portReg ^= (1 << pin); }
|
hal_timer.h
(定时器 HAL 示例,可以根据 STC32G12K128 的定时器资源进行扩展)
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
| #ifndef HAL_TIMER_H #define HAL_TIMER_H
#include <stdint.h>
typedef enum { TIMER_0, TIMER_1, TIMER_2, TIMER_MAX } TIMER_Number_t;
typedef enum { TIMER_MODE_16BIT_AUTO_RELOAD, TIMER_MODE_8BIT_AUTO_RELOAD, TIMER_MODE_COUNTER } TIMER_Mode_t;
typedef enum { TIMER_CLK_INTERNAL, TIMER_CLK_EXTERNAL } TIMER_ClockSource_t;
typedef struct { TIMER_Number_t timer_num; TIMER_Mode_t mode; TIMER_ClockSource_t clock_source; uint16_t prescaler; uint16_t reload_value; void (*callback)(void); } TIMER_InitTypeDef_t;
void HAL_TIMER_Init(TIMER_InitTypeDef_t *TIMER_InitStruct);
void HAL_TIMER_Start(TIMER_Number_t timer_num);
void HAL_TIMER_Stop(TIMER_Number_t timer_num);
uint16_t HAL_TIMER_GetCounter(TIMER_Number_t timer_num);
void HAL_TIMER_SetReloadValue(TIMER_Number_t timer_num, uint16_t reload_value);
void HAL_TIMER_EnableInterrupt(TIMER_Number_t timer_num, bool enable);
void HAL_TIMER_IRQHandler(TIMER_Number_t timer_num);
#endif
|
hal_timer.c
(定时器 HAL 实现示例,需要根据 STC32G12K128 数据手册详细实现)
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
| #include "hal_timer.h" #include "stc32g_registers.h"
static void (*timer_callback_func[TIMER_MAX])(void) = {NULL};
void HAL_TIMER_Init(TIMER_InitTypeDef_t *TIMER_InitStruct) {
timer_callback_func[TIMER_InitStruct->timer_num] = TIMER_InitStruct->callback;
if (TIMER_InitStruct->callback != NULL) { HAL_TIMER_EnableInterrupt(TIMER_InitStruct->timer_num, true); } else { HAL_TIMER_EnableInterrupt(TIMER_InitStruct->timer_num, false); } }
void HAL_TIMER_Start(TIMER_Number_t timer_num) { }
void HAL_TIMER_Stop(TIMER_Number_t timer_num) { }
uint16_t HAL_TIMER_GetCounter(TIMER_Number_t timer_num) { return 0; }
void HAL_TIMER_SetReloadValue(TIMER_Number_t timer_num, uint16_t reload_value) { }
void HAL_TIMER_EnableInterrupt(TIMER_Number_t timer_num, bool enable) { if (enable) { } else { } }
void HAL_TIMER_IRQHandler(TIMER_Number_t timer_num) {
if (timer_callback_func[timer_num] != NULL) { timer_callback_func[timer_num](); } }
|
… (HAL 层 其他模块: hal_uart.h
, hal_uart.c
, hal_spi.h
, hal_spi.c
, hal_i2c.h
, hal_i2c.c
, hal_adc.h
, hal_adc.c
, hal_pwm.h
, hal_pwm.c
, hal_ble.h
, hal_ble.c
… 这些模块的实现方式与 GPIO 和 Timer 类似,都需要根据 STC32G12K128 的数据手册进行寄存器操作和配置。这里省略详细代码,只提供框架)
2. BSP层 (Board Support Package)
bsp.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
| #ifndef BSP_H #define BSP_H
#include "hal_gpio.h" #include "hal_timer.h"
#define BSP_LED_RED_PORT GPIO_PORT_P1 #define BSP_LED_RED_PIN GPIO_PIN_0 #define BSP_LED_GREEN_PORT GPIO_PORT_P1 #define BSP_LED_GREEN_PIN GPIO_PIN_1 #define BSP_LED_BLUE_PORT GPIO_PORT_P1 #define BSP_LED_BLUE_PIN GPIO_PIN_2
#define BSP_RGB_LED_R_PORT GPIO_PORT_P2 #define BSP_RGB_LED_R_PIN GPIO_PIN_0 #define BSP_RGB_LED_G_PORT GPIO_PORT_P2 #define BSP_RGB_LED_G_PIN GPIO_PIN_1 #define BSP_RGB_LED_B_PORT GPIO_PORT_P2 #define BSP_RGB_LED_B_PIN GPIO_PIN_2
#define BSP_BUTTON_1_PORT GPIO_PORT_P3 #define BSP_BUTTON_1_PIN GPIO_PIN_0 #define BSP_BUTTON_2_PORT GPIO_PORT_P3 #define BSP_BUTTON_2_PIN GPIO_PIN_1 #define BSP_BUTTON_3_PORT GPIO_PORT_P3 #define BSP_BUTTON_3_PIN GPIO_PIN_2
#define BSP_I2C_SCL_PORT GPIO_PORT_P4 #define BSP_I2C_SCL_PIN GPIO_PIN_0 #define BSP_I2C_SDA_PORT GPIO_PORT_P4 #define BSP_I2C_SDA_PIN GPIO_PIN_1
#define BSP_SPI_SCK_PORT GPIO_PORT_P5 #define BSP_SPI_SCK_PIN GPIO_PIN_0 #define BSP_SPI_MISO_PORT GPIO_PORT_P5 #define BSP_SPI_MISO_PIN GPIO_PIN_1 #define BSP_SPI_MOSI_PORT GPIO_PORT_P5 #define BSP_SPI_MOSI_PIN GPIO_PIN_2 #define BSP_SPI_CS_PORT GPIO_PORT_P5 #define BSP_SPI_CS_PIN GPIO_PIN_3
void BSP_Init(void);
void BSP_LED_Red_On(void); void BSP_LED_Red_Off(void); void BSP_LED_Red_Toggle(void); void BSP_LED_Green_On(void); void BSP_LED_Green_Off(void); void BSP_LED_Green_Toggle(void); void BSP_LED_Blue_On(void); void BSP_LED_Blue_Off(void); void BSP_LED_Blue_Toggle(void);
void BSP_RGB_LED_Red_On(void); void BSP_RGB_LED_Red_Off(void); void BSP_RGB_LED_Green_On(void); void BSP_RGB_LED_Green_Off(void); void BSP_RGB_LED_Blue_On(void); void BSP_RGB_LED_Blue_Off(void);
bool BSP_Button1_GetState(void); bool BSP_Button2_GetState(void); bool BSP_Button3_GetState(void);
#endif
|
bsp.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
| #include "bsp.h"
void BSP_Init(void) {
GPIO_InitTypeDef_t GPIO_InitStruct;
GPIO_InitStruct.direction = GPIO_DIR_OUTPUT; GPIO_InitStruct.output_type = GPIO_OUTPUT_PP;
GPIO_InitStruct.port = BSP_LED_RED_PORT; GPIO_InitStruct.pin = BSP_LED_RED_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_LED_RED_PORT, BSP_LED_RED_PIN, false);
GPIO_InitStruct.port = BSP_LED_GREEN_PORT; GPIO_InitStruct.pin = BSP_LED_GREEN_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_LED_GREEN_PORT, BSP_LED_GREEN_PIN, false);
GPIO_InitStruct.port = BSP_LED_BLUE_PORT; GPIO_InitStruct.pin = BSP_LED_BLUE_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_LED_BLUE_PORT, BSP_LED_BLUE_PIN, false);
GPIO_InitStruct.port = BSP_RGB_LED_R_PORT; GPIO_InitStruct.pin = BSP_RGB_LED_R_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_RGB_LED_R_PORT, BSP_RGB_LED_R_PIN, false);
GPIO_InitStruct.port = BSP_RGB_LED_G_PORT; GPIO_InitStruct.pin = BSP_RGB_LED_G_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_RGB_LED_G_PORT, BSP_RGB_LED_G_PIN, false);
GPIO_InitStruct.port = BSP_RGB_LED_B_PORT; GPIO_InitStruct.pin = BSP_RGB_LED_B_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_RGB_LED_B_PORT, BSP_RGB_LED_B_PIN, false);
GPIO_InitStruct.direction = GPIO_DIR_INPUT;
GPIO_InitStruct.port = BSP_BUTTON_1_PORT; GPIO_InitStruct.pin = BSP_BUTTON_1_PIN; HAL_GPIO_Init(&GPIO_InitStruct);
GPIO_InitStruct.port = BSP_BUTTON_2_PORT; GPIO_InitStruct.pin = BSP_BUTTON_2_PIN; HAL_GPIO_Init(&GPIO_InitStruct);
GPIO_InitStruct.port = BSP_BUTTON_3_PORT; GPIO_InitStruct.pin = BSP_BUTTON_3_PIN; HAL_GPIO_Init(&GPIO_InitStruct);
GPIO_InitStruct.direction = GPIO_DIR_OUTPUT; GPIO_InitStruct.output_type = GPIO_OUTPUT_OD; GPIO_InitStruct.port = BSP_I2C_SCL_PORT; GPIO_InitStruct.pin = BSP_I2C_SCL_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_I2C_SCL_PORT, BSP_I2C_SCL_PIN, true);
GPIO_InitStruct.port = BSP_I2C_SDA_PORT; GPIO_InitStruct.pin = BSP_I2C_SDA_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_I2C_SDA_PORT, BSP_I2C_SDA_PIN, true);
GPIO_InitStruct.direction = GPIO_DIR_OUTPUT; GPIO_InitStruct.output_type = GPIO_OUTPUT_PP; GPIO_InitStruct.port = BSP_SPI_CS_PORT; GPIO_InitStruct.pin = BSP_SPI_CS_PIN; HAL_GPIO_Init(&GPIO_InitStruct); HAL_GPIO_WritePin(BSP_SPI_CS_PORT, BSP_SPI_CS_PIN, true);
}
void BSP_LED_Red_On(void) { HAL_GPIO_WritePin(BSP_LED_RED_PORT, BSP_LED_RED_PIN, true); } void BSP_LED_Red_Off(void) { HAL_GPIO_WritePin(BSP_LED_RED_PORT, BSP_LED_RED_PIN, false); } void BSP_LED_Red_Toggle(void){ HAL_GPIO_TogglePin(BSP_LED_RED_PORT, BSP_LED_RED_PIN); } void BSP_LED_Green_On(void) { HAL_GPIO_WritePin(BSP_LED_GREEN_PORT, BSP_LED_GREEN_PIN, true); } void BSP_LED_Green_Off(void){ HAL_GPIO_WritePin(BSP_LED_GREEN_PORT, BSP_LED_GREEN_PIN, false); } void BSP_LED_Green_Toggle(void){ HAL_GPIO_TogglePin(BSP_LED_GREEN_PORT, BSP_LED_GREEN_PIN); } void BSP_LED_Blue_On(void) { HAL_GPIO_WritePin(BSP_LED_BLUE_PORT, BSP_LED_BLUE_PIN, true); } void BSP_LED_Blue_Off(void) { HAL_GPIO_WritePin(BSP_LED_BLUE_PORT, BSP_LED_BLUE_PIN, false); } void BSP_LED_Blue_Toggle(void){ HAL_GPIO_TogglePin(BSP_LED_BLUE_PORT, BSP_LED_BLUE_PIN); }
void BSP_RGB_LED_Red_On(void) { HAL_GPIO_WritePin(BSP_RGB_LED_R_PORT, BSP_RGB_LED_R_PIN, true); } void BSP_RGB_LED_Red_Off(void) { HAL_GPIO_WritePin(BSP_RGB_LED_R_PORT, BSP_RGB_LED_R_PIN, false); } void BSP_RGB_LED_Green_On(void) { HAL_GPIO_WritePin(BSP_RGB_LED_G_PORT, BSP_RGB_LED_G_PIN, true); } void BSP_RGB_LED_Green_Off(void){ HAL_GPIO_WritePin(BSP_RGB_LED_G_PORT, BSP_RGB_LED_G_PIN, false); } void BSP_RGB_LED_Blue_On(void) { HAL_GPIO_WritePin(BSP_RGB_LED_B_PORT, BSP_RGB_LED_B_PIN, true); } void BSP_RGB_LED_Blue_Off(void) { HAL_GPIO_WritePin(BSP_RGB_LED_B_PORT, BSP_RGB_LED_B_PIN, false); }
bool BSP_Button1_GetState(void) { return HAL_GPIO_ReadPin(BSP_BUTTON_1_PORT, BSP_BUTTON_1_PIN); } bool BSP_Button2_GetState(void) { return HAL_GPIO_ReadPin(BSP_BUTTON_2_PORT, BSP_BUTTON_2_PIN); } bool BSP_Button3_GetState(void) { return HAL_GPIO_ReadPin(BSP_BUTTON_3_PORT, BSP_BUTTON_3_PIN); }
|
3. 中间件层 (Middleware)
middleware_rgb_led.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
| #ifndef MIDDLEWARE_RGB_LED_H #define MIDDLEWARE_RGB_LED_H
#include "bsp.h"
typedef enum { RGB_COLOR_BLACK, RGB_COLOR_RED, RGB_COLOR_GREEN, RGB_COLOR_BLUE, RGB_COLOR_YELLOW, RGB_COLOR_CYAN, RGB_COLOR_MAGENTA, RGB_COLOR_WHITE } RGB_Color_t;
void RGB_LED_SetColor(RGB_Color_t color);
#endif
|
middleware_rgb_led.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
| #include "middleware_rgb_led.h"
void RGB_LED_SetColor(RGB_Color_t color) { switch (color) { case RGB_COLOR_BLACK: BSP_RGB_LED_Red_Off(); BSP_RGB_LED_Green_Off(); BSP_RGB_LED_Blue_Off(); break; case RGB_COLOR_RED: BSP_RGB_LED_Red_On(); BSP_RGB_LED_Green_Off(); BSP_RGB_LED_Blue_Off(); break; case RGB_COLOR_GREEN: BSP_RGB_LED_Red_Off(); BSP_RGB_LED_Green_On(); BSP_RGB_LED_Blue_Off(); break; case RGB_COLOR_BLUE: BSP_RGB_LED_Red_Off(); BSP_RGB_LED_Green_Off(); BSP_RGB_LED_Blue_On(); break; case RGB_COLOR_YELLOW: BSP_RGB_LED_Red_On(); BSP_RGB_LED_Green_On(); BSP_RGB_LED_Blue_Off(); break; case RGB_COLOR_CYAN: BSP_RGB_LED_Red_Off(); BSP_RGB_LED_Green_On(); BSP_RGB_LED_Blue_On(); break; case RGB_COLOR_MAGENTA: BSP_RGB_LED_Red_On(); BSP_RGB_LED_Green_Off(); BSP_RGB_LED_Blue_On(); break; case RGB_COLOR_WHITE: BSP_RGB_LED_Red_On(); BSP_RGB_LED_Green_On(); BSP_RGB_LED_Blue_On(); break; default: RGB_LED_SetColor(RGB_COLOR_BLACK); break; } }
|
middleware_sensor_framework.h
(I2C 传感器驱动框架示例)
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
| #ifndef MIDDLEWARE_SENSOR_FRAMEWORK_H #define MIDDLEWARE_SENSOR_FRAMEWORK_H
#include <stdint.h> #include <stdbool.h>
typedef enum { SENSOR_INTERFACE_I2C, SENSOR_INTERFACE_SPI, SENSOR_INTERFACE_MAX } Sensor_InterfaceType_t;
typedef struct SensorDriver { Sensor_InterfaceType_t interface_type; const char* name; bool (*init)(void); bool (*read_data)(void *data); } SensorDriver_t;
bool SensorFramework_RegisterDriver(SensorDriver_t *driver);
SensorDriver_t* SensorFramework_GetDriver(const char *name);
bool SensorFramework_InitAllSensors(void);
bool SensorFramework_ReadSensorData(const char *name, void *data);
#endif
|
middleware_sensor_framework.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
| #include "middleware_sensor_framework.h" #include <string.h>
#define MAX_SENSOR_DRIVERS 10
static SensorDriver_t *registered_drivers[MAX_SENSOR_DRIVERS] = {NULL}; static uint8_t driver_count = 0;
bool SensorFramework_RegisterDriver(SensorDriver_t *driver) { if (driver_count >= MAX_SENSOR_DRIVERS || driver == NULL || driver->name == NULL || driver->init == NULL || driver->read_data == NULL) { return false; }
registered_drivers[driver_count++] = driver; return true; }
SensorDriver_t* SensorFramework_GetDriver(const char *name) { if (name == NULL) { return NULL; } for (uint8_t i = 0; i < driver_count; i++) { if (registered_drivers[i] != NULL && strcmp(registered_drivers[i]->name, name) == 0) { return registered_drivers[i]; } } return NULL; }
bool SensorFramework_InitAllSensors(void) { bool result = true; for (uint8_t i = 0; i < driver_count; i++) { if (registered_drivers[i] != NULL && registered_drivers[i]->init != NULL) { if (!registered_drivers[i]->init()) { result = false; } } } return result; }
bool SensorFramework_ReadSensorData(const char *name, void *data) { SensorDriver_t *driver = SensorFramework_GetDriver(name); if (driver != NULL && driver->read_data != NULL) { return driver->read_data(data); } return false; }
|
middleware_i2c_sensor_bh1750.h
(BH1750 光照传感器驱动示例)
1 2 3 4 5 6 7 8 9
| #ifndef MIDDLEWARE_I2C_SENSOR_BH1750_H #define MIDDLEWARE_I2C_SENSOR_BH1750_H
#include "middleware_sensor_framework.h"
extern SensorDriver_t BH1750_Driver;
#endif
|
middleware_i2c_sensor_bh1750.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
| #include "middleware_i2c_sensor_bh1750.h" #include "hal_i2c.h" #include "bsp.h"
#define BH1750_ADDR (0x23) #define BH1750_CMD_POWER_ON (0x01) #define BH1750_CMD_POWER_DOWN(0x00) #define BH1750_CMD_CONT_H_RES_MODE (0x10)
static bool BH1750_Init_Func(void) {
uint8_t power_on_cmd = BH1750_CMD_POWER_ON; if (!HAL_I2C_Master_Transmit(BSP_I2C_SCL_PORT, BSP_I2C_SDA_PORT, BH1750_ADDR << 1, &power_on_cmd, 1, 100)) { return false; }
uint8_t mode_cmd = BH1750_CMD_CONT_H_RES_MODE; if (!HAL_I2C_Master_Transmit(BSP_I2C_SCL_PORT, BSP_I2C_SDA_PORT, BH1750_ADDR << 1, &mode_cmd, 1, 100)) { return false; }
return true; }
static bool BH1750_ReadData_Func(void *data) { uint8_t rx_data[2]; if (!HAL_I2C_Master_Receive(BSP_I2C_SCL_PORT, BSP_I2C_SDA_PORT, BH1750_ADDR << 1, rx_data, 2, 100)) { return false; }
uint16_t lux_value = (rx_data[0] << 8) | rx_data[1]; *(uint16_t *)data = lux_value;
return true; }
SensorDriver_t BH1750_Driver = { .interface_type = SENSOR_INTERFACE_I2C, .name = "BH1750", .init = BH1750_Init_Func, .read_data = BH1750_ReadData_Func };
|
… (中间件层 其他模块: BLE 协议栈抽象层, 数据处理模块, 通信协议栈, 文件系统, RTOS 抽象层 等,根据项目需求和核心板特性进行扩展和实现。例如 BLE 模块可以使用 STC 提供的 BLE SDK 或其他开源 BLE 协议栈进行封装和抽象。RTOS 可以选择 FreeRTOS 或其他轻量级 RTOS,并进行 OSAL 封装)
4. 应用层 (Application Layer)
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
| #include "bsp.h" #include "middleware_rgb_led.h" #include "middleware_sensor_framework.h" #include "middleware_i2c_sensor_bh1750.h" #include "hal_delay.h"
int main() { BSP_Init();
SensorFramework_RegisterDriver(&BH1750_Driver);
if (!SensorFramework_InitAllSensors()) { BSP_LED_Red_On(); while(1); }
uint16_t lux_value = 0;
while (1) { if (SensorFramework_ReadSensorData("BH1750", &lux_value)) { if (lux_value < 50) { RGB_LED_SetColor(RGB_COLOR_BLUE); } else if (lux_value < 200) { RGB_LED_SetColor(RGB_COLOR_GREEN); } else { RGB_LED_SetColor(RGB_COLOR_WHITE); }
} else { RGB_LED_SetColor(RGB_COLOR_RED); HAL_Delay_ms(500); RGB_LED_SetColor(RGB_COLOR_BLACK); HAL_Delay_ms(500); }
HAL_Delay_ms(1000); }
return 0; }
|
5. 测试与验证模块 (概念描述)
- 单元测试: 针对HAL层和中间件层的各个模块进行单元测试,例如GPIO驱动单元测试、定时器驱动单元测试、RGB LED控制库单元测试、传感器驱动框架单元测试等。可以使用C语言的单元测试框架 (例如 CMocka, Unity) 或手动编写测试用例。
- 集成测试: 将HAL层、BSP层和中间件层集成起来进行测试,验证模块之间的接口和协作是否正常工作。例如测试 RGB LED 控制和按键输入的联动、传感器数据采集和处理流程等。
- 系统测试: 进行完整的系统功能测试和性能测试,验证系统是否满足需求规格书的要求。例如长时间运行测试系统的稳定性、压力测试系统的性能极限、功能测试验证所有功能是否正常工作等。
- 测试驱动开发 (TDD - Test-Driven Development): 在开发过程中,可以采用测试驱动开发方法,先编写测试用例,然后根据测试用例编写代码,确保代码的正确性和可靠性。
6. 维护与升级模块 (概念描述)
- 固件升级机制: 设计可靠的固件升级机制,例如 OTA (Over-The-Air) 无线升级或通过 UART/USB 等接口进行本地升级。升级过程需要考虑安全性、完整性和容错性。
- 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便代码的版本管理、协作开发和bug修复。
- 日志记录和错误报告: 在系统中集成日志记录功能,记录系统运行状态、错误信息等,方便问题排查和分析。可以考虑将日志信息通过 UART 或 BLE 等接口输出到上位机进行查看。
- 模块化设计和可配置性: 采用模块化设计,方便后续的功能扩展和维护。提供配置接口,允许用户根据需求配置系统参数和功能。
项目中采用的技术和方法
- 分层架构: 将系统划分为HAL层、BSP层、中间件层、应用层,提高代码模块化、可复用性、可扩展性和可维护性。
- 硬件抽象层 (HAL): 隔离硬件差异,提供统一的硬件接口,提高代码的可移植性。
- 板级支持包 (BSP): 针对具体硬件平台进行初始化和配置,简化应用层开发。
- 驱动框架: 例如传感器驱动框架,统一管理和访问各种传感器设备,提高驱动的复用性和可扩展性。
- 模块化设计: 将系统功能分解为独立的模块,降低模块之间的耦合度,提高代码的可维护性和可测试性。
- 事件驱动或任务调度 (RTOS 可选): 根据应用复杂程度选择是否引入 RTOS,提高系统的响应性和任务管理能力。
- 代码注释和文档: 编写清晰的代码注释和文档,提高代码的可读性和可维护性。
- 版本控制: 使用 Git 等版本控制系统管理代码,方便代码版本管理和协作开发。
- 测试驱动开发 (TDD - 可选): 采用 TDD 方法进行开发,提高代码的质量和可靠性。
总结
以上代码示例和架构设计方案,旨在为基于STC32G12K128核心开发板的嵌入式项目提供一个可靠、高效、可扩展的系统平台基础。代码涵盖了HAL层、BSP层、部分中间件层以及一个简单的应用层示例,展示了分层架构、硬件抽象、驱动框架等关键技术和方法在嵌入式系统开发中的应用。
需要强调的是,这只是一个基础框架和示例代码,实际项目开发中还需要根据具体的需求进行深入的分析、设计和实现。 例如,对于更复杂的功能,需要扩展中间件层的功能模块 (BLE 协议栈、通信协议栈、数据处理算法等);对于资源受限的嵌入式系统,需要考虑代码的优化和资源管理;对于高可靠性要求的系统,需要加强错误处理和容错机制的设计。
希望这份详细的解答和代码示例能够帮助您理解嵌入式系统开发流程和代码架构设计,并为您的项目开发提供有益的参考。 请根据您的实际硬件环境和需求,对代码进行相应的调整和完善。