当前位置: 首页 > news >正文

STM32F103C8T6 四驱智能小车寻迹软件源代码

项目结构

SmartCar/
├── Core/
│   ├── Src/
│   │   ├── main.c
│   │   ├── stm32f1xx_hal_msp.c
│   │   └── stm32f1xx_it.c
│   ├── Inc/
│   │   ├── main.h
│   │   └── config.h
├── Drivers/
│   ├── STM32F1xx_HAL_Driver/
│   └── CMSIS/
├── BSP/
│   ├── Src/
│   │   ├── motor.c
│   │   ├── sensor.c
│   │   ├── pwm.c
│   │   ├── uart.c
│   │   ├── pid.c
│   │   └── control.c
│   ├── Inc/
│       ├── motor.h
│       ├── sensor.h
│       ├── pwm.h
│       ├── uart.h
│       ├── pid.h
│       └── control.h
└── README.md

源代码实现

1. 配置文件 (config.h)

/*** 智能小车配置头文件* MCU: STM32F103C8T6* 晶振: 8MHz* 系统时钟: 72MHz*/#ifndef __CONFIG_H
#define __CONFIG_H// 系统时钟配置
#define SYS_CLK_FREQ     72000000
#define HSE_VALUE        8000000// 调试配置
#define DEBUG_ENABLE     1
#define DEBUG_UART       USART1
#define DEBUG_BAUDRATE   115200// 传感器配置
#define SENSOR_COUNT     5      // 5路循迹传感器
#define SENSOR_THRESHOLD 500    // 黑白区分阈值(0-4095)
#define SENSOR_INTERVAL  10     // 传感器采样间隔(ms)// 电机配置
#define MOTOR_COUNT      4      // 4个电机
#define MOTOR_BASE_SPEED 1000   // 基础速度(0-2000)
#define MOTOR_MAX_SPEED  2000   // 最大速度
#define MOTOR_MIN_SPEED  500    // 最小速度// PID参数配置
#define PID_KP           2.0f   // 比例系数
#define PID_KI           0.1f   // 积分系数
#define PID_KD           1.5f   // 微分系数
#define PID_MAX_OUTPUT   1000   // PID最大输出// 循迹模式配置
#define TRACE_MODE_NORMAL    0  // 普通循迹模式
#define TRACE_MODE_PID       1  // PID循迹模式
#define TRACE_MODE_ADVANCED  2  // 高级循迹模式// 速度配置
#define SPEED_SLOW       800    // 慢速
#define SPEED_NORMAL     1200   // 正常速度
#define SPEED_FAST       1600   // 快速
#define SPEED_TURN       1000   // 转弯速度// 引脚定义
// 电机引脚
#define MOTOR1_A_PORT    GPIOB
#define MOTOR1_A_PIN     GPIO_PIN_6
#define MOTOR1_B_PORT    GPIOB
#define MOTOR1_B_PIN     GPIO_PIN_7
#define MOTOR1_PWM_TIM   TIM4
#define MOTOR1_PWM_CH    TIM_CHANNEL_1#define MOTOR2_A_PORT    GPIOB
#define MOTOR2_A_PIN     GPIO_PIN_8
#define MOTOR2_B_PORT    GPIOB
#define MOTOR2_B_PIN     GPIO_PIN_9
#define MOTOR2_PWM_TIM   TIM4
#define MOTOR2_PWM_CH    TIM_CHANNEL_2#define MOTOR3_A_PORT    GPIOB
#define MOTOR3_A_PIN     GPIO_PIN_10
#define MOTOR3_B_PORT    GPIOB
#define MOTOR3_B_PIN     GPIO_PIN_11
#define MOTOR3_PWM_TIM   TIM4
#define MOTOR3_PWM_CH    TIM_CHANNEL_3#define MOTOR4_A_PORT    GPIOB
#define MOTOR4_A_PIN     GPIO_PIN_12
#define MOTOR4_B_PORT    GPIOB
#define MOTOR4_B_PIN     GPIO_PIN_13
#define MOTOR4_PWM_TIM   TIM4
#define MOTOR4_PWM_CH    TIM_CHANNEL_4// 传感器引脚(ADC)
#define SENSOR1_PIN      GPIO_PIN_0
#define SENSOR1_CH       ADC_CHANNEL_0
#define SENSOR2_PIN      GPIO_PIN_1
#define SENSOR2_CH       ADC_CHANNEL_1
#define SENSOR3_PIN      GPIO_PIN_2
#define SENSOR3_CH       ADC_CHANNEL_2
#define SENSOR4_PIN      GPIO_PIN_3
#define SENSOR4_CH       ADC_CHANNEL_3
#define SENSOR5_PIN      GPIO_PIN_4
#define SENSOR5_CH       ADC_CHANNEL_4// 按键引脚
#define KEY_START_PIN    GPIO_PIN_5
#define KEY_START_PORT   GPIOA
#define KEY_MODE_PIN     GPIO_PIN_6
#define KEY_MODE_PORT    GPIOA// LED指示灯
#define LED_RUN_PIN      GPIO_PIN_13
#define LED_RUN_PORT     GPIOC
#define LED_ERR_PIN      GPIO_PIN_14
#define LED_ERR_PORT     GPIOC
#define LED_TRACE_PIN    GPIO_PIN_15
#define LED_TRACE_PORT   GPIOC// 蜂鸣器
#define BUZZER_PIN       GPIO_PIN_8
#define BUZZER_PORT      GPIOA// 超声波模块(可选)
#define US_TRIG_PIN      GPIO_PIN_9
#define US_TRIG_PORT     GPIOA
#define US_ECHO_PIN      GPIO_PIN_10
#define US_ECHO_PORT     GPIOA// 枚举定义
typedef enum {CAR_STATE_IDLE = 0,      // 空闲状态CAR_STATE_READY,         // 准备就绪CAR_STATE_RUNNING,       // 运行中CAR_STATE_PAUSED,        // 暂停CAR_STATE_ERROR          // 错误
} CarState;typedef enum {DIR_FORWARD = 0,         // 前进DIR_BACKWARD,            // 后退DIR_LEFT,                // 左转DIR_RIGHT,               // 右转DIR_STOP                 // 停止
} Direction;typedef enum {TRACE_LOST = 0,          // 丢失轨迹TRACE_ON_LINE,           // 在轨迹上TRACE_CROSSROAD,         // 十字路口TRACE_TURN_LEFT,         // 左转弯TRACE_TURN_RIGHT,        // 右转弯TRACE_TURN_AROUND        // 掉头
} TraceState;// 结构体定义
typedef struct {uint16_t speed_left_front;   // 左前轮速度uint16_t speed_right_front;  // 右前轮速度uint16_t speed_left_rear;    // 左后轮速度uint16_t speed_right_rear;   // 右后轮速度Direction direction;         // 行驶方向uint8_t enable;             // 使能标志
} MotorControl;typedef struct {uint16_t sensor_values[5];   // 传感器原始值uint8_t sensor_states[5];    // 传感器状态(0:白线, 1:黑线)int8_t line_position;        // 轨迹位置(-2,-1,0,1,2)TraceState trace_state;      // 循迹状态uint32_t lost_count;         // 丢失轨迹计数
} SensorData;typedef struct {float Kp;                    // 比例系数float Ki;                    // 积分系数float Kd;                    // 微分系数float error;                // 当前误差float integral;             // 积分项float derivative;           // 微分项float last_error;           // 上次误差float output;               // 输出值float max_output;           // 最大输出
} PIDController;typedef struct {CarState state;             // 小车状态uint8_t trace_mode;         // 循迹模式uint16_t base_speed;        // 基础速度uint16_t max_speed;         // 最大速度uint32_t run_time;          // 运行时间uint32_t distance;          // 行驶距离uint8_t obstacle_detected;  // 检测到障碍物
} CarInfo;// 全局变量声明
extern CarInfo g_car_info;
extern SensorData g_sensor_data;
extern MotorControl g_motor_control;
extern PIDController g_pid_controller;#endif /* __CONFIG_H */

2. 主程序 (main.c)

/*** 主程序文件* 四驱智能小车寻迹系统*/#include "main.h"
#include "config.h"
#include "motor.h"
#include "sensor.h"
#include "control.h"
#include "uart.h"
#include "pid.h"
#include <stdio.h>
#include <string.h>// 全局变量定义
CarInfo g_car_info = {0};
SensorData g_sensor_data = {0};
MotorControl g_motor_control = {0};
PIDController g_pid_controller = {0};// 系统滴答定时器
volatile uint32_t g_sys_tick = 0;// 函数声明
static void SystemClock_Config(void);
static void GPIO_Init(void);
static void TIM_Init(void);
static void ADC_Init(void);
static void NVIC_Init(void);
static void System_Init(void);
static void Car_Init(void);
static void Error_Handler(void);
static void SysTick_Handler(void);
static void Car_State_Machine(void);
static void Trace_Task(void);
static void Control_Task(void);
static void Debug_Task(void);
static void Beep(uint8_t count, uint16_t interval);
static void LED_Blink(uint8_t led, uint8_t count, uint16_t interval);int main(void) {// 复位所有外设,初始化Flash接口和系统滴答定时器HAL_Init();// 配置系统时钟SystemClock_Config();// 初始化外设System_Init();// 初始化小车Car_Init();// 启动提示音Beep(3, 100);LED_Blink(LED_RUN_PIN, 3, 200);// 主循环while (1) {// 状态机处理Car_State_Machine();// 根据状态执行不同任务switch (g_car_info.state) {case CAR_STATE_READY:// 等待启动信号if (HAL_GPIO_ReadPin(KEY_START_PORT, KEY_START_PIN) == GPIO_PIN_RESET) {g_car_info.state = CAR_STATE_RUNNING;Beep(1, 200);HAL_GPIO_WritePin(LED_TRACE_PORT, LED_TRACE_PIN, GPIO_PIN_SET);}break;case CAR_STATE_RUNNING:// 执行循迹任务Trace_Task();// 执行控制任务Control_Task();// 调试信息输出#if DEBUG_ENABLEDebug_Task();#endifbreak;case CAR_STATE_PAUSED:// 停止电机Motor_Stop();break;case CAR_STATE_ERROR:// 错误处理Motor_Stop();HAL_GPIO_WritePin(LED_ERR_PORT, LED_ERR_PIN, GPIO_PIN_SET);break;default:break;}// 系统延时HAL_Delay(1);}
}/*** 系统时钟配置* 配置为72MHz*/
static void SystemClock_Config(void) {RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};// 初始化HSERCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {Error_Handler();}// 初始化CPU, AHB, APB总线时钟RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {Error_Handler();}
}/*** GPIO初始化*/
static void GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能GPIO时钟__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();// 电机控制引脚配置// 电机方向控制引脚GPIO_InitStruct.Pin = MOTOR1_A_PIN | MOTOR1_B_PIN | MOTOR2_A_PIN | MOTOR2_B_PIN |MOTOR3_A_PIN | MOTOR3_B_PIN | MOTOR4_A_PIN | MOTOR4_B_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// 传感器引脚配置(ADC输入)GPIO_InitStruct.Pin = SENSOR1_PIN | SENSOR2_PIN | SENSOR3_PIN | SENSOR4_PIN | SENSOR5_PIN;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 按键引脚配置GPIO_InitStruct.Pin = KEY_START_PIN | KEY_MODE_PIN;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// LED引脚配置GPIO_InitStruct.Pin = LED_RUN_PIN | LED_ERR_PIN | LED_TRACE_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);// 蜂鸣器引脚GPIO_InitStruct.Pin = BUZZER_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 初始状态HAL_GPIO_WritePin(LED_RUN_PORT, LED_RUN_PIN, GPIO_PIN_SET);   // 运行灯常亮HAL_GPIO_WritePin(LED_ERR_PORT, LED_ERR_PIN, GPIO_PIN_RESET); // 错误灯灭HAL_GPIO_WritePin(LED_TRACE_PORT, LED_TRACE_PIN, GPIO_PIN_RESET); // 循迹灯灭HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_RESET);   // 蜂鸣器关
}/*** 定时器初始化*/
static void TIM_Init(void) {TIM_HandleTypeDef htim4 = {0};TIM_OC_InitTypeDef sConfigOC = {0};// 使能TIM4时钟__HAL_RCC_TIM4_CLK_ENABLE();// 配置TIM4产生PWMhtim4.Instance = TIM4;htim4.Init.Prescaler = 72 - 1;  // 72MHz/72 = 1MHzhtim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.Period = 2000 - 1;   // PWM频率 = 1MHz/2000 = 500Hzhtim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) {Error_Handler();}// 配置PWM通道sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 0;  // 初始占空比为0sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;// 配置4个PWM通道if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK ||HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK ||HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK ||HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) {Error_Handler();}// 启动PWMHAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
}/*** ADC初始化*/
static void ADC_Init(void) {ADC_HandleTypeDef hadc1 = {0};ADC_ChannelConfTypeDef sConfig = {0};// 使能ADC1时钟__HAL_RCC_ADC1_CLK_ENABLE();// 配置ADChadc1.Instance = ADC1;hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;hadc1.Init.ContinuousConvMode = ENABLE;hadc1.Init.DiscontinuousConvMode = DISABLE;hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion = 5;if (HAL_ADC_Init(&hadc1) != HAL_OK) {Error_Handler();}// 配置ADC通道// 传感器1sConfig.Channel = ADC_CHANNEL_0;sConfig.Rank = ADC_REGULAR_RANK_1;sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;HAL_ADC_ConfigChannel(&hadc1, &sConfig);// 传感器2sConfig.Channel = ADC_CHANNEL_1;sConfig.Rank = ADC_REGULAR_RANK_2;HAL_ADC_ConfigChannel(&hadc1, &sConfig);// 传感器3sConfig.Channel = ADC_CHANNEL_2;sConfig.Rank = ADC_REGULAR_RANK_3;HAL_ADC_ConfigChannel(&hadc1, &sConfig);// 传感器4sConfig.Channel = ADC_CHANNEL_3;sConfig.Rank = ADC_REGULAR_RANK_4;HAL_ADC_ConfigChannel(&hadc1, &sConfig);// 传感器5sConfig.Channel = ADC_CHANNEL_4;sConfig.Rank = ADC_REGULAR_RANK_5;HAL_ADC_ConfigChannel(&hadc1, &sConfig);// 启动ADCHAL_ADC_Start(&hadc1);
}/*** NVIC初始化*/
static void NVIC_Init(void) {HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}/*** 系统初始化*/
static void System_Init(void) {// 初始化GPIOGPIO_Init();// 初始化定时器TIM_Init();// 初始化ADCADC_Init();// 初始化串口(调试用)#if DEBUG_ENABLEUART_Init(DEBUG_BAUDRATE);printf("System Initialized\r\n");#endif// 初始化NVICNVIC_Init();
}/*** 小车初始化*/
static void Car_Init(void) {// 初始化小车状态g_car_info.state = CAR_STATE_READY;g_car_info.trace_mode = TRACE_MODE_PID;g_car_info.base_speed = MOTOR_BASE_SPEED;g_car_info.max_speed = MOTOR_MAX_SPEED;g_car_info.run_time = 0;g_car_info.distance = 0;g_car_info.obstacle_detected = 0;// 初始化传感器数据memset(&g_sensor_data, 0, sizeof(SensorData));g_sensor_data.line_position = 0;g_sensor_data.trace_state = TRACE_LOST;g_sensor_data.lost_count = 0;// 初始化电机控制memset(&g_motor_control, 0, sizeof(MotorControl));g_motor_control.enable = 1;g_motor_control.direction = DIR_STOP;// 初始化PID控制器PID_Init(&g_pid_controller, PID_KP, PID_KI, PID_KD, PID_MAX_OUTPUT);// 初始化电机Motor_Init();#if DEBUG_ENABLEprintf("Car Initialized\r\n");printf("Mode: %s\r\n", g_car_info.trace_mode == TRACE_MODE_PID ? "PID" : "Normal");printf("Base Speed: %d\r\n", g_car_info.base_speed);#endif
}/*** 错误处理函数*/
static void Error_Handler(void) {// 错误处理HAL_GPIO_WritePin(LED_ERR_PORT, LED_ERR_PIN, GPIO_PIN_SET);while (1) {// 错误闪烁HAL_GPIO_TogglePin(LED_ERR_PORT, LED_ERR_PIN);HAL_Delay(200);}
}/*** 系统滴答定时器中断*/
void SysTick_Handler(void) {HAL_IncTick();g_sys_tick++;
}/*** 小车状态机*/
static void Car_State_Machine(void) {static uint32_t last_led_toggle = 0;static uint8_t mode_button_pressed = 0;// LED运行指示if (HAL_GetTick() - last_led_toggle > 500) {HAL_GPIO_TogglePin(LED_RUN_PORT, LED_RUN_PIN);last_led_toggle = HAL_GetTick();}// 模式切换按键检测if (HAL_GPIO_ReadPin(KEY_MODE_PORT, KEY_MODE_PIN) == GPIO_PIN_RESET) {if (!mode_button_pressed) {mode_button_pressed = 1;g_car_info.trace_mode = (g_car_info.trace_mode + 1) % 3;#if DEBUG_ENABLEprintf("Mode Changed: ");switch (g_car_info.trace_mode) {case TRACE_MODE_NORMAL:printf("Normal\r\n");break;case TRACE_MODE_PID:printf("PID\r\n");break;case TRACE_MODE_ADVANCED:printf("Advanced\r\n");break;}#endifBeep(1, 100);}} else {mode_button_pressed = 0;}
}/*** 循迹任务*/
static void Trace_Task(void) {static uint32_t last_sensor_time = 0;// 定期采样传感器if (HAL_GetTick() - last_sensor_time > SENSOR_INTERVAL) {Sensor_ReadAll();Sensor_Process();last_sensor_time = HAL_GetTick();}
}/*** 控制任务*/
static void Control_Task(void) {int16_t pid_output = 0;int16_t left_speed = 0, right_speed = 0;// 根据循迹模式选择控制算法switch (g_car_info.trace_mode) {case TRACE_MODE_NORMAL:// 普通循迹模式Control_Normal();break;case TRACE_MODE_PID:// PID循迹模式pid_output = Control_PID();// 计算左右轮速度left_speed = g_car_info.base_speed + pid_output;right_speed = g_car_info.base_speed - pid_output;// 限制速度范围left_speed = (left_speed < MOTOR_MIN_SPEED) ? MOTOR_MIN_SPEED : (left_speed > MOTOR_MAX_SPEED) ? MOTOR_MAX_SPEED : left_speed;right_speed = (right_speed < MOTOR_MIN_SPEED) ? MOTOR_MIN_SPEED : (right_speed > MOTOR_MAX_SPEED) ? MOTOR_MAX_SPEED : right_speed;// 设置电机速度Motor_SetSpeed(MOTOR_LEFT_FRONT, left_speed);Motor_SetSpeed(MOTOR_LEFT_REAR, left_speed);Motor_SetSpeed(MOTOR_RIGHT_FRONT, right_speed);Motor_SetSpeed(MOTOR_RIGHT_REAR, right_speed);// 前进Motor_Forward();break;case TRACE_MODE_ADVANCED:// 高级循迹模式(包含避障)Control_Advanced();break;}// 更新运行时间g_car_info.run_time = HAL_GetTick() / 1000;  // 转换为秒
}/*** 调试任务*/
static void Debug_Task(void) {static uint32_t last_debug_time = 0;if (HAL_GetTick() - last_debug_time > 1000) {  // 每秒输出一次printf("=== Debug Info ===\r\n");printf("State: %d, Mode: %d\r\n", g_car_info.state, g_car_info.trace_mode);printf("Run Time: %lus, Distance: %lum\r\n", g_car_info.run_time, g_car_info.distance);printf("Line Pos: %d, Trace State: %d\r\n", g_sensor_data.line_position, g_sensor_data.trace_state);printf("Motor: LF=%d, RF=%d, LR=%d, RR=%d\r\n",g_motor_control.speed_left_front,g_motor_control.speed_right_front,g_motor_control.speed_left_rear,g_motor_control.speed_right_rear);printf("PID Output: %.2f\r\n", g_pid_controller.output);printf("==================\r\n");last_debug_time = HAL_GetTick();}
}/*** 蜂鸣器控制*/
static void Beep(uint8_t count, uint16_t interval) {for (uint8_t i = 0; i < count; i++) {HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_SET);HAL_Delay(interval);HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_RESET);if (i < count - 1) {HAL_Delay(interval);}}
}/*** LED闪烁控制*/
static void LED_Blink(uint8_t led, uint8_t count, uint16_t interval) {GPIO_TypeDef* port = NULL;uint16_t pin = 0;// 确定LED端口和引脚if (led == LED_RUN_PIN) {port = LED_RUN_PORT;pin = LED_RUN_PIN;} else if (led == LED_ERR_PIN) {port = LED_ERR_PORT;pin = LED_ERR_PIN;} else if (led == LED_TRACE_PIN) {port = LED_TRACE_PORT;pin = LED_TRACE_PIN;} else {return;}for (uint8_t i = 0; i < count; i++) {HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET);HAL_Delay(interval);HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET);if (i < count - 1) {HAL_Delay(interval);}}
}

3. 电机驱动 (motor.c)

/*** 电机驱动模块*/#include "motor.h"
#include "config.h"// 电机控制结构体
typedef struct {GPIO_TypeDef* port_a;uint16_t pin_a;GPIO_TypeDef* port_b;uint16_t pin_b;TIM_HandleTypeDef* tim;uint32_t channel;uint16_t speed;uint8_t direction;
} Motor;static Motor motors[4];/*** 电机初始化*/
void Motor_Init(void) {// 初始化左前电机(M1)motors[MOTOR_LEFT_FRONT].port_a = MOTOR1_A_PORT;motors[MOTOR_LEFT_FRONT].pin_a = MOTOR1_A_PIN;motors[MOTOR_LEFT_FRONT].port_b = MOTOR1_B_PORT;motors[MOTOR_LEFT_FRONT].pin_b = MOTOR1_B_PIN;motors[MOTOR_LEFT_FRONT].tim = &MOTOR1_PWM_TIM;motors[MOTOR_LEFT_FRONT].channel = MOTOR1_PWM_CH;// 初始化右前电机(M2)motors[MOTOR_RIGHT_FRONT].port_a = MOTOR2_A_PORT;motors[MOTOR_RIGHT_FRONT].pin_a = MOTOR2_A_PIN;motors[MOTOR_RIGHT_FRONT].port_b = MOTOR2_B_PORT;motors[MOTOR_RIGHT_FRONT].pin_b = MOTOR2_B_PIN;motors[MOTOR_RIGHT_FRONT].tim = &MOTOR2_PWM_TIM;motors[MOTOR_RIGHT_FRONT].channel = MOTOR2_PWM_CH;// 初始化左后电机(M3)motors[MOTOR_LEFT_REAR].port_a = MOTOR3_A_PORT;motors[MOTOR_LEFT_REAR].pin_a = MOTOR3_A_PIN;motors[MOTOR_LEFT_REAR].port_b = MOTOR3_B_PORT;motors[MOTOR_LEFT_REAR].pin_b = MOTOR3_B_PIN;motors[MOTOR_LEFT_REAR].tim = &MOTOR3_PWM_TIM;motors[MOTOR_LEFT_REAR].channel = MOTOR3_PWM_CH;// 初始化右后电机(M4)motors[MOTOR_RIGHT_REAR].port_a = MOTOR4_A_PORT;motors[MOTOR_RIGHT_REAR].pin_a = MOTOR4_A_PIN;motors[MOTOR_RIGHT_REAR].port_b = MOTOR4_B_PORT;motors[MOTOR_RIGHT_REAR].pin_b = MOTOR4_B_PIN;motors[MOTOR_RIGHT_REAR].tim = &MOTOR4_PWM_TIM;motors[MOTOR_RIGHT_REAR].channel = MOTOR4_PWM_CH;// 初始化所有电机for (int i = 0; i < 4; i++) {motors[i].speed = 0;motors[i].direction = 0;// 设置方向引脚为停止状态HAL_GPIO_WritePin(motors[i].port_a, motors[i].pin_a, GPIO_PIN_RESET);HAL_GPIO_WritePin(motors[i].port_b, motors[i].pin_b, GPIO_PIN_RESET);// 设置PWM占空比为0__HAL_TIM_SET_COMPARE(motors[i].tim, motors[i].channel, 0);}#if DEBUG_ENABLEprintf("Motor Initialized\r\n");#endif
}/*** 设置电机速度*/
void Motor_SetSpeed(MotorID motor_id, uint16_t speed) {if (motor_id >= MOTOR_COUNT) return;// 限制速度范围if (speed > MOTOR_MAX_SPEED) speed = MOTOR_MAX_SPEED;motors[motor_id].speed = speed;// 更新PWM占空比__HAL_TIM_SET_COMPARE(motors[motor_id].tim, motors[motor_id].channel, speed);// 更新全局控制结构switch (motor_id) {case MOTOR_LEFT_FRONT:g_motor_control.speed_left_front = speed;break;case MOTOR_RIGHT_FRONT:g_motor_control.speed_right_front = speed;break;case MOTOR_LEFT_REAR:g_motor_control.speed_left_rear = speed;break;case MOTOR_RIGHT_REAR:g_motor_control.speed_right_rear = speed;break;}
}/*** 设置电机方向*/
void Motor_SetDirection(MotorID motor_id, uint8_t direction) {if (motor_id >= MOTOR_COUNT) return;motors[motor_id].direction = direction;switch (direction) {case 0:  // 停止HAL_GPIO_WritePin(motors[motor_id].port_a, motors[motor_id].pin_a, GPIO_PIN_RESET);HAL_GPIO_WritePin(motors[motor_id].port_b, motors[motor_id].pin_b, GPIO_PIN_RESET);break;case 1:  // 正转HAL_GPIO_WritePin(motors[motor_id].port_a, motors[motor_id].pin_a, GPIO_PIN_SET);HAL_GPIO_WritePin(motors[motor_id].port_b, motors[motor_id].pin_b, GPIO_PIN_RESET);break;case 2:  // 反转HAL_GPIO_WritePin(motors[motor_id].port_a, motors[motor_id].pin_a, GPIO_PIN_RESET);HAL_GPIO_WritePin(motors[motor_id].port_b, motors[motor_id].pin_b, GPIO_PIN_SET);break;case 3:  // 刹车HAL_GPIO_WritePin(motors[motor_id].port_a, motors[motor_id].pin_a, GPIO_PIN_SET);HAL_GPIO_WritePin(motors[motor_id].port_b, motors[motor_id].pin_b, GPIO_PIN_SET);break;}
}/*** 前进*/
void Motor_Forward(void) {for (int i = 0; i < 4; i++) {Motor_SetDirection(i, 1);}g_motor_control.direction = DIR_FORWARD;
}/*** 后退*/
void Motor_Backward(void) {for (int i = 0; i < 4; i++) {Motor_SetDirection(i, 2);}g_motor_control.direction = DIR_BACKWARD;
}/*** 左转*/
void Motor_TurnLeft(void) {// 左轮慢,右轮快Motor_SetSpeed(MOTOR_LEFT_FRONT, SPEED_TURN * 0.3);Motor_SetSpeed(MOTOR_LEFT_REAR, SPEED_TURN * 0.3);Motor_SetSpeed(MOTOR_RIGHT_FRONT, SPEED_TURN);Motor_SetSpeed(MOTOR_RIGHT_REAR, SPEED_TURN);for (int i = 0; i < 4; i++) {Motor_SetDirection(i, 1);}g_motor_control.direction = DIR_LEFT;
}/*** 右转*/
void Motor_TurnRight(void) {// 左轮快,右轮慢Motor_SetSpeed(MOTOR_LEFT_FRONT, SPEED_TURN);Motor_SetSpeed(MOTOR_LEFT_REAR, SPEED_TURN);Motor_SetSpeed(MOTOR_RIGHT_FRONT, SPEED_TURN * 0.3);Motor_SetSpeed(MOTOR_RIGHT_REAR, SPEED_TURN * 0.3);for (int i = 0; i < 4; i++) {Motor_SetDirection(i, 1);}g_motor_control.direction = DIR_RIGHT;
}/*** 急左转*/
void Motor_SharpLeft(void) {// 左轮反转,右轮正转Motor_SetDirection(MOTOR_LEFT_FRONT, 2);Motor_SetDirection(MOTOR_LEFT_REAR, 2);Motor_SetDirection(MOTOR_RIGHT_FRONT, 1);Motor_SetDirection(MOTOR_RIGHT_REAR, 1);Motor_SetSpeed(MOTOR_LEFT_FRONT, SPEED_TURN * 0.5);Motor_SetSpeed(MOTOR_LEFT_REAR, SPEED_TURN * 0.5);Motor_SetSpeed(MOTOR_RIGHT_FRONT, SPEED_TURN);Motor_SetSpeed(MOTOR_RIGHT_REAR, SPEED_TURN);g_motor_control.direction = DIR_LEFT;
}/*** 急右转*/
void Motor_SharpRight(void) {// 左轮正转,右轮反转Motor_SetDirection(MOTOR_LEFT_FRONT, 1);Motor_SetDirection(MOTOR_LEFT_REAR, 1);Motor_SetDirection(MOTOR_RIGHT_FRONT, 2);Motor_SetDirection(MOTOR_RIGHT_REAR, 2);Motor_SetSpeed(MOTOR_LEFT_FRONT, SPEED_TURN);Motor_SetSpeed(MOTOR_LEFT_REAR, SPEED_TURN);Motor_SetSpeed(MOTOR_RIGHT_FRONT, SPEED_TURN * 0.5);Motor_SetSpeed(MOTOR_RIGHT_REAR, SPEED_TURN * 0.5);g_motor_control.direction = DIR_RIGHT;
}/*** 停止*/
void Motor_Stop(void) {for (int i = 0; i < 4; i++) {Motor_SetSpeed(i, 0);Motor_SetDirection(i, 0);}g_motor_control.direction = DIR_STOP;
}/*** 刹车*/
void Motor_Brake(void) {for (int i = 0; i < 4; i++) {Motor_SetDirection(i, 3);  // 刹车模式}g_motor_control.direction = DIR_STOP;
}/*** 设置所有电机速度*/
void Motor_SetAllSpeed(uint16_t left_front, uint16_t right_front, uint16_t left_rear, uint16_t right_rear) {Motor_SetSpeed(MOTOR_LEFT_FRONT, left_front);Motor_SetSpeed(MOTOR_RIGHT_FRONT, right_front);Motor_SetSpeed(MOTOR_LEFT_REAR, left_rear);Motor_SetSpeed(MOTOR_RIGHT_REAR, right_rear);
}/*** 获取电机速度*/
uint16_t Motor_GetSpeed(MotorID motor_id) {if (motor_id >= MOTOR_COUNT) return 0;return motors[motor_id].speed;
}/*** 获取电机方向*/
uint8_t Motor_GetDirection(MotorID motor_id) {if (motor_id >= MOTOR_COUNT) return 0;return motors[motor_id].direction;
}

参考代码 stm32f103c8t6单片机设计四驱智能小车寻迹软件 www.youwenfan.com/contentcnt/183172.html

4. 传感器模块 (sensor.c)

/*** 传感器模块*/#include "sensor.h"
#include "config.h"// 传感器权重(用于计算位置)
static const int8_t sensor_weights[5] = {-2, -1, 0, 1, 2};/*** 读取所有传感器*/
void Sensor_ReadAll(void) {static ADC_HandleTypeDef hadc1;// 启动ADC转换HAL_ADC_Start(&hadc1);// 等待转换完成if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {// 读取5个通道的值g_sensor_data.sensor_values[0] = HAL_ADC_GetValue(&hadc1);g_sensor_data.sensor_values[1] = HAL_ADC_GetValue(&hadc1);g_sensor_data.sensor_values[2] = HAL_ADC_GetValue(&hadc1);g_sensor_data.sensor_values[3] = HAL_ADC_GetValue(&hadc1);g_sensor_data.sensor_values[4] = HAL_ADC_GetValue(&hadc1);}HAL_ADC_Stop(&hadc1);
}/*** 处理传感器数据*/
void Sensor_Process(void) {int8_t line_position = 0;uint8_t sensor_count = 0;uint8_t all_white = 1;uint8_t all_black = 1;// 处理每个传感器for (int i = 0; i < SENSOR_COUNT; i++) {// 判断传感器状态if (g_sensor_data.sensor_values[i] > SENSOR_THRESHOLD) {g_sensor_data.sensor_states[i] = 1;  // 黑线all_white = 0;// 计算加权位置line_position += sensor_weights[i];sensor_count++;} else {g_sensor_data.sensor_states[i] = 0;  // 白线all_black = 0;}}// 计算平均位置if (sensor_count > 0) {g_sensor_data.line_position = line_position / sensor_count;} else {g_sensor_data.line_position = 0;}// 判断循迹状态if (all_white) {// 所有传感器都检测到白线,可能丢失轨迹g_sensor_data.trace_state = TRACE_LOST;g_sensor_data.lost_count++;} else if (all_black) {// 所有传感器都检测到黑线,可能是十字路口g_sensor_data.trace_state = TRACE_CROSSROAD;g_sensor_data.lost_count = 0;} else {// 根据传感器状态判断uint8_t pattern = 0;for (int i = 0; i < SENSOR_COUNT; i++) {pattern |= (g_sensor_data.sensor_states[i] << i);}switch (pattern) {// 中间传感器检测到黑线case 0b00100:  // 只有中间传感器case 0b00110:  // 中间两个case 0b00010:  // 右中case 0b00100:  // 中间case 0b01000:  // 左中g_sensor_data.trace_state = TRACE_ON_LINE;break;// 左转弯case 0b11000:  // 最左+左中case 0b10000:  // 最左case 0b01000:  // 左中g_sensor_data.trace_state = TRACE_TURN_LEFT;break;// 右转弯case 0b00011:  // 右中+最右case 0b00001:  // 最右case 0b00010:  // 右中g_sensor_data.trace_state = TRACE_TURN_RIGHT;break;// 掉头case 0b11111:  // 全部g_sensor_data.trace_state = TRACE_TURN_AROUND;break;default:g_sensor_data.trace_state = TRACE_ON_LINE;break;}g_sensor_data.lost_count = 0;}
}/*** 获取传感器原始值*/
uint16_t Sensor_GetRawValue(uint8_t sensor_id) {if (sensor_id >= SENSOR_COUNT) return 0;return g_sensor_data.sensor_values[sensor_id];
}/*** 获取传感器状态*/
uint8_t Sensor_GetState(uint8_t sensor_id) {if (sensor_id >= SENSOR_COUNT) return 0;return g_sensor_data.sensor_states[sensor_id];
}/*** 获取轨迹位置*/
int8_t Sensor_GetLinePosition(void) {return g_sensor_data.line_position;
}/*** 获取循迹状态*/
TraceState Sensor_GetTraceState(void) {return g_sensor_data.trace_state;
}/*** 是否丢失轨迹*/
uint8_t Sensor_IsLost(void) {return (g_sensor_data.trace_state == TRACE_LOST);
}/*** 获取丢失计数*/
uint32_t Sensor_GetLostCount(void) {return g_sensor_data.lost_count;
}/*** 打印传感器状态(调试用)*/
void Sensor_PrintStatus(void) {#if DEBUG_ENABLEprintf("Sensors: ");for (int i = 0; i < SENSOR_COUNT; i++) {printf("[%d:%d:%d] ", i, g_sensor_data.sensor_values[i], g_sensor_data.sensor_states[i]);}printf(" Pos:%d State:%d\r\n", g_sensor_data.line_position, g_sensor_data.trace_state);#endif
}

5. PID控制器 (pid.c)

/*** PID控制器模块*/#include "pid.h"
#include "config.h"/*** PID初始化*/
void PID_Init(PIDController* pid, float kp, float ki, float kd, float max_output) {pid->Kp = kp;pid->Ki = ki;pid->Kd = kd;pid->error = 0;pid->integral = 0;pid->derivative = 0;pid->last_error = 0;pid->output = 0;pid->max_output = max_output;
}/*** PID计算*/
float PID_Calculate(PIDController* pid, float setpoint, float actual, float dt) {// 计算误差pid->error = setpoint - actual;// 计算积分项(带抗饱和)pid->integral += pid->error * dt;// 积分限幅if (pid->integral > pid->max_output) {pid->integral = pid->max_output;} else if (pid->integral < -pid->max_output) {pid->integral = -pid->max_output;}// 计算微分项pid->derivative = (pid->error - pid->last_error) / dt;// 计算输出pid->output = (pid->Kp * pid->error) + (pid->Ki * pid->integral) + (pid->Kd * pid->derivative);// 输出限幅if (pid->output > pid->max_output) {pid->output = pid->max_output;} else if (pid->output < -pid->max_output) {pid->output = -pid->max_output;}// 保存当前误差pid->last_error = pid->error;return pid->output;
}/*** PID重置*/
void PID_Reset(PIDController* pid) {pid->error = 0;pid->integral = 0;pid->derivative = 0;pid->last_error = 0;pid->output = 0;
}/*** 设置PID参数*/
void PID_SetParameters(PIDController* pid, float kp, float ki, float kd) {pid->Kp = kp;pid->Ki = ki;pid->Kd = kd;
}/*** 获取PID输出*/
float PID_GetOutput(PIDController* pid) {return pid->output;
}

6. 控制算法 (control.c)

/*** 控制算法模块*/#include "control.h"
#include "config.h"// 循迹状态机
static uint8_t g_trace_state = 0;
static uint32_t g_last_lost_time = 0;/*** 普通循迹控制*/
void Control_Normal(void) {// 获取传感器状态uint8_t s1 = Sensor_GetState(0);  // 最左uint8_t s2 = Sensor_GetState(1);  // 左中uint8_t s3 = Sensor_GetState(2);  // 中间uint8_t s4 = Sensor_GetState(3);  // 右中uint8_t s5 = Sensor_GetState(4);  // 最右// 根据传感器状态控制小车if (s3 == 1) {// 中间传感器检测到黑线,直行Motor_Forward();Motor_SetSpeed(MOTOR_LEFT_FRONT, SPEED_NORMAL);Motor_SetSpeed(MOTOR_RIGHT_FRONT, SPEED_NORMAL);Motor_SetSpeed(MOTOR_LEFT_REAR, SPEED_NORMAL);Motor_SetSpeed(MOTOR_RIGHT_REAR, SPEED_NORMAL);} else if (s2 == 1 || s1 == 1) {// 左侧传感器检测到黑线,左转Motor_TurnLeft();}else if (s4 == 1 || s5 == 1) {// 右侧传感器检测到黑线,右转Motor_TurnRight();}else if (s1 == 1 && s5 == 1) {// 两侧传感器都检测到黑线,可能是十字路口,直行Motor_Forward();Motor_SetAllSpeed(SPEED_NORMAL, SPEED_NORMAL, SPEED_NORMAL, SPEED_NORMAL);}else {// 没有检测到黑线,尝试寻找Control_FindLine();}
}/*** PID循迹控制*/
int16_t Control_PID(void) {static uint32_t last_time = 0;uint32_t current_time = HAL_GetTick();float dt = (current_time - last_time) / 1000.0f;  // 转换为秒if (dt == 0) dt = 0.01f;  // 避免除零// 获取当前位置(误差)float current_position = Sensor_GetLinePosition();// PID计算float pid_output = PID_Calculate(&g_pid_controller, 0, current_position, dt);last_time = current_time;return (int16_t)pid_output;
}/*** 高级循迹控制(带避障)*/
void Control_Advanced(void) {// 检查障碍物if (Control_CheckObstacle()) {// 检测到障碍物,避障Control_AvoidObstacle();return;}// 正常循迹Control_PID();
}/*** 寻找轨迹*/
void Control_FindLine(void) {static uint8_t search_direction = 0;  // 0:左转, 1:右转static uint32_t search_start_time = 0;uint32_t current_time = HAL_GetTick();if (g_trace_state == 0) {// 开始寻找search_start_time = current_time;g_trace_state = 1;search_direction = 0;  // 先向左转#if DEBUG_ENABLEprintf("Start searching line...\r\n");#endif}if (current_time - search_start_time < 1000) {// 向左转寻找1秒if (search_direction == 0) {Motor_SharpLeft();} else {Motor_SharpRight();}} else if (current_time - search_start_time < 2000) {// 向右转寻找1秒if (search_direction == 0) {Motor_SharpRight();search_direction = 1;} else {Motor_SharpLeft();search_direction = 0;}}else {// 寻找超时,停止Motor_Stop();g_car_info.state = CAR_STATE_ERROR;#if DEBUG_ENABLEprintf("Line search timeout!\r\n");#endif}// 检查是否找到轨迹if (!Sensor_IsLost()) {g_trace_state = 0;#if DEBUG_ENABLEprintf("Line found!\r\n");#endif}
}/*** 检查障碍物*/
uint8_t Control_CheckObstacle(void) {// 这里可以添加超声波或红外避障传感器检测// 简化实现:返回0return 0;
}/*** 避障算法*/
void Control_AvoidObstacle(void) {// 避障算法实现// 1. 停止Motor_Stop();HAL_Delay(500);// 2. 后退Motor_Backward();Motor_SetAllSpeed(SPEED_SLOW, SPEED_SLOW, SPEED_SLOW, SPEED_SLOW);HAL_Delay(300);// 3. 左转Motor_SharpLeft();HAL_Delay(500);// 4. 前进Motor_Forward();Motor_SetAllSpeed(SPEED_NORMAL, SPEED_NORMAL, SPEED_NORMAL, SPEED_NORMAL);HAL_Delay(800);// 5. 右转Motor_SharpRight();HAL_Delay(500);// 6. 继续前进Motor_Forward();
}/*** 处理十字路口*/
void Control_HandleCrossroad(void) {static uint8_t crossroad_count = 0;// 十字路口处理策略// 可以根据需要实现左转、右转、直行// 默认直行Motor_Forward();Motor_SetAllSpeed(SPEED_FAST, SPEED_FAST, SPEED_FAST, SPEED_FAST);HAL_Delay(300);crossroad_count++;#if DEBUG_ENABLEprintf("Crossroad passed: %d\r\n", crossroad_count);#endif
}/*** 急弯处理*/
void Control_HandleSharpTurn(void) {TraceState trace_state = Sensor_GetTraceState();if (trace_state == TRACE_TURN_LEFT) {// 急左转Motor_SharpLeft();HAL_Delay(200);} else if (trace_state == TRACE_TURN_RIGHT) {// 急右转Motor_SharpRight();HAL_Delay(200);}
}/*** 速度控制*/
void Control_SpeedAdjust(uint8_t condition) {switch (condition) {case 0:  // 直线加速g_car_info.base_speed = SPEED_FAST;break;case 1:  // 转弯减速g_car_info.base_speed = SPEED_TURN;break;case 2:  // 复杂路况慢速g_car_info.base_speed = SPEED_SLOW;break;default:g_car_info.base_speed = SPEED_NORMAL;break;}
}

7. 串口调试 (uart.c)

/*** 串口调试模块*/#include "uart.h"
#include "config.h"UART_HandleTypeDef huart1;/*** 串口初始化*/
void UART_Init(uint32_t baudrate) {huart1.Instance = USART1;huart1.Init.BaudRate = baudrate;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;// 使能USART1时钟__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();// 配置GPIOGPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 初始化UARTif (HAL_UART_Init(&huart1) != HAL_OK) {Error_Handler();}printf("UART Initialized: %lu baud\r\n", baudrate);
}/*** 重定向printf到串口*/
#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endifPUTCHAR_PROTOTYPE {HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}

引脚分配表

引脚 功能 说明
PA0 传感器1 最左侧循迹传感器
PA1 传感器2 左侧循迹传感器
PA2 传感器3 中间循迹传感器
PA3 传感器4 右侧循迹传感器
PA4 传感器5 最右侧循迹传感器
PA5 启动按键 开始/暂停
PA6 模式按键 切换循迹模式
PA8 蜂鸣器 状态提示音
PB6 电机1A 左前电机方向A
PB7 电机1B 左前电机方向B
PB8 电机2A 右前电机方向A
PB9 电机2B 右前电机方向B
PB10 电机3A 左后电机方向A
PB11 电机3B 左后电机方向B
PB12 电机4A 右后电机方向A
PB13 电机4B 右后电机方向B
PC13 运行LED 系统运行指示
PC14 错误LED 错误状态指示
PC15 循迹LED 循迹状态指示

使用说明

1. 编译和烧录

# 使用Keil MDK
1. 打开工程文件 SmartCar.uvprojx
2. 设置目标设备为 STM32F103C8T6
3. 编译工程 (F7)
4. 使用ST-Link烧录 (F8)# 使用STM32CubeIDE
1. 导入工程
2. 选择正确的芯片型号
3. 编译并运行

2. 操作说明

  • 启动按键: 长按启动小车,短按暂停/继续
  • 模式按键: 切换循迹模式(普通/PID/高级)
  • 运行LED: 系统正常运行指示灯,1Hz闪烁
  • 循迹LED: 检测到轨迹时亮起
  • 错误LED: 系统错误时亮起

3. 调试信息

通过串口(115200bps)可查看调试信息:

=== Debug Info ===
State: 2, Mode: 1
Run Time: 120s, Distance: 50m
Line Pos: 0, Trace State: 1
Motor: LF=1200, RF=1200, LR=1200, RR=1200
PID Output: 0.00
==================

参数调优

1. PID参数调优

// 在config.h中修改
#define PID_KP   2.0f   // 增大:响应更快但易震荡
#define PID_KI   0.1f   // 增大:消除稳态误差
#define PID_KD   1.5f   // 增大:抑制超调

2. 传感器阈值校准

// 在config.h中修改
#define SENSOR_THRESHOLD 500
// 实际值需要根据传感器安装高度和地面颜色调整

3. 速度参数调整

// 在config.h中修改
#define MOTOR_BASE_SPEED 1000
#define SPEED_SLOW       800
#define SPEED_FAST       1600
#define SPEED_TURN       1000

扩展功能建议

  1. 蓝牙遥控: 添加HC-05模块实现手机控制
  2. OLED显示: 添加0.96寸OLED显示状态信息
  3. 超声波避障: 添加HC-SR04模块实现自动避障
  4. MPU6050: 添加姿态传感器实现更精准控制
  5. 编码器测速: 添加光电编码器实现闭环速度控制
  6. WiFi摄像头: 添加ESP32-CAM实现视频传输
http://www.jsqmd.com/news/672195/

相关文章:

  • 市场价值预测:时间序列分析的实践
  • Liunx创建挂载步骤
  • 2026 年 AI 应用开发学习路线:从入门到精通,6 个月速成实战指南
  • OneForAll学习指南
  • Maven私服部署避坑指南:除了用户名密码,你的pom.xml和settings.xml里这个‘id’标签配对了么?
  • 1.AI不是魔法:一文看懂人工智能的“前世今生”
  • 非CS专业也能玩转!用OpenMV和Python实现板球平衡系统(附完整代码与PID调参心得)
  • 速腾聚创雷达点云秒变Velodyne格式:一个ROS节点搞定SLAM算法适配(Ubuntu18.04实测)
  • 一镜通古今:Rokid AI Glasses 驱动的古建筑文物全流程智能讲解终端
  • 别再只会写代码了!Pycharm 2023.3主界面这6个隐藏功能,让你效率翻倍
  • 第2课-Python基础回顾
  • 新手司机也能懂:你的车在偷偷保护你?聊聊ESP里的ABS、TCS和VDC都是啥
  • 氨基化MIL-53包覆四氧化三铁纳米颗粒,NH₂-MIL-53@Fe₃O₄ NPs,化学结构特点
  • 构建专业级视频门户:MediaCMS如何解决现代媒体管理痛点
  • 技术深度解析:如何通过OmenSuperHub精准控制惠普游戏本硬件性能
  • 81.1 AP!ViTPose:免费开源的视觉Transformer人体姿态估计完整解决方案
  • Pixel Aurora Engine 工作流自动化:与GitHub Actions集成实现每日自动绘图
  • 一种废弃打印纸可用区域的自动识别和再利用方法
  • 别再死记硬背Flex属性了!用这5个真实网页布局案例,带你彻底搞懂CSS Flexbox
  • Python自动化生成目录树:快速了解项目结构的利器
  • 深圳几百人团建|佳天下:安全・定制・透明・省心 - 佳天下国旅
  • 【百例RUST - 013】泛型
  • 3分钟快速搞定GitHub终极加速:免费插件让下载速度飙升10倍
  • 黑苹果完整安装指南:从零开始构建macOS系统
  • 在ruoyi vue v3.8.2 实现后端单表user 的CURD 功能代码和Postman 测试接口
  • 告别CasADi的慢速:用ACADOS在Python里10倍速搞定移动机器人MPC(附避坑配置)
  • Python自动化文件批量格式转换工具
  • 谷歌:强化学习实现参数化知识重组
  • 企业老板血泪教训!裁掉一半业务员,40万高端货凭空消失,内控漏洞差点拖垮公司
  • VS2022全局搜索失效