不管是对于初学者还是对于一个玩过单片机的电子爱好者来说,或多或少都接触到过小车项目,今天给大家介绍的的一个项目基于STM32超声波避障小车。这也是我曾经的一个课设,在此开源分享给大家,全文5000多字,干货满满,加油读完,保证你收货多多。

基于STM32超声波避障小车https://www.zhihu.com/video/1229107254572007424

处理器电路设计

单片机是系统的CPU,是系统稳定、正常运行的重要前提,以下为单片机选型的两种方案: (1)传统的8位单片机,是通过超大规模集成电路对其进行集成为一个独立芯片的控制器。内部组件包括CPU、随机存储器、只读存储器、I/O接口、中断系统、计时器、串口通讯、数模转换等。STC89C52单片机是最常见的51单片机,但是资源较少,精确度低,处理速度相比STM32单片机差很多。 (2)使用目前市面上最常见的STM32单片机,STM32系列单片机可分为ARMCortex-M3内核体系结构的不同应用领域。它可分为STM32F1系列和STM32F4系列,STM32F1系列单片机时钟频率最高可达72MHZ,在同一产品中性能最好。单片机的基本处理速度为36米,16位单片机的性能也很好。微晶片的内建快闪记忆体相当大,范围从32kb到512kb,可视需要选择。单个设备的功耗非常低,仅360mA,32位单片机产品的功耗最低,每兆赫只有0.5安培。特别值得一提的是,内接单晶片汇流排是一种Harvard架构,可执行速度高达1.25 DMIPS/MHz的指令。此芯片越来越多地被用作主要控制器。 通过对单片机的资源和处理时间的速度我们采用选择STM32103C8T6为本系统主控芯片,程序下载是只需要一个JLINK就可以轻松完成。控制器模块电路如下所示:

电源模块设计

本设计采用锂电池供电, 模块的供电电压一般都为5V,同时超声波模块需要较大的电流才能正常工作,所以在降压的基础上也要保证足够大的输出电流。本设计采用可调输出版本,模块的输入电压范围广,输出电压在1.25V-35V内可调,电压转换效率高,输出纹波小。降压电路如下所示:

电机驱动模块设计

要完成转向是能够利用单片机实现的,然而单片机I0的带负载能力弱,因此我们选择了大功率放大器件TB6612FNG。TB6612FNG是采用MOSFET-H桥结构的双通道大电流电路输出,可以控制2个电机的驱动。相比普通的电机驱动,外围电路非常简单,只需要一个芯片和一个钽电容进行PWM输出滤波,系统尺寸小。PWM信号输入频率范围广,轻松满足本设计的需求。

电源驱动引脚表

控制芯片:TB6612
控制芯片数量:21号TB6612引脚分配:VM         PWMA--------->TIM1_CH1(PA8)VCC        AIN2--------->GPIOB_12GND        AIN1--------->GPIOB_13AO1        STBY--------->GPIOB_14AO2        BIN1--------->GPIOB_15BO2        BIN2--------->GPIOA_12BO1        PWMB--------->TIM1_CH2(PA9)GND        GND2号TB6612引脚分配:VM         PWMA--------->TIM1_CH3(PA10)VCC        AIN2--------->GPIOB_5GND        AIN1--------->GPIOB_6AO1        STBY--------->GPIOB_7AO2        BIN1--------->GPIOB_8BO2        BIN2--------->GPIOA_9BO1        PWMB--------->TIM1_CH4(PA11)GND        GND
真值表AIN1   0     1     0     1AIN2   0     0     1     1BIN1   0     1     0     1BIN2   0     0     1     1停止  正转  反转  刹车

电机所用到的定时器配置

//初始化TIMX,设置TIMx的ARR,PSC
//arr:自动重装载初值,psc为预分频值,两者配合控制定时器时钟的周期
//定时器选择TIM1
static void TB6612_ADVANCE_TIM1_Mode_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty){//-----------------时基结构体初始化-------------------------/TIM_TimeBaseInitTypeDef TIM_TimeStructure;/*开启定时器1时钟,即内部时钟CK_INT=72M*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);TIM_DeInit(TIMx);/*内部时钟作为计数器时钟,72MHZ*/TIM_InternalClockConfig(TIMx);/*自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断*/TIM_TimeStructure.TIM_Period=arr;/*时钟预分频系数为71,则驱动计数器的时钟CK_CNT=CK_INT/(71+1)=1MHZ*/TIM_TimeStructure.TIM_Prescaler=psc-1;/*设置时钟分割,TIM_CKD_DIV1=0,PWM波不延时*/TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;/*向上计数模式*/TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;/*重复计数器*/TIM_TimeStructure.TIM_RepetitionCounter=0;/*初始化定时器*/TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);/*使能ARR预装载寄存器(影子寄存器)*/TIM_ARRPreloadConfig(TIMx,ENABLE);//-----------------输出比较结构体初始化-----------------------/TIM_OCInitTypeDef   TIM_OCInitStructure;/*PWM模式设置,设置为PWM模式1*/TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;/*PWM输出使能相应的IO口输出信号*/TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;/*设置占空比大小,CCR1[15:0]: 捕获/比较通道1的值,若CC1通道配置为输出:CCR1包含了装入当前捕获/比较1寄存器的值(预装载值)。*/TIM_OCInitStructure.TIM_Pulse=duty;/*输出通道电平极性设置*/TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;/*初始化输出比较参数*/TIM_OC1Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道1TIM_OC2Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道2TIM_OC3Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道3TIM_OC4Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道4/*自动重装载*/TIM_OC1PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC3PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC4PreloadConfig(TIMx,TIM_OCPreload_Enable);/*使能计数器*/TIM_Cmd(TIMx,ENABLE);/*主输出使能,如果设置了相应的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),则开启OC和OCN输出。*/TIM_CtrlPWMOutputs(TIMx,ENABLE);
}
//高级定时器输出通道初始化函数
static void TB6612_ADVANCE_TIM_Gpio_Config()
{GPIO_InitTypeDef  GPIO_InitStruct;/*----------通道1配置--------------*//*定时器1输出比较通道*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/*配置为复用推挽输出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道二配置-------------*//*定时器1输出比较通道*//*配置为复用推挽输出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道三配置-------------*//*定时器1输出比较通道*//*配置为复用推挽输出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道四配置-------------*//*定时器1输出比较通道*//*配置为复用推挽输出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);
}

超声波模块

采用HC-SR04超声波模块,该芯片具有较高的集成度以及良好的稳定性,测度距离十分精确,十分稳定。供电电压为DC5V供电电流小于10mA,探测距离为0.010m-3.5m一共有四个引脚VCC(DC5V)、Triger(发射端)、Echo(接收端)、GND(地)。HC-SR04实物图如下:

该模块是利用单片机的IO触发电平测距,单片机内部利用普通定时器产生一个高电平信号之后,超声波就可以自主发送频率为40khz的方波,然后等待信号的返回;若有信号返回,单片机IO口就立刻输出一高电平,利用高电平产生的时间可以计算小车与障碍物的距离。最终距离就是高电平持续时间乘以声音在空气中传播的速度再除以2,可以反复测量距离。 在程序开始首先初始化超声波,利用定时器并设置时基的自动重装载初值1000,psc为预分频值72,这样的话我们产生一次中断的时间是1ms,并设置抢占优先级0,子优先级3。HC_SR04_Echo引脚接收到高电平,打开定时器,且每1ms进入一次中断。在测量时首先让Trig发送一个大于10us的高电平,然后拉高HC_SR04_Trig,当Echo为0时打开定时器计时,当Echo为1时关闭定时器,通过公式计算距离。 模块工作原理: (1)单片机触发引脚,输出高电平信号; (2)模块发送端自动发送特定频率的方波; (3)如果有信号返回,通过IO输出一高电平,高电平持续的时间就是超声波的发射时长; (4)测试距离=(高电平时间*声速(340M/S))/2。 注意:在硬件操作上需要首先让模块地端先连接,否则会影响模块工作。测距时,被测物体的摆放不能太过于杂乱,否则会影响测试结果。

超声波重要代码(可参考)

/* 获取接收到的高电平的时间(us*/uint32_t Get_HC_SR04_Time(void){uint32_t t=0;t=Acoustic_Distance_Count*1000;//ust+=TIM_GetCounter(TIM2);//获取usTIM2->CNT =0;Acoustic_Distance_Count=0;Systic_Delay_us(100);return t;
}
/*获取距离*/
void Get_HC_SR04_Distance(void)
{static uint16_t count=0;switch(count){case 1:{GPIO_SetBits(Acoustic_Port,HC_SR04_Trig);//Trig发送一个大于10us的高电平}break;case 15:{count=0;GPIO_ResetBits(Acoustic_Port,HC_SR04_Trig);while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==0);//当Echo为0时打开定时器 计时Open_Tim2();while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==1);//当Echo为0时打开定时器 计时Close_Tim2();HC_SR04_Distance=(float)(Get_HC_SR04_Time()/5.78);}break;default:break;}count++;
}

舵机模块

本系统使用的是SG90型号的舵机,舵机是一种常见的角度驱动器,本系统需要判断不同位置的障碍物可以且对转向的力度小。舵机可以理解为方向盘称,方向盘是一个常见的名字。它实际上是一个伺服马达。舵机实物图如下:

舵机模块接口简单,舵机模块只有三个引脚。分别引引出了三根线左右两边是电源正负接口线,中间一根是PWM信号线直接连接单片机的控制引脚。通过控制单片机的引脚输出的脉冲宽度进而控制舵机旋转的角度。舵机每增加0.1ms 舵机对应增加9度。 0.5ms---------0 1.0ms---------45
1.5ms---------90 2.0ms---------135 2.5ms-----------180 20ms的时基脉冲,如果想让舵机转90度,就应该发生一个高电平持续时间为1.5ms,周期为20ms的方波,duty=1.5/20=7.5%。在这里设置定时器自动重装载寄存器arr的值为1000,所以当占空比为百分之75是,在程序中就要设置占空比为75/1000=7.5%, 这就是具体的算法。

舵机重要代码(可参考)

/**PWM引脚初始化*/static void SERVO_Gpio_Init(void){GPIO_InitTypeDef  GPIO_InitStruct;/*----------通道2配置--------------*//*定时器3输出比较通道*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/*配置为复用推挽输出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);
}
//定时器3初始化,设置TIMx的ARR,PSC
//arr:自动重装载初值,psc为预分频值,两者配合控制定时器时钟的周期
static void SERVO_TIM_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty)
{//-----------------时基结构体初始化-------------------------/TIM_TimeBaseInitTypeDef TIM_TimeStructure;/*开启定时器3时钟,即内部时钟CK_INT=72M*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);TIM_DeInit(TIMx);/*内部时钟作为计数器时钟,72MHZ*/TIM_InternalClockConfig(TIMx);/*自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断*/TIM_TimeStructure.TIM_Period=arr;//1000 当定时器从0计数到999,即1000次,为一个定时周期/*时钟预分频系数为71,则驱动计数器的时钟CK_CNT=CK_INT/(1440-1+1)=0.05MHZ*/TIM_TimeStructure.TIM_Prescaler=psc-1;;//1400  //即定时器的频率为5KHZ/*设置时钟分割,TIM_CKD_DIV1=0,PWM波不延时*/TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;/*向上计数模式*/TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;/*重复计数器*/TIM_TimeStructure.TIM_RepetitionCounter=0;/*初始化定时器*/TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);/*使能ARR预装载寄存器(影子寄存器)*/TIM_ARRPreloadConfig(TIMx,ENABLE);//-----------------输出比较结构体初始化 开始-----------------------/TIM_OCInitTypeDef   TIM_OCInitStructure;/*PWM模式设置,设置为PWM模式1*/TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;/*PWM输出使能相应的IO口输出信号*/TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;/*设置占空比大小,CCR1[15:0]: 捕获/比较通道1的值,若CC1通道配置为输出:CCR1包含了装入当前捕获/比较1寄存器的值(预装载值)。*/TIM_OCInitStructure.TIM_Pulse=duty;   //占空比大小/*输出通道电平极性设置*/TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;/*初始化输出比较参数*/TIM_OC2Init(TIMx,&TIM_OCInitStructure);//-----------------输出比较结构体初始化 结束-----------------------//*自动重装载*/TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);/*使能计数器*/TIM_Cmd(TIMx,ENABLE);/*主输出使能,如果设置了相应的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),则开启OC和OCN输出。*/TIM_CtrlPWMOutputs(TIMx,ENABLE);
}
/*舵机PWM初始化每增加0.1ms 舵机对应增加9度
0.5ms---------0
1.0ms---------45
1.5ms---------90
2.0ms---------135
2.5ms-----------180
2.1ms    turn_left=150
0.8ms    turn_right=25
1.3ms    turn_front=75
20ms的时基脉冲,如果想让舵机转90度,就应该发生一个高电平为1.5ms,周期为20ms的方波,duty=1.5/20=7.5% ,而定时器自动重装载寄存器arr的值为 1000 ,所以duty=75,时占空比为75/1000=7.5%.
*/
void SERVO_Init(void)
{SERVO_Gpio_Init();SERVO_TIM_Config(TIM3,1000,1440,turn_front);
/** 我们把定时器设置自动重装载寄存器 arr 的值为 1000,设置时钟预分频器为 1440,则
驱动计数器的时钟:CK_CNT = CK_INT / (1440-1+1)=0.05M,则计数器计数一次的时间等于:
1/CK_CNT=20us,当计数器计数到 ARR 的值 1000 时,产生一次中断,则中断一次的时间
为:1/CK_CNT*ARR=20ms。
PWM 信号的频率 f = TIM_CLK/{(ARR+1)*(PSC+1)}  TIM_CLK=72MHZ= 72 000 000/(1000*1440)=5KHZ
*/
}
/*舵机角度控制*/
void SERVO_Angle_Control(uint16_t Compare2)
{TIM_SetCompare2(TIM3,Compare2);
}

编码器模块

调节小车前进的速度和避障快慢我们采用EC11旋转式编码器,可以用于光度、湿度、音量调节等参数的调节。EC11编码器的形状类似于电位器,中心有一个旋钮可以调节PWM信号,光电码盘利用光电转换原理输出三组方波脉冲。EC11编码器的实物图如下:


用来显示小车转速,以及左右编码器数值和电池电压等参数所用的是OLED显示模块,分辨率较高,而且功耗低,正常显示时仅0.06W,供电电压范围在3.3V-5V,有IIC和SPI两种通信协议可供选择。显示模块的亮度和对比度可以通过程序设置。由于它使用寿命长以及其他的优点,OLED更加适合小系统,本系统由于单片机引脚有限,不适合利用简单的LCD1602或者12864来显示,在多方对比之下OLED效果更好。OLED显示部分相对比较简单,大家参考中景园的例程就可以实现。

stm32捕获占空比_基于STM32超声波避障小车相关推荐

  1. 基于51单片机的超声波避障小车设计(含Proteus仿真)

    超声波避障程序随处可见,基于51单片机的超声波避障小车也很成熟,但是完整的Proteus仿真并不容易找到开源资料. 这次主要给大家分享其Proteus仿真部分. 涉及到的模块有:超声波模块(hc-sr ...

  2. 利用52单片机制作的超声波避障小车(包含所有源码)

    做这个超声波避障小车的原因是因为单片机课程设计 一.硬件部分 1.电机驱动 电机驱动四个输入端IN1.IN2.IN3和IN4,四个输出端OUT1.OUT2.OUT3和OUT4,一个接地端GND,单片机 ...

  3. 基于STM32三路超声波避障小车

    基于STM32的避障小车 最近几天的学习了STM32输入捕获输入捕获的相关知识,为了巩固自己学习的知识特意制作一辆有三个超声波组成的4轮避障小车来加深对输入捕获的理解. 1.输入捕获简介 输入捕获模式 ...

  4. STM32F103RCT6 实验代码之舵机+超声波避障小车(一)杂谈+电机+L298N

    STM32 舵机+超声波避障 一.直流电机 二.L298N模块 寒假由于时间较长,自己就想做一个智能车玩玩,第一个做的是蓝牙小车,不过比较简单,我就不打算具体另开一个部分,到时候挑一些与避障小车不一样 ...

  5. STM32F103RCT6 实验代码之舵机+超声波避障小车(三)蓝牙遥控

    STM32 蓝牙遥控 一.蓝牙简述 二.蓝牙遥控 一.蓝牙简述 我这次把小车的坑补上,这是小车的最后一个部分,蓝牙遥控.这个部分重点在于蓝牙,其实蓝牙可以相当于一个串口,用串口通信就可以进行手机与单片 ...

  6. c语言超声波壁障源码,超声波避障小车源程序【精】

    电子制作空间收集的这套入门级小车(只是入门级的,仅供参考)希望诸位入门智能车的吧友有所帮助.可以实现避障.寻迹.测距.寻找静态物体.做这个项目的经验,可分为四步. 第1步:根据实际情况确定智能小车所需 ...

  7. 智能避障小车学习笔记(基于Wemos的避障小车)

    智能避障小车 一.开发环境及硬件 ArduiNo平台 网盘地址:https://pan.baidu.com/s/1w3MHxkCUBOlbqKRxRhlwbQ 提取码:o6gk 硬件 WeMos D1 ...

  8. stm32的语音识别_基于stm32循迹避障语音控制金属探测蓝牙小车设计(原理图+pcb+源码+参考文档)...

    功能描述及设计原理: 小车具有检测里程功能,在金属探测模式,槽型光耦会检测小车车轮的圈数,以此来计算小车行走的里程,并可以通过OLED屏幕显示出来.还可以显示小车的工作模式以及小车距离前方障碍物的距离 ...

  9. stm32车牌识别_基于STM32单片机的车牌识别

    系统介绍    使用STM32F103RCT6作为主控,摄像头使用OV7670(带FIFO).STM32进行了16倍频.识别过程分别为:图像采集,二值化,识别车牌区域,字符分割,字符匹配. 识别过程分 ...

最新文章

  1. Python入门系列之字符编码
  2. Base64转文件,图片
  3. Kotlin实战指南三:流程控制
  4. Java REST框架一览
  5. JavaScript面向对象编程(转)
  6. Keras-3 Keras With Otto Group
  7. [实战演练]2014年人人公司应届生校招技术笔试题
  8. HDFS-HA-federation的机制和功能组件
  9. 英文简历中的自我评价
  10. (Step2-500题)POJ训练计划+SGU
  11. 什么是数据挖掘 有什么作用
  12. cscope索引软链接解决方法
  13. NYOJ 138 找球号(二) (哈希)
  14. 如何将网页另存为PDF
  15. 安装Microsoft Office Document Image Writer
  16. CA1704:标识符应正确拼写
  17. matlab包络分析函数,数据包络分析 (MATLAB代码).doc
  18. 互联网产品推广分为哪些阶段?
  19. Win10电脑怎么恢复出厂设置
  20. PWM控制电机转速的原理

热门文章

  1. matlab如何画图时去掉陆地点,科学网—Matlab m_map一张地图上使用用多个colormap以及patch精细岸线数据去除河流 - 肖鑫的博文...
  2. Python中sort和sorted的用法与区别
  3. Python字节到大整数的打包与解包
  4. Python Sphinx使用踩坑记录
  5. php图片生成缩略图_PHP生成图片缩略图类示例
  6. 【中级软考】UML图(Unified Modeling Language统一建模语言、标准建模语言)
  7. 将yolo标注转换为tensorflow_yolov3标注生成train.txt和test.txt同时做数据清洗
  8. Intel Realsense D435报错 RuntimeError: MFCreateDeviceSource(_device_attrs, _source) returned: HResult
  9. 考研 考研爬虫大数据分析专业热度
  10. 下载并配置完dex-net,在CLI中执行相应操作命令报错解决