编程技术分享

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

0%

简介:基于立创梁山派的智能小车,包含循迹,避障,蓝牙遥控功能

好的,作为一名高级嵌入式软件开发工程师,很高兴能为您详细解析基于立创梁山派智能小车的嵌入式系统开发流程和代码架构。这个项目是一个非常好的实践案例,涵盖了嵌入式系统开发的多个关键环节。我将从需求分析、系统架构设计、详细代码实现、测试验证以及维护升级等方面进行深入阐述,确保您能理解并应用到实际项目中。
关注微信公众号,提前获取相关推文

项目简介回顾:

  • 平台: 立创梁山派 (LCSC Liangshan Pai) - 这通常指的是基于某个微控制器(如ARM Cortex-M系列)的开发板,具体型号需要进一步确认,但架构设计思路是通用的。
  • 功能:
    • 循迹 (Line Following): 小车能够沿着预设的黑色轨迹线自动行驶。
    • 避障 (Obstacle Avoidance): 小车能够检测前方障碍物并自动避开。
    • 蓝牙遥控 (Bluetooth Remote Control): 通过蓝牙连接,用户可以使用手机或其他蓝牙设备遥控小车的运动。

系统开发流程概述:

一个完整的嵌入式系统开发流程通常包括以下阶段:

  1. 需求分析 (Requirements Analysis): 明确系统需要实现的功能、性能指标、环境约束等。
  2. 系统设计 (System Design): 确定硬件选型、软件架构、模块划分、接口定义等。
  3. 详细设计 (Detailed Design): 对每个软件模块进行详细设计,包括算法选择、数据结构设计、流程图绘制等。
  4. 编码实现 (Coding Implementation): 根据详细设计,编写C代码实现各个模块的功能。
  5. 单元测试 (Unit Testing): 对每个模块进行单独测试,确保其功能正确。
  6. 集成测试 (Integration Testing): 将各个模块组合起来进行测试,验证模块间的协同工作。
  7. 系统测试 (System Testing): 对整个系统进行全面测试,验证系统是否满足所有需求。
  8. 调试与优化 (Debugging and Optimization): 解决测试中发现的问题,并对系统性能进行优化。
  9. 维护与升级 (Maintenance and Upgrade): 对已部署的系统进行维护和升级,修复bug,添加新功能。

最适合的代码设计架构:分层架构 (Layered Architecture)

对于这种功能相对复杂,且需要考虑可靠性、高效性和可扩展性的嵌入式系统,分层架构是最合适的选择。分层架构将系统分解成多个层次,每个层次只关注特定的功能,并向上层提供服务,向下层请求服务。 这种架构具有以下优点:

  • 模块化 (Modularity): 每个层次和模块职责清晰,易于理解、开发、测试和维护。
  • 可重用性 (Reusability): 底层模块可以被多个上层模块复用。
  • 可扩展性 (Scalability): 可以方便地添加新的层次或模块,扩展系统功能。
  • 可移植性 (Portability): 通过硬件抽象层 (HAL) 可以提高代码在不同硬件平台之间的可移植性。
  • 易于测试 (Testability): 可以对每个层次进行独立的单元测试,降低测试难度。

针对智能小车项目,我们可以设计如下分层架构:

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
+---------------------+  <- 应用层 (Application Layer) - 负责系统整体逻辑和用户交互
| 应用逻辑模块 |
| (蓝牙遥控, 模式切换) |
+---------------------+
|
| API接口
V
+---------------------+ <- 服务层 (Service Layer) - 提供核心功能服务
| 循迹服务模块 |
| 避障服务模块 |
| 电机控制服务模块 |
| 蓝牙通信服务模块 |
+---------------------+
|
| API接口
V
+---------------------+ <- 硬件驱动层 (Hardware Driver Layer) - 驱动硬件设备
| 循迹传感器驱动 |
| 超声波传感器驱动 |
| 电机驱动模块 |
| 蓝牙模块驱动 |
| GPIO驱动 |
| 定时器驱动 |
| PWM驱动 |
| UART驱动 |
+---------------------+
|
| 硬件接口
V
+---------------------+ <- 硬件抽象层 (Hardware Abstraction Layer - HAL) - 屏蔽硬件差异
| HAL接口定义 |
| (GPIO, Timer, UART, PWM...) |
+---------------------+
|
| 硬件平台
V
+---------------------+ <- 硬件平台 (Hardware Platform) - 立创梁山派开发板及外围硬件
| 微控制器 (MCU) |
| 传感器 |
| 电机 |
| 蓝牙模块 |
| ... |
+---------------------+

各层的功能职责:

  • 硬件平台层 (Hardware Platform): 实际的硬件设备,包括微控制器、传感器、电机、蓝牙模块等。
  • 硬件抽象层 (HAL - Hardware Abstraction Layer): 提供统一的硬件接口,屏蔽不同硬件平台之间的差异。例如,GPIO的初始化、读写操作,定时器的配置,PWM的输出控制,UART的通信等。HAL层通常定义一组通用的API接口,供驱动层调用。
  • 硬件驱动层 (Hardware Driver Layer): 直接与硬件交互,驱动各种硬件设备工作。例如,读取循迹传感器的数值,控制电机转动,接收蓝牙模块的数据等。驱动层调用HAL层提供的接口来访问硬件。
  • 服务层 (Service Layer): 基于驱动层提供的硬件功能,实现核心业务逻辑。例如,循迹服务模块负责根据循迹传感器的数据控制电机,实现小车沿着轨迹线行驶;避障服务模块负责根据超声波传感器的数据判断前方是否有障碍物,并控制小车避开;电机控制服务模块提供统一的电机控制接口,供上层调用;蓝牙通信服务模块负责处理蓝牙数据的接收和发送。
  • 应用层 (Application Layer): 实现系统的整体应用逻辑和用户交互。例如,蓝牙遥控功能,模式切换功能(循迹模式、避障模式、遥控模式),以及可能的更高层级的逻辑控制。应用层调用服务层提供的API接口来完成各种功能。

代码实现 (C语言):

为了详细说明代码架构,并达到“3000行”的要求 (虽然实际代码量不一定需要这么多,但为了展示详细的设计思路和代码示例,我会尽量展开),我将分层逐步展示代码实现,并进行详细的注释和解释。

1. 硬件抽象层 (HAL - Hardware Abstraction Layer):

HAL层定义了与硬件无关的接口,例如GPIO、Timer、UART、PWM等。 这里我们假设立创梁山派使用常见的ARM Cortex-M系列MCU,并使用一些通用的HAL接口命名。 请注意,实际的HAL层代码需要根据具体的MCU型号和硬件平台进行适配。 以下代码仅为示例,展示HAL层的设计思想。

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
// HAL层头文件 (hal.h)

#ifndef __HAL_H__
#define __HAL_H__

#include <stdint.h>
#include <stdbool.h>

// GPIO HAL 定义
typedef enum {
HAL_GPIO_MODE_INPUT,
HAL_GPIO_MODE_OUTPUT
} HAL_GPIO_ModeTypeDef;

typedef enum {
HAL_GPIO_PIN_RESET,
HAL_GPIO_PIN_SET
} HAL_GPIO_PinStateTypeDef;

typedef struct {
uint32_t Pin; // GPIO引脚号
HAL_GPIO_ModeTypeDef Mode; // GPIO模式 (输入/输出)
// ... 其他GPIO配置参数,例如上拉/下拉,速度等 (根据实际需求添加)
} HAL_GPIO_InitTypeDef;

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

// 设置GPIO引脚输出状态 (高/低电平)
void HAL_GPIO_WritePin(uint32_t Pin, HAL_GPIO_PinStateTypeDef PinState);

// 读取GPIO引脚输入状态 (高/低电平)
HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(uint32_t Pin);


// 定时器 HAL 定义
typedef struct {
uint32_t TimerInstance; // 定时器实例 (例如 TIM1, TIM2, ...)
uint32_t Prescaler; // 预分频器
uint32_t Period; // 计数周期
// ... 其他定时器配置参数 (根据实际需求添加)
} HAL_Timer_InitTypeDef;

// 初始化定时器
void HAL_Timer_Init(HAL_Timer_InitTypeDef *Timer_InitStruct);

// 启动定时器
void HAL_Timer_Start(uint32_t TimerInstance);

// 停止定时器
void HAL_Timer_Stop(uint32_t TimerInstance);

// 获取当前定时器计数值
uint32_t HAL_Timer_GetCounter(uint32_t TimerInstance);

// 设置定时器回调函数 (用于中断处理)
void HAL_Timer_SetCallback(uint32_t TimerInstance, void (*callback)(void));


// PWM HAL 定义
typedef struct {
uint32_t PWMInstance; // PWM实例 (例如 PWM1, PWM2, ...)
uint32_t Channel; // PWM通道 (例如 CHANNEL_1, CHANNEL_2, ...)
uint32_t Prescaler; // 预分频器
uint32_t Period; // 计数周期
uint32_t Pulse; // 脉冲宽度 (占空比)
// ... 其他PWM配置参数 (根据实际需求添加)
} HAL_PWM_InitTypeDef;

// 初始化PWM
void HAL_PWM_Init(HAL_PWM_InitTypeDef *PWM_InitStruct);

// 启动PWM
void HAL_PWM_Start(uint32_t PWMInstance, uint32_t Channel);

// 停止PWM
void HAL_PWM_Stop(uint32_t PWMInstance, uint32_t Channel);

// 设置PWM脉冲宽度 (占空比)
void HAL_PWM_SetPulse(uint32_t PWMInstance, uint32_t Channel, uint32_t Pulse);


// UART HAL 定义
typedef struct {
uint32_t UARTInstance; // UART实例 (例如 UART1, UART2, ...)
uint32_t BaudRate; // 波特率
// ... 其他UART配置参数 (根据实际需求添加)
} HAL_UART_InitTypeDef;

// 初始化UART
void HAL_UART_Init(HAL_UART_InitTypeDef *UART_InitStruct);

// 发送一个字节数据
void HAL_UART_Transmit(uint32_t UARTInstance, uint8_t data);

// 接收一个字节数据 (阻塞等待)
uint8_t HAL_UART_Receive(uint32_t UARTInstance);

// 发送字符串
void HAL_UART_TransmitString(uint32_t UARTInstance, const char *str);

// 注册 UART 接收回调函数 (用于中断接收)
void HAL_UART_SetReceiveCallback(uint32_t UARTInstance, void (*callback)(uint8_t data));


#endif // __HAL_H__

HAL层实现 (hal.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
// HAL层实现文件 (hal.c)

#include "hal.h"

// 假设使用 STM32 系列 MCU (只是示例,需要根据实际梁山派使用的MCU修改)
#include "stm32fxxx_hal.h" // 替换为实际的 MCU HAL 库头文件

// GPIO HAL 实现
void HAL_GPIO_Init(HAL_GPIO_InitTypeDef *GPIO_InitStruct) {
GPIO_InitTypeDef GPIO_Config;
GPIO_Config.Pin = GPIO_InitStruct->Pin;
if (GPIO_InitStruct->Mode == HAL_GPIO_MODE_INPUT) {
GPIO_Config.Mode = GPIO_MODE_INPUT;
} else {
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
}
GPIO_Config.Pull = GPIO_NOPULL; // 无上下拉
GPIO_Config.Speed = GPIO_SPEED_FREQ_LOW; // 低速
HAL_GPIO_Init(GPIOA, &GPIO_Config); // 假设 GPIOA 是 GPIO_InitStruct->Pin 所属的端口,需要根据实际情况修改
}

void HAL_GPIO_WritePin(uint32_t Pin, HAL_GPIO_PinStateTypeDef PinState) {
HAL_GPIO_WritePin(GPIOA, Pin, (PinState == HAL_GPIO_PIN_SET) ? GPIO_PIN_SET : GPIO_PIN_RESET); // 假设 GPIOA,需要根据实际情况修改
}

HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(uint32_t Pin) {
return (HAL_GPIO_ReadPin(GPIOA, Pin) == GPIO_PIN_SET) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET; // 假设 GPIOA,需要根据实际情况修改
}


// 定时器 HAL 实现 (示例 - 需要根据实际 MCU 定时器外设进行配置)
void HAL_Timer_Init(HAL_Timer_InitTypeDef *Timer_InitStruct) {
TIM_HandleTypeDef TimHandle;
TimHandle.Instance = (TIM_TypeDef *)Timer_InitStruct->TimerInstance;
TimHandle.Init.Prescaler = Timer_InitStruct->Prescaler;
TimHandle.Init.Period = Timer_InitStruct->Period;
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&TimHandle); // 初始化定时器基准单元
}

void HAL_Timer_Start(uint32_t TimerInstance) {
HAL_TIM_Base_Start((TIM_HandleTypeDef *)TimerInstance);
}

void HAL_Timer_Stop(uint32_t TimerInstance) {
HAL_TIM_Base_Stop((TIM_HandleTypeDef *)TimerInstance);
}

uint32_t HAL_Timer_GetCounter(uint32_t TimerInstance) {
return HAL_TIM_Base_GetCounter((TIM_HandleTypeDef *)TimerInstance);
}

// ... (HAL_Timer_SetCallback 的实现需要涉及到中断配置,这里省略,实际项目中需要实现)


// PWM HAL 实现 (示例 - 需要根据实际 MCU PWM 外设进行配置)
void HAL_PWM_Init(HAL_PWM_InitTypeDef *PWM_InitStruct) {
TIM_HandleTypeDef TimHandle;
TIM_OC_InitTypeDef PWM_Config;

TimHandle.Instance = (TIM_TypeDef *)PWM_InitStruct->PWMInstance;
TimHandle.Init.Prescaler = PWM_InitStruct->Prescaler;
TimHandle.Init.Period = PWM_InitStruct->Period;
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(&TimHandle); // 初始化PWM定时器基准单元

PWM_Config.OCMode = TIM_OCMODE_PWM1;
PWM_Config.Pulse = PWM_InitStruct->Pulse;
PWM_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
PWM_Config.OCFastMode = TIM_OCFAST_DISABLE;
PWM_Config.OCNPolarity = TIM_OCNPOLARITY_LOW;
PWM_Config.OCNFastMode = TIM_OCNFAST_DISABLE;
PWM_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
PWM_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&TimHandle, &PWM_Config, PWM_InitStruct->Channel); // 配置PWM通道
}

void HAL_PWM_Start(uint32_t PWMInstance, uint32_t Channel) {
HAL_TIM_PWM_Start((TIM_HandleTypeDef *)PWMInstance, Channel);
}

void HAL_PWM_Stop(uint32_t PWMInstance, uint32_t Channel) {
HAL_TIM_PWM_Stop((TIM_HandleTypeDef *)PWMInstance, Channel);
}

void HAL_PWM_SetPulse(uint32_t PWMInstance, uint32_t Channel, uint32_t Pulse) {
TIM_HandleTypeDef TimHandle;
TimHandle.Instance = (TIM_TypeDef *)PWM_InitStruct->PWMInstance;
__HAL_TIM_SET_COMPARE(&TimHandle, Channel, Pulse); // 设置PWM脉冲宽度
}


// UART HAL 实现 (示例 - 需要根据实际 MCU UART 外设进行配置)
void HAL_UART_Init(HAL_UART_InitTypeDef *UART_InitStruct) {
UART_HandleTypeDef UartHandle;
UartHandle.Instance = (USART_TypeDef *)UART_InitStruct->UARTInstance;
UartHandle.Init.BaudRate = UART_InitStruct->BaudRate;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&UartHandle); // 初始化UART
}

void HAL_UART_Transmit(uint32_t UARTInstance, uint8_t data) {
HAL_UART_Transmit((UART_HandleTypeDef *)UARTInstance, &data, 1, HAL_MAX_DELAY);
}

uint8_t HAL_UART_Receive(uint32_t UARTInstance) {
uint8_t data;
HAL_UART_Receive((UART_HandleTypeDef *)UARTInstance, &data, 1, HAL_MAX_DELAY);
return data;
}

void HAL_UART_TransmitString(uint32_t UARTInstance, const char *str) {
HAL_UART_Transmit((UART_HandleTypeDef *)UARTInstance, (uint8_t *)str, strlen(str), HAL_MAX_DELAY);
}

// ... (HAL_UART_SetReceiveCallback 的实现需要涉及到中断配置,这里省略,实际项目中需要实现)

2. 硬件驱动层 (Hardware Driver Layer):

驱动层基于HAL层提供的接口,实现特定硬件设备的功能驱动。

2.1 循迹传感器驱动 (line_sensor_driver.h / .c):

假设使用多个红外反射式循迹传感器,并连接到GPIO引脚。

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
// 循迹传感器驱动头文件 (line_sensor_driver.h)
#ifndef __LINE_SENSOR_DRIVER_H__
#define __LINE_SENSOR_DRIVER_H__

#include <stdint.h>
#include <stdbool.h>
#include "hal.h" // 包含 HAL 头文件

// 循迹传感器数量 (假设使用5个)
#define LINE_SENSOR_COUNT 5

// 定义循迹传感器引脚 (需要根据实际硬件连接修改)
#define LINE_SENSOR_PIN_1 /* ... GPIO Pin 定义 ... */
#define LINE_SENSOR_PIN_2 /* ... GPIO Pin 定义 ... */
#define LINE_SENSOR_PIN_3 /* ... GPIO Pin 定义 ... */
#define LINE_SENSOR_PIN_4 /* ... GPIO Pin 定义 ... */
#define LINE_SENSOR_PIN_5 /* ... GPIO Pin 定义 ... */

// 初始化循迹传感器驱动
void LineSensor_Init(void);

// 读取所有循迹传感器状态
uint8_t LineSensor_ReadSensors(void); // 返回一个字节,每一位代表一个传感器的状态 (1: 检测到黑线, 0: 未检测到)

// 获取单个循迹传感器状态
bool LineSensor_ReadSensor(uint8_t sensor_index); // sensor_index: 0 to LINE_SENSOR_COUNT-1

#endif // __LINE_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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 循迹传感器驱动实现文件 (line_sensor_driver.c)
#include "line_sensor_driver.h"

// 循迹传感器引脚数组
static const uint32_t line_sensor_pins[LINE_SENSOR_COUNT] = {
LINE_SENSOR_PIN_1, LINE_SENSOR_PIN_2, LINE_SENSOR_PIN_3, LINE_SENSOR_PIN_4, LINE_SENSOR_PIN_5
};

// 初始化循迹传感器驱动
void LineSensor_Init(void) {
HAL_GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = HAL_GPIO_MODE_INPUT;

for (int i = 0; i < LINE_SENSOR_COUNT; i++) {
GPIO_InitStruct.Pin = line_sensor_pins[i];
HAL_GPIO_Init(&GPIO_InitStruct);
}
}

// 读取所有循迹传感器状态
uint8_t LineSensor_ReadSensors(void) {
uint8_t sensor_values = 0;
for (int i = 0; i < LINE_SENSOR_COUNT; i++) {
if (HAL_GPIO_ReadPin(line_sensor_pins[i]) == HAL_GPIO_PIN_RESET) { // 假设检测到黑线时传感器输出低电平
sensor_values |= (1 << i); // 设置对应位为 1
}
}
return sensor_values;
}

// 获取单个循迹传感器状态
bool LineSensor_ReadSensor(uint8_t sensor_index) {
if (sensor_index < LINE_SENSOR_COUNT) {
return (HAL_GPIO_ReadPin(line_sensor_pins[sensor_index]) == HAL_GPIO_PIN_RESET); // 假设检测到黑线时传感器输出低电平
} else {
return false; // 索引无效
}
}

2.2 超声波传感器驱动 (ultrasonic_sensor_driver.h / .c):

假设使用HC-SR04超声波传感器,需要一个GPIO引脚作为Trig (触发) 引脚,另一个GPIO引脚作为Echo (回响) 引脚,并使用定时器测量回响时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 超声波传感器驱动头文件 (ultrasonic_sensor_driver.h)
#ifndef __ULTRASONIC_SENSOR_DRIVER_H__
#define __ULTRASONIC_SENSOR_DRIVER_H__

#include <stdint.h>
#include <stdbool.h>
#include "hal.h" // 包含 HAL 头文件

// 定义超声波传感器引脚 (需要根据实际硬件连接修改)
#define ULTRASONIC_TRIG_PIN /* ... GPIO Pin 定义 ... */
#define ULTRASONIC_ECHO_PIN /* ... GPIO Pin 定义 ... */

// 定义定时器实例 (用于测量回响时间,需要根据实际硬件选择合适的定时器)
#define ULTRASONIC_TIMER_INSTANCE /* ... 定时器实例 定义 ... */

// 初始化超声波传感器驱动
void Ultrasonic_Init(void);

// 测量距离 (单位:厘米)
float Ultrasonic_MeasureDistance(void);

#endif // __ULTRASONIC_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
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
// 超声波传感器驱动实现文件 (ultrasonic_sensor_driver.c)
#include "ultrasonic_sensor_driver.h"

#define SOUND_SPEED_CM_US 0.0343 // 声速 (厘米/微秒)

// 初始化超声波传感器驱动
void Ultrasonic_Init(void) {
HAL_GPIO_InitTypeDef GPIO_InitStruct;

// Trig 引脚配置为输出
GPIO_InitStruct.Pin = ULTRASONIC_TRIG_PIN;
GPIO_InitStruct.Mode = HAL_GPIO_MODE_OUTPUT;
HAL_GPIO_Init(&GPIO_InitStruct);

// Echo 引脚配置为输入
GPIO_InitStruct.Pin = ULTRASONIC_ECHO_PIN;
GPIO_InitStruct.Mode = HAL_GPIO_MODE_INPUT;
HAL_GPIO_Init(&GPIO_InitStruct);

// 初始化定时器 (用于测量时间)
HAL_Timer_InitTypeDef Timer_InitStruct;
Timer_InitStruct.TimerInstance = ULTRASONIC_TIMER_INSTANCE;
Timer_InitStruct.Prescaler = 72 - 1; // 假设 MCU 主频 72MHz,预分频到 1MHz (1us 计数)
Timer_InitStruct.Period = 0xFFFF; // 最大计数周期
HAL_Timer_Init(&Timer_InitStruct);
}

// 测量距离 (单位:厘米)
float Ultrasonic_MeasureDistance(void) {
// 1. 发送触发信号 (高电平至少 10us)
HAL_GPIO_WritePin(ULTRASONIC_TRIG_PIN, HAL_GPIO_PIN_SET);
// 延时 10us (可以使用 HAL_Delay 或更精确的定时器延时)
// 假设 HAL_Delay 是毫秒级延时,需要实现微秒级延时函数,这里简化使用 HAL_Delay(1) 毫秒级延时,实际应用中需要更精确的延时
// 例如可以使用 __HAL_TIM_SET_COUNTER 和 while 循环等待
// 或者使用更精确的微秒级延时函数,例如 __delay_us() (如果 HAL 库提供)
// 这里为了代码简洁,假设 HAL_Delay(1) 足够短
HAL_Delay(1);
HAL_GPIO_WritePin(ULTRASONIC_TRIG_PIN, HAL_GPIO_PIN_RESET);

// 2. 等待 Echo 引脚变为高电平,并开始计时
while (HAL_GPIO_ReadPin(ULTRASONIC_ECHO_PIN) == HAL_GPIO_PIN_RESET);
HAL_Timer_Start(ULTRASONIC_TIMER_INSTANCE);

// 3. 等待 Echo 引脚变为低电平,停止计时
while (HAL_GPIO_ReadPin(ULTRASONIC_ECHO_PIN) == HAL_GPIO_PIN_SET);
HAL_Timer_Stop(ULTRASONIC_TIMER_INSTANCE);

// 4. 读取计时器计数值,计算距离
uint32_t echo_time_us = HAL_Timer_GetCounter(ULTRASONIC_TIMER_INSTANCE);
HAL_Timer_SetCounter(ULTRASONIC_TIMER_INSTANCE, 0); // 清零计数器

float distance_cm = (float)echo_time_us * SOUND_SPEED_CM_US / 2.0f; // 除以 2 是因为声波是往返距离

return distance_cm;
}

2.3 电机驱动模块 (motor_driver.h / .c):

假设使用L298N电机驱动模块,需要控制两个电机,每个电机需要两个GPIO引脚控制方向 (IN1, IN2, IN3, IN4) 和一个PWM引脚控制速度 (ENA, ENB)。

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
// 电机驱动模块头文件 (motor_driver.h)
#ifndef __MOTOR_DRIVER_H__
#define __MOTOR_DRIVER_H__

#include <stdint.h>
#include <stdbool.h>
#include "hal.h" // 包含 HAL 头文件

// 定义电机控制引脚 (需要根据实际硬件连接修改)
#define MOTOR_LEFT_IN1_PIN /* ... GPIO Pin 定义 ... */
#define MOTOR_LEFT_IN2_PIN /* ... GPIO Pin 定义 ... */
#define MOTOR_LEFT_ENA_PWM_INSTANCE /* ... 左电机 PWM 实例 定义 ... */
#define MOTOR_LEFT_ENA_PWM_CHANNEL /* ... 左电机 PWM 通道 定义 ... */

#define MOTOR_RIGHT_IN3_PIN /* ... GPIO Pin 定义 ... */
#define MOTOR_RIGHT_IN4_PIN /* ... GPIO Pin 定义 ... */
#define MOTOR_RIGHT_ENB_PWM_INSTANCE /* ... 右电机 PWM 实例 定义 ... */
#define MOTOR_RIGHT_ENB_PWM_CHANNEL /* ... 右电机 PWM 通道 定义 ... */

// 电机速度范围 (0-100,百分比)
#define MOTOR_SPEED_MIN 0
#define MOTOR_SPEED_MAX 100

// 初始化电机驱动模块
void Motor_Init(void);

// 控制左电机
void Motor_Left_Forward(uint8_t speed); // speed: 0-100
void Motor_Left_Backward(uint8_t speed);
void Motor_Left_Stop(void);

// 控制右电机
void Motor_Right_Forward(uint8_t speed); // speed: 0-100
void Motor_Right_Backward(uint8_t speed);
void Motor_Right_Stop(void);

// 控制两个电机
void Motor_Forward(uint8_t speed_left, uint8_t speed_right);
void Motor_Backward(uint8_t speed_left, uint8_t speed_right);
void Motor_TurnLeft(uint8_t speed);
void Motor_TurnRight(uint8_t speed);
void Motor_Stop(void);

#endif // __MOTOR_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
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
// 电机驱动模块实现文件 (motor_driver.c)
#include "motor_driver.h"

// PWM 周期 (假设 PWM 定时器计数周期为 1000,对应 0-100% 占空比)
#define PWM_PERIOD 1000

// 初始化电机驱动模块
void Motor_Init(void) {
HAL_GPIO_InitTypeDef GPIO_InitStruct;
HAL_PWM_InitTypeDef PWM_InitStruct;

// 左电机方向引脚配置为输出
GPIO_InitStruct.Mode = HAL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Pin = MOTOR_LEFT_IN1_PIN | MOTOR_LEFT_IN2_PIN;
HAL_GPIO_Init(&GPIO_InitStruct);

// 右电机方向引脚配置为输出
GPIO_InitStruct.Pin = MOTOR_RIGHT_IN3_PIN | MOTOR_RIGHT_IN4_PIN;
HAL_GPIO_Init(&GPIO_InitStruct);

// 左电机 PWM 初始化
PWM_InitStruct.PWMInstance = MOTOR_LEFT_ENA_PWM_INSTANCE;
PWM_InitStruct.Channel = MOTOR_LEFT_ENA_PWM_CHANNEL;
PWM_InitStruct.Prescaler = 72 - 1; // 假设 MCU 主频 72MHz,预分频到 1MHz
PWM_InitStruct.Period = PWM_PERIOD;
PWM_InitStruct.Pulse = 0; // 初始占空比 0%
HAL_PWM_Init(&PWM_InitStruct);
HAL_PWM_Start(MOTOR_LEFT_ENA_PWM_INSTANCE, MOTOR_LEFT_ENA_PWM_CHANNEL);

// 右电机 PWM 初始化
PWM_InitStruct.PWMInstance = MOTOR_RIGHT_ENB_PWM_INSTANCE;
PWM_InitStruct.Channel = MOTOR_RIGHT_ENB_PWM_CHANNEL;
PWM_InitStruct.Prescaler = 72 - 1;
PWM_InitStruct.Period = PWM_PERIOD;
PWM_InitStruct.Pulse = 0; // 初始占空比 0%
HAL_PWM_Init(&PWM_InitStruct);
HAL_PWM_Start(MOTOR_RIGHT_ENB_PWM_INSTANCE, MOTOR_RIGHT_ENB_CHANNEL);

Motor_Stop(); // 初始化时停止电机
}

// 设置电机速度 (PWM 占空比)
static void Motor_SetSpeed(uint32_t pwm_instance, uint32_t pwm_channel, uint8_t speed) {
if (speed > MOTOR_SPEED_MAX) speed = MOTOR_SPEED_MAX;
uint32_t pulse = (uint32_t)((float)speed / 100.0f * PWM_PERIOD); // 计算脉冲宽度
HAL_PWM_SetPulse(pwm_instance, pwm_channel, pulse);
}

// 控制左电机
void Motor_Left_Forward(uint8_t speed) {
HAL_GPIO_WritePin(MOTOR_LEFT_IN1_PIN, HAL_GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_LEFT_IN2_PIN, HAL_GPIO_PIN_RESET);
Motor_SetSpeed(MOTOR_LEFT_ENA_PWM_INSTANCE, MOTOR_LEFT_ENA_PWM_CHANNEL, speed);
}

void Motor_Left_Backward(uint8_t speed) {
HAL_GPIO_WritePin(MOTOR_LEFT_IN1_PIN, HAL_GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_LEFT_IN2_PIN, HAL_GPIO_PIN_SET);
Motor_SetSpeed(MOTOR_LEFT_ENA_PWM_INSTANCE, MOTOR_LEFT_ENA_PWM_CHANNEL, speed);
}

void Motor_Left_Stop(void) {
HAL_GPIO_WritePin(MOTOR_LEFT_IN1_PIN, HAL_GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_LEFT_IN2_PIN, HAL_GPIO_PIN_RESET);
Motor_SetSpeed(MOTOR_LEFT_ENA_PWM_INSTANCE, MOTOR_LEFT_ENA_PWM_CHANNEL, 0);
}

// 控制右电机
void Motor_Right_Forward(uint8_t speed) {
HAL_GPIO_WritePin(MOTOR_RIGHT_IN3_PIN, HAL_GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_RIGHT_IN4_PIN, HAL_GPIO_PIN_RESET);
Motor_SetSpeed(MOTOR_RIGHT_ENB_PWM_INSTANCE, MOTOR_RIGHT_ENB_CHANNEL, speed);
}

void Motor_Right_Backward(uint8_t speed) {
HAL_GPIO_WritePin(MOTOR_RIGHT_IN3_PIN, HAL_GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_RIGHT_IN4_PIN, HAL_GPIO_PIN_SET);
Motor_SetSpeed(MOTOR_RIGHT_ENB_PWM_INSTANCE, MOTOR_RIGHT_ENB_CHANNEL, speed);
}

void Motor_Right_Stop(void) {
HAL_GPIO_WritePin(MOTOR_RIGHT_IN3_PIN, HAL_GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_RIGHT_IN4_PIN, HAL_GPIO_PIN_RESET);
Motor_SetSpeed(MOTOR_RIGHT_ENB_PWM_INSTANCE, MOTOR_RIGHT_ENB_CHANNEL, 0);
}

// 控制两个电机
void Motor_Forward(uint8_t speed_left, uint8_t speed_right) {
Motor_Left_Forward(speed_left);
Motor_Right_Forward(speed_right);
}

void Motor_Backward(uint8_t speed_left, uint8_t speed_right) {
Motor_Left_Backward(speed_left);
Motor_Right_Backward(speed_right);
}

void Motor_TurnLeft(uint8_t speed) {
Motor_Left_Backward(speed);
Motor_Right_Forward(speed);
}

void Motor_TurnRight(uint8_t speed) {
Motor_Left_Forward(speed);
Motor_Right_Backward(speed);
}

void Motor_Stop(void) {
Motor_Left_Stop();
Motor_Right_Stop();
}

2.4 蓝牙模块驱动 (bluetooth_driver.h / .c):

假设使用HC-05蓝牙模块,通过UART串口通信。

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
// 蓝牙模块驱动头文件 (bluetooth_driver.h)
#ifndef __BLUETOOTH_DRIVER_H__
#define __BLUETOOTH_DRIVER_H__

#include <stdint.h>
#include <stdbool.h>
#include "hal.h" // 包含 HAL 头文件

// 定义蓝牙模块 UART 实例 (需要根据实际硬件连接修改)
#define BLUETOOTH_UART_INSTANCE /* ... UART 实例 定义 ... */
#define BLUETOOTH_BAUDRATE 9600 // 常用的蓝牙模块波特率

// 初始化蓝牙模块驱动
void Bluetooth_Init(void);

// 发送数据
void Bluetooth_SendData(uint8_t *data, uint16_t len);

// 接收数据 (非阻塞方式,需要轮询或中断处理)
bool Bluetooth_ReceiveData(uint8_t *data, uint16_t *len);

// 设置蓝牙接收回调函数 (中断方式接收数据)
void Bluetooth_SetReceiveCallback(void (*callback)(uint8_t *data, uint16_t len));

#endif // __BLUETOOTH_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
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
// 蓝牙模块驱动实现文件 (bluetooth_driver.c)
#include "bluetooth_driver.h"

#define BLUETOOTH_RX_BUFFER_SIZE 64 // 蓝牙接收缓冲区大小
static uint8_t bluetooth_rx_buffer[BLUETOOTH_RX_BUFFER_SIZE];
static uint16_t bluetooth_rx_index = 0;
static void (*bluetooth_receive_callback)(uint8_t *data, uint16_t len) = NULL; // 接收回调函数指针


// UART 接收中断回调函数 (示例,需要在 HAL 层注册)
void UART_Receive_IRQHandler(uint8_t data) {
bluetooth_rx_buffer[bluetooth_rx_index++] = data;
if (bluetooth_rx_index >= BLUETOOTH_RX_BUFFER_SIZE) {
bluetooth_rx_index = BLUETOOTH_RX_BUFFER_SIZE - 1; // 防止缓冲区溢出
}
if (bluetooth_receive_callback != NULL) {
bluetooth_receive_callback(bluetooth_rx_buffer, bluetooth_rx_index); // 调用回调函数
}
}

// 初始化蓝牙模块驱动
void Bluetooth_Init(void) {
HAL_UART_InitTypeDef UART_InitStruct;
UART_InitStruct.UARTInstance = BLUETOOTH_UART_INSTANCE;
UART_InitStruct.BaudRate = BLUETOOTH_BAUDRATE;
HAL_UART_Init(&UART_InitStruct);

// 注册 UART 接收中断回调函数 (需要在 HAL 层实现 UART 中断接收功能)
// HAL_UART_SetReceiveCallback(BLUETOOTH_UART_INSTANCE, UART_Receive_IRQHandler); // 示例,需要根据实际 HAL 层 API 修改
}

// 发送数据
void Bluetooth_SendData(uint8_t *data, uint16_t len) {
for (uint16_t i = 0; i < len; i++) {
HAL_UART_Transmit(BLUETOOTH_UART_INSTANCE, data[i]);
}
}

// 接收数据 (非阻塞方式)
bool Bluetooth_ReceiveData(uint8_t *data, uint16_t *len) {
if (bluetooth_rx_index > 0) {
*len = bluetooth_rx_index;
memcpy(data, bluetooth_rx_buffer, *len);
bluetooth_rx_index = 0; // 清空接收缓冲区
return true; // 接收到数据
} else {
*len = 0;
return false; // 没有接收到数据
}
}

// 设置蓝牙接收回调函数 (中断方式接收数据)
void Bluetooth_SetReceiveCallback(void (*callback)(uint8_t *data, uint16_t len)) {
bluetooth_receive_callback = callback;
}

3. 服务层 (Service Layer):

服务层基于驱动层提供的硬件功能,实现核心业务逻辑。

3.1 循迹服务模块 (line_following_service.h / .c):

实现PID控制算法进行循迹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 循迹服务模块头文件 (line_following_service.h)
#ifndef __LINE_FOLLOWING_SERVICE_H__
#define __LINE_FOLLOWING_SERVICE_H__

#include <stdint.h>
#include <stdbool.h>

// 初始化循迹服务
void LineFollowing_Init(void);

// 执行循迹控制
void LineFollowing_Run(void);

// 设置循迹使能
void LineFollowing_SetEnable(bool enable);

// 获取循迹使能状态
bool LineFollowing_GetEnable(void);

#endif // __LINE_FOLLOWING_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
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
// 循迹服务模块实现文件 (line_following_service.c)
#include "line_following_service.h"
#include "line_sensor_driver.h"
#include "motor_driver.h"

// PID 控制参数 (需要根据实际情况调参)
#define KP 1.0f
#define KI 0.0f
#define KD 0.0f

#define BASE_SPEED 50 // 基础速度
#define MAX_SPEED_DIFF 30 // 最大速度差

static float integral_error = 0.0f;
static float last_error = 0.0f;
static bool line_following_enabled = false;

// 初始化循迹服务
void LineFollowing_Init(void) {
LineSensor_Init();
Motor_Init(); // 确保电机驱动也初始化
line_following_enabled = false;
}

// 执行循迹控制
void LineFollowing_Run(void) {
if (!line_following_enabled) return;

uint8_t sensor_values = LineSensor_ReadSensors();
float error = 0.0f;

// 计算偏差值 (error) - 假设中间传感器为 0 位置,左侧为负数,右侧为正数
// 例如: 5个传感器从左到右编号 0, 1, 2, 3, 4
// 如果只有中间传感器 (传感器 2) 检测到黑线,error 接近 0
// 如果左侧传感器检测到黑线,error 为负数,需要向右转
// 如果右侧传感器检测到黑线,error 为正数,需要向左转

if (sensor_values & (1 << 0)) error -= 2.0f; // 最左侧传感器
if (sensor_values & (1 << 1)) error -= 1.0f; // 左侧传感器
if (sensor_values & (1 << 3)) error += 1.0f; // 右侧传感器
if (sensor_values & (1 << 4)) error += 2.0f; // 最右侧传感器

// PID 控制计算
integral_error += error;
float derivative_error = error - last_error;
float control_signal = KP * error + KI * integral_error + KD * derivative_error;

last_error = error;

// 计算左右电机速度
int16_t speed_diff = (int16_t)(control_signal * MAX_SPEED_DIFF);
if (speed_diff > MAX_SPEED_DIFF) speed_diff = MAX_SPEED_DIFF;
if (speed_diff < -MAX_SPEED_DIFF) speed_diff = -MAX_SPEED_DIFF;

uint8_t left_speed = BASE_SPEED - speed_diff;
uint8_t right_speed = BASE_SPEED + speed_diff;

if (left_speed < MOTOR_SPEED_MIN) left_speed = MOTOR_SPEED_MIN;
if (left_speed > MOTOR_SPEED_MAX) left_speed = MOTOR_SPEED_MAX;
if (right_speed < MOTOR_SPEED_MIN) right_speed = MOTOR_SPEED_MIN;
if (right_speed > MOTOR_SPEED_MAX) right_speed = MOTOR_SPEED_MAX;

// 控制电机
if (sensor_values == 0) { // 如果没有检测到黑线,停止或继续直行 (根据实际需求调整)
Motor_Forward(BASE_SPEED, BASE_SPEED); // 继续直行
// Motor_Stop(); // 停止
} else {
Motor_Forward(left_speed, right_speed);
}
}

// 设置循迹使能
void LineFollowing_SetEnable(bool enable) {
line_following_enabled = enable;
if (!enable) {
Motor_Stop(); // 停止电机
}
}

// 获取循迹使能状态
bool LineFollowing_GetEnable(void) {
return line_following_enabled;
}

3.2 避障服务模块 (obstacle_avoidance_service.h / .c):

实现简单的避障逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 避障服务模块头文件 (obstacle_avoidance_service.h)
#ifndef __OBSTACLE_AVOIDANCE_SERVICE_H__
#define __OBSTACLE_AVOIDANCE_SERVICE_H__

#include <stdint.h>
#include <stdbool.h>

// 初始化避障服务
void ObstacleAvoidance_Init(void);

// 执行避障控制
void ObstacleAvoidance_Run(void);

// 设置避障使能
void ObstacleAvoidance_SetEnable(bool enable);

// 获取避障使能状态
bool ObstacleAvoidance_GetEnable(void);

#endif // __OBSTACLE_AVOIDANCE_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
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
// 避障服务模块实现文件 (obstacle_avoidance_service.c)
#include "obstacle_avoidance_service.h"
#include "ultrasonic_sensor_driver.h"
#include "motor_driver.h"

#define OBSTACLE_DISTANCE_THRESHOLD 30.0f // 障碍物距离阈值 (厘米)
#define AVOIDANCE_SPEED 40 // 避障时的速度
#define AVOIDANCE_TURN_TIME_MS 500 // 避障转向时间 (毫秒)

static bool obstacle_avoidance_enabled = false;
static bool is_avoiding = false; // 标记是否正在避障
static uint32_t avoidance_start_time = 0;

// 初始化避障服务
void ObstacleAvoidance_Init(void) {
Ultrasonic_Init();
Motor_Init(); // 确保电机驱动也初始化
obstacle_avoidance_enabled = false;
is_avoiding = false;
}

// 执行避障控制
void ObstacleAvoidance_Run(void) {
if (!obstacle_avoidance_enabled) return;

if (is_avoiding) {
// 正在避障中
if (HAL_GetTick() - avoidance_start_time >= AVOIDANCE_TURN_TIME_MS) {
is_avoiding = false; // 避障转向完成
Motor_Forward(AVOIDANCE_SPEED, AVOIDANCE_SPEED); // 恢复前进
} else {
// 继续避障转向 (例如向左转)
Motor_TurnLeft(AVOIDANCE_SPEED);
}
} else {
// 正常行驶状态,检测前方障碍物
float distance = Ultrasonic_MeasureDistance();
if (distance < OBSTACLE_DISTANCE_THRESHOLD) {
// 检测到障碍物,开始避障
is_avoiding = true;
avoidance_start_time = HAL_GetTick();
Motor_Backward(AVOIDANCE_SPEED, AVOIDANCE_SPEED); // 先后退一下
HAL_Delay(200); // 后退延时
Motor_TurnLeft(AVOIDANCE_SPEED); // 然后向左转 (或者向右转,可以随机选择)
}
}
}

// 设置避障使能
void ObstacleAvoidance_SetEnable(bool enable) {
obstacle_avoidance_enabled = enable;
if (!enable) {
is_avoiding = false;
Motor_Stop(); // 停止电机
}
}

// 获取避障使能状态
bool ObstacleAvoidance_GetEnable(void) {
return obstacle_avoidance_enabled;
}

3.3 蓝牙通信服务模块 (bluetooth_service.h / .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
// 蓝牙通信服务模块头文件 (bluetooth_service.h)
#ifndef __BLUETOOTH_SERVICE_H__
#define __BLUETOOTH_SERVICE_H__

#include <stdint.h>
#include <stdbool.h>

// 初始化蓝牙通信服务
void BluetoothService_Init(void);

// 处理蓝牙接收到的数据
void BluetoothService_ProcessData(uint8_t *data, uint16_t len);

// 定义蓝牙命令类型 (根据实际需求扩展)
typedef enum {
BLUETOOTH_CMD_STOP = 0x00,
BLUETOOTH_CMD_FORWARD = 0x01,
BLUETOOTH_CMD_BACKWARD = 0x02,
BLUETOOTH_CMD_LEFT = 0x03,
BLUETOOTH_CMD_RIGHT = 0x04,
BLUETOOTH_CMD_SPEED = 0x05, // 设置速度,后面跟一个字节的速度值 (0-100)
BLUETOOTH_CMD_LINE_FOLLOWING_ON = 0x10,
BLUETOOTH_CMD_LINE_FOLLOWING_OFF = 0x11,
BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_ON = 0x20,
BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_OFF = 0x21,
BLUETOOTH_CMD_UNKNOWN = 0xFF
} BluetoothCommandType;

// 解析蓝牙命令
BluetoothCommandType BluetoothService_ParseCommand(uint8_t *data, uint16_t len);

#endif // __BLUETOOTH_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
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
// 蓝牙通信服务模块实现文件 (bluetooth_service.c)
#include "bluetooth_service.h"
#include "bluetooth_driver.h"
#include "motor_driver.h"
#include "line_following_service.h"
#include "obstacle_avoidance_service.h"

#define DEFAULT_REMOTE_SPEED 60 // 默认遥控速度

// 初始化蓝牙通信服务
void BluetoothService_Init(void) {
Bluetooth_Init();
// 设置蓝牙接收回调函数
Bluetooth_SetReceiveCallback(BluetoothService_ProcessData);
}

// 处理蓝牙接收到的数据 (回调函数)
void BluetoothService_ProcessData(uint8_t *data, uint16_t len) {
if (len > 0) {
BluetoothCommandType command = BluetoothService_ParseCommand(data, len);
switch (command) {
case BLUETOOTH_CMD_STOP:
Motor_Stop();
break;
case BLUETOOTH_CMD_FORWARD:
Motor_Forward(DEFAULT_REMOTE_SPEED, DEFAULT_REMOTE_SPEED);
break;
case BLUETOOTH_CMD_BACKWARD:
Motor_Backward(DEFAULT_REMOTE_SPEED, DEFAULT_REMOTE_SPEED);
break;
case BLUETOOTH_CMD_LEFT:
Motor_TurnLeft(DEFAULT_REMOTE_SPEED);
break;
case BLUETOOTH_CMD_RIGHT:
Motor_TurnRight(DEFAULT_REMOTE_SPEED);
break;
case BLUETOOTH_CMD_SPEED:
if (len >= 2) {
uint8_t speed = data[1]; // 第二个字节是速度值
if (speed > MOTOR_SPEED_MAX) speed = MOTOR_SPEED_MAX;
Motor_Forward(speed, speed); // 或者根据上次方向设置速度
}
break;
case BLUETOOTH_CMD_LINE_FOLLOWING_ON:
LineFollowing_SetEnable(true);
ObstacleAvoidance_SetEnable(false); // 关闭避障模式
break;
case BLUETOOTH_CMD_LINE_FOLLOWING_OFF:
LineFollowing_SetEnable(false);
break;
case BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_ON:
ObstacleAvoidance_SetEnable(true);
LineFollowing_SetEnable(false); // 关闭循迹模式
break;
case BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_OFF:
ObstacleAvoidance_SetEnable(false);
break;
case BLUETOOTH_CMD_UNKNOWN:
default:
// 未知命令,忽略
break;
}
}
}

// 解析蓝牙命令
BluetoothCommandType BluetoothService_ParseCommand(uint8_t *data, uint16_t len) {
if (len > 0) {
uint8_t command_byte = data[0];
switch (command_byte) {
case 0x00: return BLUETOOTH_CMD_STOP;
case 0x01: return BLUETOOTH_CMD_FORWARD;
case 0x02: return BLUETOOTH_CMD_BACKWARD;
case 0x03: return BLUETOOTH_CMD_LEFT;
case 0x04: return BLUETOOTH_CMD_RIGHT;
case 0x05: return BLUETOOTH_CMD_SPEED;
case 0x10: return BLUETOOTH_CMD_LINE_FOLLOWING_ON;
case 0x11: return BLUETOOTH_CMD_LINE_FOLLOWING_OFF;
case 0x20: return BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_ON;
case 0x21: return BLUETOOTH_CMD_OBSTACLE_AVOIDANCE_OFF;
default: return BLUETOOTH_CMD_UNKNOWN;
}
}
return BLUETOOTH_CMD_UNKNOWN;
}

4. 应用层 (Application Layer):

应用层负责系统整体逻辑和用户交互,例如模式切换、主循环等。

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
// 应用层主文件 (main.c)
#include "hal.h" // HAL 层头文件
#include "motor_driver.h" // 电机驱动模块
#include "line_sensor_driver.h" // 循迹传感器驱动
#include "ultrasonic_sensor_driver.h" // 超声波传感器驱动
#include "bluetooth_driver.h" // 蓝牙模块驱动
#include "line_following_service.h" // 循迹服务模块
#include "obstacle_avoidance_service.h" // 避障服务模块
#include "bluetooth_service.h" // 蓝牙通信服务模块

// 系统运行模式
typedef enum {
MODE_MANUAL_CONTROL, // 手动遥控模式
MODE_LINE_FOLLOWING, // 循迹模式
MODE_OBSTACLE_AVOIDANCE, // 避障模式
MODE_COMBINED // 组合模式 (例如循迹+避障,根据实际需求定义)
} SystemMode;

SystemMode current_mode = MODE_MANUAL_CONTROL; // 默认模式

// 初始化系统
void System_Init(void) {
// HAL 初始化 (例如时钟,外设等,需要根据实际硬件平台进行初始化)
// HAL_Init(); // 示例,实际 HAL 初始化函数可能不同

Motor_Init();
LineSensor_Init();
Ultrasonic_Init();
Bluetooth_Init();

LineFollowing_Init();
ObstacleAvoidance_Init();
BluetoothService_Init();

// 初始化时关闭所有服务,进入手动遥控模式
LineFollowing_SetEnable(false);
ObstacleAvoidance_SetEnable(false);
current_mode = MODE_MANUAL_CONTROL;

HAL_Delay(1000); // 延时等待硬件初始化完成
HAL_UART_TransmitString(BLUETOOTH_UART_INSTANCE, "System Initialized!\r\n"); // 通过蓝牙发送初始化完成信息
}

// 系统主循环
int main(void) {
System_Init();

while (1) {
switch (current_mode) {
case MODE_MANUAL_CONTROL:
// 手动遥控模式,蓝牙命令已经在 BluetoothService_ProcessData 中处理
break;
case MODE_LINE_FOLLOWING:
LineFollowing_Run();
break;
case MODE_OBSTACLE_AVOIDANCE:
ObstacleAvoidance_Run();
break;
case MODE_COMBINED:
// 组合模式逻辑 (例如循迹+避障) - 可以根据实际需求实现
LineFollowing_Run(); // 循迹
ObstacleAvoidance_Run(); // 避障 (可以调整优先级和策略)
break;
default:
// 未知模式,停止电机
Motor_Stop();
break;
}

// 其他系统任务 (例如状态监测,数据上报等)
HAL_Delay(10); // 适当延时,降低 CPU 占用率
}
}

测试验证和维护升级:

  • 单元测试: 针对每个驱动模块和服务模块编写单元测试代码,例如测试电机驱动模块的电机正反转和速度控制功能,测试循迹传感器驱动模块的传感器数据读取功能等。可以使用单元测试框架 (例如 CUnit, Unity) 来组织和执行测试用例。
  • 集成测试: 将各个模块组合起来进行集成测试,例如测试循迹服务模块是否能正确控制电机沿着轨迹线行驶,测试避障服务模块是否能正确避开障碍物,测试蓝牙遥控功能是否正常工作等。
  • 系统测试: 进行全面的系统测试,验证整个智能小车系统是否满足所有需求,包括功能性测试、性能测试、可靠性测试、环境适应性测试等。
  • 调试与优化: 使用调试器 (例如 GDB, J-Link) 和日志输出 (例如 UART 串口打印) 来定位和解决测试中发现的bug。 根据测试结果和性能指标,对代码进行优化,提高系统效率和响应速度。
  • 维护与升级:
    • 模块化设计: 分层架构和模块化设计使得系统易于维护和升级。当需要修改或添加功能时,只需要修改或添加相应的模块,而不会影响其他模块。
    • 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便代码的版本管理、协作开发和回滚。
    • OTA 升级 (Over-The-Air): 如果硬件平台支持,可以考虑实现OTA升级功能,通过蓝牙或其他无线方式远程升级系统固件,方便后续的维护和升级。

总结:

以上代码示例提供了一个基于分层架构的智能小车嵌入式系统软件框架。 这只是一个基础框架,实际项目中还需要根据具体的硬件平台、传感器型号、电机驱动模块、蓝牙模块等进行适配和完善。 代码中也省略了一些细节,例如错误处理、中断处理、更精细的延时函数、详细的硬件配置等等,这些都需要在实际开发中根据具体情况进行补充和实现。

希望这个详细的解答和代码示例能帮助您理解嵌入式系统开发流程和代码架构设计,并能应用到您的智能小车项目中。 在实际开发过程中,请务必根据您的具体硬件平台和需求,进行代码的适配、测试和优化。 祝您项目顺利!

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