基于STM32的智能循迹避障小车技术指南
智能循迹避障小车技术文章大纲
一、引言
在物联网与智能硬件快速发展的今天,智能巡检小车作为一种高效的自动化设备,广泛应用于工业检测、安防监控、环境监测等场景。本文将详细介绍一款基于 STM32F103C8T6 微控制器的智能巡检小车项目,该小车具备LED 状态指示、循迹避障、超声波测距、图像采集等核心功能,适合作为嵌入式开发入门的实践案例。(小编是一名大学生,参加学校和企业的项目实践,经过两周的学习与设计开发,内容会有遗漏、错误,请您见谅。)
二、硬件架构与核心器件
-
主控芯片:STM32F103C8T6
主控芯片采用意法半导体(STMicroelectronics)公司生产的STM32F103C8T6,这是一款基于ARM Cortex-M3内核的32位微控制器。该芯片具有72MHz的主频,内置64KB的Flash存储器和20KB的SRAM,支持多种外设接口,包括2个SPI、2个I2C、3个USART、1个USB和1个CAN总线。STM32F103C8T6广泛应用于工业控制、消费电子、智能家居和物联网等领域,其高性能和低功耗特性使其成为嵌入式系统开发的理想选择。此外,该芯片还支持多种开发工具和软件库,如STM32CubeMX和HAL库,极大地简化了开发流程,提高了开发效率。
- 关键外设配置
- 超声波测距
-
功能:检测前方障碍物距离,触发避障逻辑。
-
硬件配置:模块型号:HC-SR04(TRIG 触发引脚、ECHO 回声引脚)。
-
模块型号:HC-SR04(TRIG 触发引脚、ECHO 回声引脚)。
-
定时器:
-
TIM6:周期 500ms,触发测距(预分频器
7199,周期4999,计数频率 10kHz)。 -
TIM7:精确计时 20μs 脉冲(预分频器
0,周期1439,计数频率 72MHz)。
-
-
引脚:
-
TRIG:连接 STM32 GPIO(如
TRIG_GPIO、TRIG_PIN)。 -
ECHO:连接外部中断引脚(如
ECHO_PIN),通过HAL_GPIO_EXTI_Callback检测脉冲边沿
- 超声波测距
-
功能
检测地面黑线,实现循迹行驶。
-
传感器:红外发射 – 接收对管(如 TCRT5000),连接 STM32 GPIO。
-
引脚:
-
左红外:
PA7(检测左侧黑线,高电平有效)。 -
右红外:
PA6(检测右侧黑线,高电平有效)。
-
功能
控制小车运动(前进、后退、转向、调速)。
-
电机驱动:L298N 电机驱动模块,连接 STM32 定时器 PWM 引脚。
-
定时器:TIM2(通道 1、4 输出 PWM,控制左右电机速度)。
-
引脚:
-
左电机方向:
LEFT1_PIN、LEFT2_PIN(正转 / 反转)。 -
右电机方向:
RIGHT1_PIN、RIGHT2_PIN(正转 / 反转)。 -
PWM 输出:TIM2_CH1(左电机速度)、TIM2_CH4(右电机速度)。
LED 指示灯
-
功能
显示小车状态(如行驶方向、故障提示)。
硬件配置
-
LED 类型:红绿蓝三色 LED,独立控制。
-
引脚:
-
绿灯:
G_LED_PIN(低电平点亮)。 -
蓝灯:
B_LED_PIN(低电平点亮)。 -
红灯:
R_LED_PIN(低电平点亮)。
USB 摄像头
-
功能
采集图像,实现视觉检测(如人脸检测)。
硬件配置
-
摄像头:USB 网络摄像头(支持 RTSP 协议),URL:
http://admin:admin@10.150.44.188:8081/video。 -
软件框架:Qt + OpenCV,通过
cv::VideoCapture读取视频流。
三、软件设计与核心代码解析
-
感知层组件
- 红外传感器阵列排布方案(左中、右中)
- 无障碍物时(
distance > 20cm),读取红外引脚状态: -
左侧黑线(PA7 高):右转(调整方向)。
-
右侧黑线(PA6 高):左转(调整方向)。
-
中间 / 无黑线:直行。
// 如果没有障碍物,执行循迹功能 if(distence > 10 || distence == 0) { // 这里循迹代码 PA6_P = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6); PA7_P = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7); // 循迹逻辑 if(PA6_P == GPIO_PIN_SET && PA7_P == GPIO_PIN_RESET) { // 右侧检测到线,左转 left(); } else if(PA7_P == GPIO_PIN_SET && PA6_P == GPIO_PIN_RESET) { // 左侧检测到线,右转 right(); } else { // 直行 gogogo(); } - 超声波测距模块(车头中间位置)
-
测距流程:
-
TIM6 定时触发,TRIG 引脚拉高 20μs(通过 TIM7 精确控制)。
-
ECHO 上升沿记录开始时间(
count1),下降沿记录结束时间(count2),计算时间差Δt = count2 - count1。 -
距离公式:
distance = Δt × 17 / 10(单位:cm,声速简化为 340m/s)。 -
避障函数:
-
当
distance ≤ 20cm时,调用avoid_obstacle,执行 “停止→后退→右转→前进” 逻辑。// 避障函数 void avoid_obstacle(void) { if(distence <= 20 && distence > 0) // 检测到障碍物 { printf("检测到障碍物,距离:%d cm,执行避障\n", distence); // 1. 停止 stop(); HAL_Delay(2000); // 2. 后退一段距离 backward(); HAL_Delay(2500); // 3. 右转 right(); HAL_Delay(4000); // 4. 继续前进 gogogo(); HAL_Delay(5000); //5.左转 left(); HAL_Delay(5000); //6. 继续前进 gogogo(); HAL_Delay(4000); } } - 视觉传感器配置(QT)
-
执行机构
- 电机驱动电路设计
-
速度控制:
-
通过
set_compare(left, right)函数设置 PWM 占空比(如set_compare(120, 133)表示左电机占空比 120,右电机 133)。/设置占空比,控制速度 参数:比较寄存器的值 void set_compare(int left,int right) { __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,left); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,right); } -
运动函数:
-
直行:左右电机正转,PWM 差异调整速度同步。
-
左转:左电机反转、右电机正转(差速转向)。
-
右转:右电机反转、左电机正转(差速转向)。
-
后退:左右电机反转。
void gogogo(void) //直行 { //1.配置速度 set_compare(120,133); //set_compare(150,165); //2.电机转动方向 HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET); // 新增:直行亮绿灯 control_led(0); } void left(void) //左转 { HAL_Delay(200); //1.配置速度 // set_compare(60,145); set_compare(130,153); //2.电机转动方向 // HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET); // HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET); // 新增:转向亮蓝灯 control_led(1); } void right(void) //右转 { HAL_Delay(200); //1.配置速度 // set_compare(130,60); set_compare(153,130); //2.电机转动方向 HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET); // HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET); // HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_SET); // 新增:转向亮蓝灯 control_led(1); } void stop(void) //停止 { //1.配置速度 set_compare(0,0); //2.电机转动方向 HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET); // 新增:停止时关闭所有灯(保持原有逻辑) control_led(0); // 调用函数关闭所有灯 } void backward(void) //后退 { //1.配置速度 set_compare(120,133); //set_compare(155,175); //2.电机转动方向 HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_SET); HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_RESET); HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_SET); // 新增:后退亮红灯 control_led(2); } - LED展示不同状态
void control_led(uint8_t state) { led_state = state; // 关闭所有LED HAL_GPIO_WritePin(G_LED_GPIO, G_LED_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(B_LED_GPIO, B_LED_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(R_LED_GPIO, R_LED_PIN, GPIO_PIN_SET); switch(state) { case 0: // 绿灯 HAL_GPIO_WritePin(G_LED_GPIO, G_LED_PIN, GPIO_PIN_RESET); break; case 1: // 蓝灯 HAL_GPIO_WritePin(B_LED_GPIO, B_LED_PIN, GPIO_PIN_RESET); break; case 2: // 红灯 HAL_GPIO_WritePin(R_LED_GPIO, R_LED_PIN, GPIO_PIN_RESET); break; default: break; } }
四、软件算法实现
-
循迹控制算法
- 红外传感器数据处理
void trace_control() { if (line_state == 0b01) { // 右侧压线,需左转 set_compare(130, 153); // 左电机加速,右电机减速(差速左转) } else if (line_state == 0b10) { // 左侧压线,需右转 set_compare(100, 120); // 右电机加速,左电机减速(差速右转) } else { set_compare(120, 133); // 直行速度(左右电机略有差异补偿机械误差) } } - 红外传感器数据传输
// 初始化GPIO为输入模式(上拉电阻使能) GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉电阻消除悬空噪声 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); -
避障决策系统
void avoid_obstacle() { if (filter_distance() ≤ 20) { // 有效障碍物 stop(); // 紧急制动 HAL_Delay(1000); backward(); // 后退 HAL_Delay(2000); right(); // 右转避障(可改为随机左/右转) HAL_Delay(7000); gogogo(); // 恢复行驶 } }
五、实验与测试
-
测试环境构建
- 标准测试赛道设计
- 环形封闭赛道测试
- 障碍物场景模拟
- 在赛道上放障碍物
-
性能评估指标
- 循迹横向偏差
- 根据小车以及路面情况调整函数参考值,车辆电机的实际情况可能不同
- 急停响应时间
- 最小避障距离
-
实验结果分析
六、总代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
//led
#define R_LED_GPIO GPIOB
#define R_LED_PIN GPIO_PIN_8
#define G_LED_GPIO GPIOB
#define G_LED_PIN GPIO_PIN_6
#define B_LED_GPIO GPIOB
#define B_LED_PIN GPIO_PIN_7 // 修正蓝灯引脚为GPIO_PIN_7
//电机
#define LEFT1_GPIO GPIOA
#define LEFT1_PIN GPIO_PIN_2
#define LEFT2_GPIO GPIOB
#define LEFT2_PIN GPIO_PIN_9
#define RIGHT1_GPIO GPIOC
#define RIGHT1_PIN GPIO_PIN_9
#define RIGHT2_GPIO GPIOA
#define RIGHT2_PIN GPIO_PIN_1
//超声波
#define TRIG_GPIO GPIOD
#define TRIG_PIN GPIO_PIN_2
#define ECHO_GPIO GPIOB
#define ECHO_PIN GPIO_PIN_3
volatile uint8_t printFlag = 0; // 全局变量,用于标志需要打印
int distence = 0;
int count1 = 0;
int count2 = 0;
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 新增LED控制变量
static uint8_t led_state = 0; // 0:绿灯 1:蓝灯 2:红灯
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// 新增LED控制函数
void control_led(uint8_t state) {
led_state = state;
// 关闭所有LED
HAL_GPIO_WritePin(G_LED_GPIO, G_LED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(B_LED_GPIO, B_LED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(R_LED_GPIO, R_LED_PIN, GPIO_PIN_SET);
switch(state) {
case 0: // 绿灯
HAL_GPIO_WritePin(G_LED_GPIO, G_LED_PIN, GPIO_PIN_RESET);
break;
case 1: // 蓝灯
HAL_GPIO_WritePin(B_LED_GPIO, B_LED_PIN, GPIO_PIN_RESET);
break;
case 2: // 红灯
HAL_GPIO_WritePin(R_LED_GPIO, R_LED_PIN, GPIO_PIN_RESET);
break;
default:
break;
}
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim6)//定时器6的时间到了产生事件
{
HAL_GPIO_TogglePin(B_LED_GPIO, B_LED_PIN);
//开启超声波
//trig引脚拉高
HAL_GPIO_WritePin(TRIG_GPIO,TRIG_PIN,GPIO_PIN_SET);
//以中断的方式打开定时器7
HAL_TIM_Base_Start_IT(&htim7);
}
/*
超声波拉高20微秒
*/
if(htim == &htim7)
{
//关闭定时器7
HAL_TIM_Base_Stop_IT(&htim7);
//拉低trig的引脚
HAL_GPIO_WritePin(TRIG_GPIO,TRIG_PIN,GPIO_PIN_RESET);
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == ECHO_PIN)
{
//判断是否为上升沿触发
// 读取ECHO引脚的电平状态
GPIO_PinState echo_state = HAL_GPIO_ReadPin(ECHO_GPIO, ECHO_PIN);
if(echo_state == GPIO_PIN_SET)
{
count1 = __HAL_TIM_GET_COUNTER(&htim6);
}
else
{
count2 = __HAL_TIM_GET_COUNTER(&htim6);
distence = (count2 - count1) * 17 / 10; //单位:cm
printFlag = 1;
}
}
}
//printf()函数使用
int fputc(int ch, FILE*f)
{
uint8_t temp = ch;
HAL_UART_Transmit(&huart1,&temp,1,HAL_MAX_DELAY);
return ch;
}
//设置占空比,控制速度 参数:比较寄存器的值
void set_compare(int left,int right)
{
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,left);
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,right);
}
void gogogo(void) //直行
{
//1.配置速度
set_compare(120,133);
//set_compare(150,165);
//2.电机转动方向
HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET);
// 新增:直行亮绿灯
control_led(0);
}
void left(void) //左转
{
HAL_Delay(200);
//1.配置速度
// set_compare(60,145);
set_compare(130,153);
//2.电机转动方向
// HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET);
// HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET);
// 新增:转向亮蓝灯
control_led(1);
}
void right(void) //右转
{
HAL_Delay(200);
//1.配置速度
// set_compare(130,60);
set_compare(153,130);
//2.电机转动方向
HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET);
// HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET);
// HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_SET);
// 新增:转向亮蓝灯
control_led(1);
}
void stop(void) //停止
{
//1.配置速度
set_compare(0,0);
//2.电机转动方向
HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_RESET);
// 新增:停止时关闭所有灯(保持原有逻辑)
control_led(0); // 调用函数关闭所有灯
}
void backward(void) //后退
{
//1.配置速度
set_compare(120,133);
//set_compare(155,175);
//2.电机转动方向
HAL_GPIO_WritePin(LEFT1_GPIO,LEFT1_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(LEFT2_GPIO,LEFT2_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RIGHT1_GPIO,RIGHT1_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RIGHT2_GPIO,RIGHT2_PIN,GPIO_PIN_SET);
// 新增:后退亮红灯
control_led(2);
}
// 避障函数
void avoid_obstacle(void)
{
if(distence <= 20 && distence > 0) // 检测到障碍物
{
printf("检测到障碍物,距离:%d cm,执行避障\n", distence);
// 1. 停止
stop();
HAL_Delay(2000);
// 2. 后退一段距离
backward();
HAL_Delay(2500);
// 3. 右转
right();
HAL_Delay(4000);
// 4. 继续前进
gogogo();
HAL_Delay(5000);
//5.左转
left();
HAL_Delay(5000);
//6. 继续前进
gogogo();
HAL_Delay(4000);
// //7.you转
// right();
// HAL_Delay(3000);
//8.直行
// gogogo();
// HAL_Delay(3000);
// //右转
// right();
// HAL_Delay(7000);
// //8.直行
// gogogo();
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM6_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM7_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
//关闭所有灯(初始状态)
HAL_GPIO_WritePin(G_LED_GPIO, G_LED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(B_LED_GPIO, B_LED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(R_LED_GPIO, R_LED_PIN, GPIO_PIN_SET);
//启动定时器
HAL_TIM_Base_Start_IT(&htim6);
//启动占空比
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
uint8_t data=0;
GPIO_PinState PA6_P;
GPIO_PinState PA7_P;
/*
检查引脚复用冲突
STM32的PB3默认可能用于JTAG功能(如SWO信号),需禁用JTAG释放引脚。
*/
__HAL_AFIO_REMAP_SWJ_DISABLE(); // 禁用JTAG/SWD
// 或仅释放PB3
//__HAL_AFIO_REMAP_SWJ_NOJTAG(); // PB3作为普通GPIO使用
while (1)
{
HAL_Delay(500);
if (printFlag)
{
printf("距离:%d \n",distence);
printFlag = 0; // 清除标志
}
avoid_obstacle();
// 如果没有障碍物,执行循迹功能
if(distence > 10 || distence == 0)
{
// 这里循迹代码
PA6_P = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6);
PA7_P = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7);
// 循迹逻辑
if(PA6_P == GPIO_PIN_SET && PA7_P == GPIO_PIN_RESET)
{
// 右侧检测到线,左转
left();
}
else if(PA7_P == GPIO_PIN_SET && PA6_P == GPIO_PIN_RESET)
{
// 左侧检测到线,右转
right();
}
else
{
// 直行
gogogo();
}
}
HAL_UART_Transmit(&huart1,&data,1,HAL_MAX_DELAY);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
七、总结与展望
- 项目成果总结
- 循迹避障测试
V20250516-140715
- 人脸识别
- 循迹避障测试
- 技术难点突破
附录
- 关键代码片段示例
作者:SCX404