基于STM32的智能循迹避障小车技术指南

智能循迹避障小车技术文章大纲

一、引言

     在物联网与智能硬件快速发展的今天,智能巡检小车作为一种高效的自动化设备,广泛应用于工业检测、安防监控、环境监测等场景。本文将详细介绍一款基于 STM32F103C8T6 微控制器的智能巡检小车项目,该小车具备LED 状态指示、循迹避障、超声波测距、图像采集等核心功能,适合作为嵌入式开发入门的实践案例。(小编是一名大学生,参加学校和企业的项目实践,经过两周的学习与设计开发,内容会有遗漏、错误,请您见谅。)

二、硬件架构与核心器件
  1. 主控芯片: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库,极大地简化了开发流程,提高了开发效率。​​​​​

  2. 关键外设配置
    1. 超声波测距
      1. 功能:检测前方障碍物距离,触发避障逻辑。

      2. 硬件配置:模块型号:HC-SR04(TRIG 触发引脚、ECHO 回声引脚)。

      3. 模块型号:HC-SR04(TRIG 触发引脚、ECHO 回声引脚)。

      4. 定时器:

      5. TIM6:周期 500ms,触发测距(预分频器7199,周期4999,计数频率 10kHz)。

      6. TIM7:精确计时 20μs 脉冲(预分频器0,周期1439,计数频率 72MHz)。

      7. 引脚:

      8. TRIG:连接 STM32 GPIO(如TRIG_GPIOTRIG_PIN)。

      9. ECHO:连接外部中断引脚(如ECHO_PIN),通过HAL_GPIO_EXTI_Callback检测脉冲边沿

    2. 红外对管
      1. 功能

        检测地面黑线,实现循迹行驶。

      2. 传感器:红外发射 – 接收对管(如 TCRT5000),连接 STM32 GPIO。

      3. 引脚:

      4. 左红外:PA7(检测左侧黑线,高电平有效)。

      5. 右红外:PA6(检测右侧黑线,高电平有效)。

    3. 直流电机
      1. 功能

        控制小车运动(前进、后退、转向、调速)。

      2. 电机驱动:L298N 电机驱动模块,连接 STM32 定时器 PWM 引脚。

      3. 定时器:TIM2(通道 1、4 输出 PWM,控制左右电机速度)。

      4. 引脚:

      5. 左电机方向:LEFT1_PINLEFT2_PIN(正转 / 反转)。

      6. 右电机方向:RIGHT1_PINRIGHT2_PIN(正转 / 反转)。

      7. PWM 输出:TIM2_CH1(左电机速度)、TIM2_CH4(右电机速度)。

    4. LED 指示灯

      1. 功能

        显示小车状态(如行驶方向、故障提示)。

        硬件配置

      2. LED 类型:红绿蓝三色 LED,独立控制。

      3. 引脚:

      4. 绿灯:G_LED_PIN(低电平点亮)。

      5. 蓝灯:B_LED_PIN(低电平点亮)。

      6. 红灯:R_LED_PIN(低电平点亮)。

    5. USB 摄像头

      1. 功能

        采集图像,实现视觉检测(如人脸检测)。

        硬件配置

      2. 摄像头:USB 网络摄像头(支持 RTSP 协议),URL:http://admin:admin@10.150.44.188:8081/video

      3. 软件框架:Qt + OpenCV,通过cv::VideoCapture读取视频流。

三、软件设计与核心代码解析
  1. 感知层组件

  2. 红外传感器阵列排布方案(左中、右中)
  3. 无障碍物时(distance > 20cm),读取红外引脚状态:
  4. 左侧黑线(PA7 高):右转(调整方向)。

  5. 右侧黑线(PA6 高):左转(调整方向)。

  6. 中间 / 无黑线:直行。

      // 如果没有障碍物,执行循迹功能
        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();
            }

  7. 超声波测距模块(车头中间位置)
  8. 测距流程:

  9. TIM6 定时触发,TRIG 引脚拉高 20μs(通过 TIM7 精确控制)。

  10. ECHO 上升沿记录开始时间(count1),下降沿记录结束时间(count2),计算时间差Δt = count2 - count1

  11. 距离公式:distance = Δt × 17 / 10(单位:cm,声速简化为 340m/s)。

  12. 避障函数:

  13. 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);
    			  
    
        }
    }
    

  14. 视觉传感器配置(QT)
  15. 执行机构

  16. 电机驱动电路设计
  17. 速度控制:

  18. 通过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);
    	
    }

  19. 运动函数:

  20. 直行:左右电机正转,PWM 差异调整速度同步。

  21. 左转:左电机反转、右电机正转(差速转向)。

  22. 右转:右电机反转、左电机正转(差速转向)。

  23. 后退:左右电机反转。

    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);
    }

  24. 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;
        }
    }

四、软件算法实现
  1. 循迹控制算法

  2. 红外传感器数据处理
    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); // 直行速度(左右电机略有差异补偿机械误差)
        }
    }
  3. 红外传感器数据传输
    // 初始化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);
  4. 避障决策系统

    void avoid_obstacle() {
        if (filter_distance() ≤ 20) { // 有效障碍物
            stop(); // 紧急制动
            HAL_Delay(1000);
            backward(); // 后退
            HAL_Delay(2000);
            right(); // 右转避障(可改为随机左/右转)
            HAL_Delay(7000);
            gogogo(); // 恢复行驶
        }
    }
五、实验与测试
  1. 测试环境构建

  2. 标准测试赛道设计
  3. 环形封闭赛道测试
  4. 障碍物场景模拟
  5. 在赛道上放障碍物
  6. 性能评估指标

  7. 循迹横向偏差
  8. 根据小车以及路面情况调整函数参考值,车辆电机的实际情况可能不同
  9. 急停响应时间
  10. 最小避障距离
  11. 实验结果分析 

六、总代码
/* 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 */
七、总结与展望
  1. 项目成果总结
    1. 循迹避障测试

      V20250516-140715

    2. 人脸识别
  2. 技术难点突破
附录
  1. 关键代码片段示例

作者:SCX404

物联沃分享整理
物联沃-IOTWORD物联网 » 基于STM32的智能循迹避障小车技术指南

发表回复