编程技术分享

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

0%

简介:基于STC32G12K128-35I-LQFP64的核心开发板,一款通用性很强的核心板,板载RGB/LED/BLE5.0、IIC传感器模块,标准SPI接口和IIC接口拓展,P0口完全引出。可玩性强!

我将针对您提供的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>

// GPIO 端口定义 (根据 STC32G12K128 数据手册定义)
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;

// GPIO 引脚定义 (0-7)
typedef uint8_t GPIO_Pin_t;

// GPIO 方向定义
typedef enum {
GPIO_DIR_INPUT,
GPIO_DIR_OUTPUT
} GPIO_Dir_t;

// GPIO 输出类型定义 (例如 推挽输出、开漏输出等,根据 STC32G12K128 支持的类型定义)
typedef enum {
GPIO_OUTPUT_PP, // 推挽输出
GPIO_OUTPUT_OD // 开漏输出
// ... 其他输出类型
} GPIO_OutputType_t;

// GPIO 初始化结构体
typedef struct {
GPIO_Port_t port; // GPIO 端口
GPIO_Pin_t pin; // GPIO 引脚
GPIO_Dir_t direction; // GPIO 方向
GPIO_OutputType_t output_type; // GPIO 输出类型 (仅输出模式有效)
} GPIO_InitTypeDef_t;

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

// 设置 GPIO 输出电平
void HAL_GPIO_WritePin(GPIO_Port_t port, GPIO_Pin_t pin, bool PinState);

// 读取 GPIO 输入电平
bool HAL_GPIO_ReadPin(GPIO_Port_t port, GPIO_Pin_t pin);

// 切换 GPIO 输出电平
void HAL_GPIO_TogglePin(GPIO_Port_t port, GPIO_Pin_t 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
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" // 假设定义了 STC32G12K128 的寄存器定义

// GPIO 端口寄存器基地址 (根据 STC32G12K128 数据手册定义)
#define P0_BASE (0x80) // 假设 P0 端口基地址为 0x80, 需要根据实际数据手册修改
#define P1_BASE (0x90) // 假设 P1 端口基地址为 0x90, 需要根据实际数据手册修改
#define P2_BASE (0xA0) // 假设 P2 端口基地址为 0xA0, 需要根据实际数据手册修改
#define P3_BASE (0xB0) // 假设 P3 端口基地址为 0xB0, 需要根据实际数据手册修改
#define P4_BASE (0xC0) // 假设 P4 端口基地址为 0xC0, 需要根据实际数据手册修改
#define P5_BASE (0xD0) // 假设 P5 端口基地址为 0xD0, 需要根据实际数据手册修改
#define P6_BASE (0xE0) // 假设 P6 端口基地址为 0xE0, 需要根据实际数据手册修改
#define P7_BASE (0xF0) // 假设 P7 端口基地址为 0xF0, 需要根据实际数据手册修改

// 获取 GPIO 端口寄存器地址
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; // 错误处理
}
}

// 初始化 GPIO
void HAL_GPIO_Init(GPIO_InitTypeDef_t *GPIO_InitStruct) {
volatile uint8_t *portReg = Get_GPIO_PortReg(GPIO_InitStruct->port);
if (portReg == NULL) {
// 错误处理,例如打印错误信息或返回错误码
return;
}

// 配置 GPIO 方向 (假设 DDIR 寄存器控制方向,具体寄存器名称和位操作需要查阅数据手册)
if (GPIO_InitStruct->direction == GPIO_DIR_OUTPUT) {
// 设置为输出
// 例如: *DDIR_Reg(GPIO_InitStruct->port) |= (1 << GPIO_InitStruct->pin); // 假设 DDIR_Reg(port) 返回方向寄存器地址
// 具体代码需要根据 STC32G12K128 数据手册实现
} else {
// 设置为输入
// 例如: *DDIR_Reg(GPIO_InitStruct->port) &= ~(1 << GPIO_InitStruct->pin);
}

// 配置 GPIO 输出类型 (例如 推挽/开漏,具体寄存器和位操作需要查阅数据手册)
if (GPIO_InitStruct->direction == GPIO_DIR_OUTPUT) {
if (GPIO_InitStruct->output_type == GPIO_OUTPUT_OD) {
// 设置为开漏输出
// 例如: *OTYPE_Reg(GPIO_InitStruct->port) |= (1 << GPIO_InitStruct->pin); // 假设 OTYPE_Reg(port) 返回输出类型寄存器地址
} else {
// 设置为推挽输出 (默认)
// 例如: *OTYPE_Reg(GPIO_InitStruct->port) &= ~(1 << GPIO_InitStruct->pin);
}
}
}

// 设置 GPIO 输出电平
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);
}
}

// 读取 GPIO 输入电平
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; // 读取引脚状态
}

// 切换 GPIO 输出电平
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>

// 定时器编号定义 (根据 STC32G12K128 数据手册定义)
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;

// 定时器时钟源定义 (根据 STC32G12K128 数据手册定义)
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_H

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" // 假设定义了 STC32G12K128 的寄存器定义

// 定时器寄存器基地址 (需要根据 STC32G12K128 数据手册定义)
// 例如:
//#define TIMER0_BASE (0x...)
//#define TIMER1_BASE (0x...)
//#define TIMER2_BASE (0x...)

// 定时器中断向量号 (需要根据 STC32G12K128 中断向量表定义)
// 例如:
//#define TIMER0_IRQn (...)
//#define TIMER1_IRQn (...)
//#define TIMER2_IRQn (...)

// 定时器回调函数指针数组
static void (*timer_callback_func[TIMER_MAX])(void) = {NULL};

// 初始化定时器
void HAL_TIMER_Init(TIMER_InitTypeDef_t *TIMER_InitStruct) {
// 获取定时器寄存器基地址 (根据 timer_num 选择)
// volatile uint8_t *timerRegBase = Get_TIMER_RegBase(TIMER_InitStruct->timer_num);

// 配置定时器模式 (例如 16位自动重载、8位自动重载、计数器模式等)
// ... (根据 TIMER_InitStruct->mode 配置相关寄存器)

// 配置时钟源 (内部/外部)
// ... (根据 TIMER_InitStruct->clock_source 配置相关寄存器)

// 配置预分频器
// ... (根据 TIMER_InitStruct->prescaler 配置相关寄存器)

// 设置重载值
// ... (根据 TIMER_InitStruct->reload_value 配置相关寄存器)

// 设置中断回调函数
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) {
// 使能 NVIC 中断 (需要根据 TIMER_IRQn 定义的中断向量号使能)
// 例如: NVIC_EnableIRQ(TIMER_IRQn[timer_num]); // 假设 NVIC_EnableIRQ 函数存在
} else {
// 禁用 NVIC 中断
// 例如: NVIC_DisableIRQ(TIMER_IRQn[timer_num]);
}
}

// 定时器中断处理函数 (需要在中断服务程序中调用)
void HAL_TIMER_IRQHandler(TIMER_Number_t timer_num) {
// 检查定时器中断标志位
// ... (判断是否是对应的定时器中断)
// 清除中断标志位
// ...

// 调用回调函数 (如果注册了)
if (timer_callback_func[timer_num] != NULL) {
timer_callback_func[timer_num]();
}
}

// ... (其他定时器 HAL 函数,例如 HAL_TIMER_SetPrescaler(), HAL_TIMER_SetMode() 等)

… (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"
// ... (包含其他 HAL 头文件)

// 板载 LED 定义 (根据核心板原理图确定引脚)
#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

// 板载 RGB LED 定义 (根据核心板原理图确定引脚)
#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

// I2C 接口定义 (根据核心板原理图确定引脚)
#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

// SPI 接口定义 (根据核心板原理图确定引脚)
#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

// 初始化 BSP
void BSP_Init(void);

// 板载 LED 控制
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);

// 板载 RGB LED 控制 (更高级的控制将在中间件层实现)
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);

// ... (其他 BSP 函数,例如 UART 初始化, SPI 初始化, I2C 初始化等)

#endif // BSP_H

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"

// 初始化 BSP
void BSP_Init(void) {
// 初始化时钟 (根据 STC32G12K128 的时钟系统配置,例如配置主时钟频率)
// ... (时钟配置代码,需要查阅 STC32G12K128 数据手册和时钟树)

// 初始化 GPIO
GPIO_InitTypeDef_t GPIO_InitStruct;

// 板载 LED 初始化 (输出,推挽)
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); // 默认熄灭

// 板载 RGB LED 初始化 (输出,推挽)
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);

// I2C 初始化 (作为 GPIO 输出,初始状态高电平,需要更完善的 I2C HAL 和中间件驱动)
GPIO_InitStruct.direction = GPIO_DIR_OUTPUT;
GPIO_InitStruct.output_type = GPIO_OUTPUT_OD; // 开漏输出,I2C 通常使用开漏
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); // SCL 初始高电平

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); // SDA 初始高电平

// SPI 初始化 (作为 GPIO 输出,CS 片选信号,需要更完善的 SPI HAL 和中间件驱动)
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); // CS 初始高电平 (非选中状态)

// ... (其他外设的 BSP 初始化,例如 UART, SPI, I2C, BLE 等)
}

// 板载 LED 控制函数
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); }

// 板载 RGB LED 控制函数
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); }

// ... (其他 BSP 函数实现,例如 UART 初始化, SPI 初始化, I2C 初始化等,需要根据 HAL 层提供的接口进行调用和配置)

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" // 依赖 BSP 层

// RGB LED 颜色定义
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;

// 设置 RGB LED 颜色
void RGB_LED_SetColor(RGB_Color_t color);

// 设置 RGB LED 亮度 (如果硬件支持 PWM 调光,可以添加亮度控制功能)
// void RGB_LED_SetBrightness(uint8_t brightness);

// 使用 HSV 颜色空间设置 RGB LED 颜色 (可选,更灵活的颜色控制)
// void RGB_LED_SetHSV(uint16_t hue, uint8_t saturation, uint8_t value);

#endif // MIDDLEWARE_RGB_LED_H

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"

// 设置 RGB LED 颜色
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: // Red + Green
BSP_RGB_LED_Red_On();
BSP_RGB_LED_Green_On();
BSP_RGB_LED_Blue_Off();
break;
case RGB_COLOR_CYAN: // Green + Blue
BSP_RGB_LED_Red_Off();
BSP_RGB_LED_Green_On();
BSP_RGB_LED_Blue_On();
break;
case RGB_COLOR_MAGENTA: // Red + Blue
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;
}
}

// ... (RGB_LED_SetBrightness(), RGB_LED_SetHSV() 等函数的实现,如果需要)

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); // 读取数据函数
// ... 其他通用传感器操作接口,例如 power_on, power_off, set_config 等
} 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_H

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> // for strcmp

#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"

// BH1750 传感器驱动结构体
extern SensorDriver_t BH1750_Driver;

#endif // MIDDLEWARE_I2C_SENSOR_BH1750_H

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" // 假设有 I2C HAL 驱动
#include "bsp.h" // 使用 BSP 定义的 I2C 引脚

#define BH1750_ADDR (0x23) // BH1750 I2C 地址 (7-bit)
#define BH1750_CMD_POWER_ON (0x01) // 上电命令
#define BH1750_CMD_POWER_DOWN(0x00) // 断电命令
#define BH1750_CMD_CONT_H_RES_MODE (0x10) // 连续高分辨率模式

// BH1750 初始化函数
static bool BH1750_Init_Func(void) {
// 初始化 I2C (假设 BSP_I2C_Init() 函数已在 BSP 层实现)
// BSP_I2C_Init(); // 如果 I2C 初始化需要在传感器驱动中完成,则在此处调用

// BH1750 上电
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; // 初始化成功
}

// BH1750 读取光照强度数据函数
static bool BH1750_ReadData_Func(void *data) {
uint8_t rx_data[2]; // 接收 2 字节数据 (光照强度值)
if (!HAL_I2C_Master_Receive(BSP_I2C_SCL_PORT, BSP_I2C_SDA_PORT, BH1750_ADDR << 1, rx_data, 2, 100)) { // 接收数据
return false; // 数据接收失败
}

// 数据转换 (BH1750 输出 16-bit 光照强度值,单位 Lux)
uint16_t lux_value = (rx_data[0] << 8) | rx_data[1];
*(uint16_t *)data = lux_value; // 将光照强度值写入到 data 指针指向的内存

return true; // 读取成功
}

// BH1750 传感器驱动实例
SensorDriver_t BH1750_Driver = {
.interface_type = SENSOR_INTERFACE_I2C,
.name = "BH1750",
.init = BH1750_Init_Func,
.read_data = BH1750_ReadData_Func
// ... 其他驱动接口实现,例如 power_on, power_off, set_config 等
};

// 注册 BH1750 传感器驱动 (在其他地方调用,例如在 main 函数中)
// 在 main.c 中:
// #include "middleware_i2c_sensor_bh1750.h"
// SensorFramework_RegisterDriver(&BH1750_Driver);

… (中间件层 其他模块: 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" // 包含 BH1750 驱动头文件
#include "hal_delay.h" // 假设有 HAL 延时函数

int main() {
BSP_Init(); // 初始化 BSP (板级支持包)

// 注册传感器驱动
SensorFramework_RegisterDriver(&BH1750_Driver);

// 初始化所有注册的传感器
if (!SensorFramework_InitAllSensors()) {
// 传感器初始化失败处理
BSP_LED_Red_On(); // 例如红色 LED 闪烁表示错误
while(1);
}

uint16_t lux_value = 0;

while (1) {
// 读取 BH1750 光照强度数据
if (SensorFramework_ReadSensorData("BH1750", &lux_value)) {
// 数据读取成功
// 根据光照强度控制 RGB LED 颜色
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); // 光亮时白色
}

// 打印光照强度值 (需要 UART HAL 和相关配置)
// printf("Lux: %d\r\n", lux_value); // 假设 printf 可用,需要配置 UART
} 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); // 1秒采样一次
}

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 协议栈、通信协议栈、数据处理算法等);对于资源受限的嵌入式系统,需要考虑代码的优化和资源管理;对于高可靠性要求的系统,需要加强错误处理和容错机制的设计。

希望这份详细的解答和代码示例能够帮助您理解嵌入式系统开发流程和代码架构设计,并为您的项目开发提供有益的参考。 请根据您的实际硬件环境和需求,对代码进行相应的调整和完善。

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