基于STM32的智能小车避障与循迹实战(江科大标准库开发)
1. 项目概述与硬件准备
如果你已经学完了江科大的STM32入门教程,却不知道下一步该做什么,那么这个智能小车项目绝对是你的不二之选!我自己在做完这个项目后,对STM32的各种外设和编程逻辑有了更深刻的理解。今天我就把自己在实现过程中的经验分享给大家,包括避障、循迹等核心功能的实现方法。
智能小车项目需要的硬件其实并不复杂,下面是必备清单:
- 主控芯片:STM32F103C8T6最小系统板(核心板)
- 电机驱动:TB6612模块(1-2个,根据电机数量决定)
- 舵机:SG90(用于超声波模块的旋转扫描)
- 传感器:HC-SR04超声波模块(避障)、TCRT5000红外模块(循迹)
- 通信模块:HC-04蓝牙模块(手机控制)
- 车体框架:某多多上搜索"STM32智能小车框架"(自带四个直流电机)
- 烧录器:ST-LINK V2
- 其他:导线若干、面包板或洞洞板(建议用洞洞板,更稳定)
我在第一次组装时犯了个错误,没有先测试电机就直接焊接了,结果发现有个电机是坏的,不得不重新拆焊。所以强烈建议大家先测试所有元件再组装!
2. 电机驱动与PWM控制
2.1 TB6612电机驱动详解
TB6612是东芝公司生产的直流电机驱动芯片,我用下来感觉比L298N效率高很多,发热量也小。这个芯片有双通道输出,可以同时驱动两个直流电机,每个通道能提供1A的连续电流,峰值可达2A。
关键引脚功能:
- VM:电机驱动电压(3V-13.5V)
- VCC:逻辑电平输入(2.7V-5.5V)
- STBY:待机控制(高电平正常工作)
- AO1/AO2、BO1/BO2:两路电机输出
- PWMA/PWMB、AIN1/AIN2、BIN1/BIN2:控制信号输入
接线时要注意,电机驱动电压最好单独供电,不要和STM32共用电源,否则电机启动时可能会造成电压波动导致单片机复位。
2.2 PWM驱动程序实现
PWM控制是让电机转起来的关键,我使用的是TIM2的通道1和通道2:
#include "stm32f10x.h" void PWM_Init(void) { // 开启GPIOA和TIM2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 配置GPIOA_Pin0和Pin1为复用推挽输出 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置时基单元 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV2; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; // ARR TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; // PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); // 配置输出比较通道 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比为0 TIM_OC1Init(TIM2, &TIM_OCInitStructure); // 通道1 TIM_OC2Init(TIM2, &TIM_OCInitStructure); // 通道2 TIM_Cmd(TIM2, ENABLE); } // 设置比较值函数 void PWM_SetCompare1(uint16_t Compare) { TIM_SetCompare1(TIM2, Compare); } void PWM_SetCompare2(uint16_t Compare) { TIM_Se