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

项目简介回顾:
- 平台: 立创梁山派 (LCSC Liangshan Pai) - 这通常指的是基于某个微控制器(如ARM Cortex-M系列)的开发板,具体型号需要进一步确认,但架构设计思路是通用的。
- 功能:
- 循迹 (Line Following): 小车能够沿着预设的黑色轨迹线自动行驶。
- 避障 (Obstacle Avoidance): 小车能够检测前方障碍物并自动避开。
- 蓝牙遥控 (Bluetooth Remote Control): 通过蓝牙连接,用户可以使用手机或其他蓝牙设备遥控小车的运动。
系统开发流程概述:
一个完整的嵌入式系统开发流程通常包括以下阶段:
- 需求分析 (Requirements Analysis): 明确系统需要实现的功能、性能指标、环境约束等。
- 系统设计 (System Design): 确定硬件选型、软件架构、模块划分、接口定义等。
- 详细设计 (Detailed Design): 对每个软件模块进行详细设计,包括算法选择、数据结构设计、流程图绘制等。
- 编码实现 (Coding Implementation): 根据详细设计,编写C代码实现各个模块的功能。
- 单元测试 (Unit Testing): 对每个模块进行单独测试,确保其功能正确。
- 集成测试 (Integration Testing): 将各个模块组合起来进行测试,验证模块间的协同工作。
- 系统测试 (System Testing): 对整个系统进行全面测试,验证系统是否满足所有需求。
- 调试与优化 (Debugging and Optimization): 解决测试中发现的问题,并对系统性能进行优化。
- 维护与升级 (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
|
#ifndef __HAL_H__ #define __HAL_H__
#include <stdint.h> #include <stdbool.h>
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; HAL_GPIO_ModeTypeDef Mode; } HAL_GPIO_InitTypeDef;
void HAL_GPIO_Init(HAL_GPIO_InitTypeDef *GPIO_InitStruct);
void HAL_GPIO_WritePin(uint32_t Pin, HAL_GPIO_PinStateTypeDef PinState);
HAL_GPIO_PinStateTypeDef HAL_GPIO_ReadPin(uint32_t Pin);
typedef struct { uint32_t TimerInstance; 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));
typedef struct { uint32_t PWMInstance; uint32_t Channel; uint32_t Prescaler; uint32_t Period; uint32_t Pulse; } HAL_PWM_InitTypeDef;
void HAL_PWM_Init(HAL_PWM_InitTypeDef *PWM_InitStruct);
void HAL_PWM_Start(uint32_t PWMInstance, uint32_t Channel);
void HAL_PWM_Stop(uint32_t PWMInstance, uint32_t Channel);
void HAL_PWM_SetPulse(uint32_t PWMInstance, uint32_t Channel, uint32_t Pulse);
typedef struct { uint32_t UARTInstance; uint32_t BaudRate; } HAL_UART_InitTypeDef;
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);
void HAL_UART_SetReceiveCallback(uint32_t UARTInstance, void (*callback)(uint8_t data));
#endif
|
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
|
#include "hal.h"
#include "stm32fxxx_hal.h"
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); }
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); }
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; }
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); }
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_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); }
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); }
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); }
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); }
|
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
| #ifndef __LINE_SENSOR_DRIVER_H__ #define __LINE_SENSOR_DRIVER_H__
#include <stdint.h> #include <stdbool.h> #include "hal.h"
#define LINE_SENSOR_COUNT 5
#define LINE_SENSOR_PIN_1 #define LINE_SENSOR_PIN_2 #define LINE_SENSOR_PIN_3 #define LINE_SENSOR_PIN_4 #define LINE_SENSOR_PIN_5
void LineSensor_Init(void);
uint8_t LineSensor_ReadSensors(void);
bool LineSensor_ReadSensor(uint8_t sensor_index);
#endif
|
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
| #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); } } 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
| #ifndef __ULTRASONIC_SENSOR_DRIVER_H__ #define __ULTRASONIC_SENSOR_DRIVER_H__
#include <stdint.h> #include <stdbool.h> #include "hal.h"
#define ULTRASONIC_TRIG_PIN #define ULTRASONIC_ECHO_PIN
#define ULTRASONIC_TIMER_INSTANCE
void Ultrasonic_Init(void);
float Ultrasonic_MeasureDistance(void);
#endif
|
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
| #include "ultrasonic_sensor_driver.h"
#define SOUND_SPEED_CM_US 0.0343
void Ultrasonic_Init(void) { HAL_GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = ULTRASONIC_TRIG_PIN; GPIO_InitStruct.Mode = HAL_GPIO_MODE_OUTPUT; HAL_GPIO_Init(&GPIO_InitStruct);
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; Timer_InitStruct.Period = 0xFFFF; HAL_Timer_Init(&Timer_InitStruct); }
float Ultrasonic_MeasureDistance(void) { HAL_GPIO_WritePin(ULTRASONIC_TRIG_PIN, HAL_GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(ULTRASONIC_TRIG_PIN, HAL_GPIO_PIN_RESET);
while (HAL_GPIO_ReadPin(ULTRASONIC_ECHO_PIN) == HAL_GPIO_PIN_RESET); HAL_Timer_Start(ULTRASONIC_TIMER_INSTANCE);
while (HAL_GPIO_ReadPin(ULTRASONIC_ECHO_PIN) == HAL_GPIO_PIN_SET); HAL_Timer_Stop(ULTRASONIC_TIMER_INSTANCE);
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;
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
| #ifndef __MOTOR_DRIVER_H__ #define __MOTOR_DRIVER_H__
#include <stdint.h> #include <stdbool.h> #include "hal.h"
#define MOTOR_LEFT_IN1_PIN #define MOTOR_LEFT_IN2_PIN #define MOTOR_LEFT_ENA_PWM_INSTANCE #define MOTOR_LEFT_ENA_PWM_CHANNEL
#define MOTOR_RIGHT_IN3_PIN #define MOTOR_RIGHT_IN4_PIN #define MOTOR_RIGHT_ENB_PWM_INSTANCE #define MOTOR_RIGHT_ENB_PWM_CHANNEL
#define MOTOR_SPEED_MIN 0 #define MOTOR_SPEED_MAX 100
void Motor_Init(void);
void Motor_Left_Forward(uint8_t speed); void Motor_Left_Backward(uint8_t speed); void Motor_Left_Stop(void);
void Motor_Right_Forward(uint8_t speed); 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
|
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
| #include "motor_driver.h"
#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_InitStruct.PWMInstance = MOTOR_LEFT_ENA_PWM_INSTANCE; PWM_InitStruct.Channel = MOTOR_LEFT_ENA_PWM_CHANNEL; PWM_InitStruct.Prescaler = 72 - 1; PWM_InitStruct.Period = PWM_PERIOD; PWM_InitStruct.Pulse = 0; HAL_PWM_Init(&PWM_InitStruct); HAL_PWM_Start(MOTOR_LEFT_ENA_PWM_INSTANCE, MOTOR_LEFT_ENA_PWM_CHANNEL);
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; HAL_PWM_Init(&PWM_InitStruct); HAL_PWM_Start(MOTOR_RIGHT_ENB_PWM_INSTANCE, MOTOR_RIGHT_ENB_CHANNEL);
Motor_Stop(); }
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
| #ifndef __BLUETOOTH_DRIVER_H__ #define __BLUETOOTH_DRIVER_H__
#include <stdint.h> #include <stdbool.h> #include "hal.h"
#define BLUETOOTH_UART_INSTANCE #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
|
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
| #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;
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);
}
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
| #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
|
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
| #include "line_following_service.h" #include "line_sensor_driver.h" #include "motor_driver.h"
#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;
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;
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); } 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
| #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
|
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
| #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
| #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, 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
|
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
| #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
| #include "hal.h" #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) {
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: 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); } }
|
测试验证和维护升级:
- 单元测试: 针对每个驱动模块和服务模块编写单元测试代码,例如测试电机驱动模块的电机正反转和速度控制功能,测试循迹传感器驱动模块的传感器数据读取功能等。可以使用单元测试框架 (例如 CUnit, Unity) 来组织和执行测试用例。
- 集成测试: 将各个模块组合起来进行集成测试,例如测试循迹服务模块是否能正确控制电机沿着轨迹线行驶,测试避障服务模块是否能正确避开障碍物,测试蓝牙遥控功能是否正常工作等。
- 系统测试: 进行全面的系统测试,验证整个智能小车系统是否满足所有需求,包括功能性测试、性能测试、可靠性测试、环境适应性测试等。
- 调试与优化: 使用调试器 (例如 GDB, J-Link) 和日志输出 (例如 UART 串口打印) 来定位和解决测试中发现的bug。 根据测试结果和性能指标,对代码进行优化,提高系统效率和响应速度。
- 维护与升级:
- 模块化设计: 分层架构和模块化设计使得系统易于维护和升级。当需要修改或添加功能时,只需要修改或添加相应的模块,而不会影响其他模块。
- 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便代码的版本管理、协作开发和回滚。
- OTA 升级 (Over-The-Air): 如果硬件平台支持,可以考虑实现OTA升级功能,通过蓝牙或其他无线方式远程升级系统固件,方便后续的维护和升级。
总结:
以上代码示例提供了一个基于分层架构的智能小车嵌入式系统软件框架。 这只是一个基础框架,实际项目中还需要根据具体的硬件平台、传感器型号、电机驱动模块、蓝牙模块等进行适配和完善。 代码中也省略了一些细节,例如错误处理、中断处理、更精细的延时函数、详细的硬件配置等等,这些都需要在实际开发中根据具体情况进行补充和实现。
希望这个详细的解答和代码示例能帮助您理解嵌入式系统开发流程和代码架构设计,并能应用到您的智能小车项目中。 在实际开发过程中,请务必根据您的具体硬件平台和需求,进行代码的适配、测试和优化。 祝您项目顺利!