当前位置:首页 > 公众号精选 > 程序员小哈
[导读]不管是对于初学者,还是对于一个玩过单片机的电子爱好者来说,或多或少都接触到过小车项目,今天给大家介绍的的一个项目——基于STM32超声波避障小车。

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

话不多说先来看视频


处理器电路设计


单片机是系统的CPU,是系统稳定、正常运行的重要前提,以下为单片机选型的两种方案:

(1)传统的8位单片机,是通过超大规模集成电路对其进行集成为一个独立芯片的控制器。内部组件包括CPU、随机存储器、只读存储器、I/O接口、中断系统、计时器、串口通讯、数模转换等。STC89C52单片机是最常见的51单片机,但是资源较少,精确度低,处理速度相比STM32单片机差很多。

(2)使用目前市面上最常见的STM32单片机,STM32系列单片机可分为ARMCortex-M3内核体系结构的不同应用领域。它可分为STM32F1系列和STM32F4系列,STM32F1系列单片机时钟频率最高可达72米,在同一产品中性能最好。单片机的基本处理速度为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信号输入频率范围广,轻松满足本设计的需求。    

电机驱动引脚表

1控制芯片:TB6612
2控制芯片数量:2
3    1号TB6612引脚分配:
4     VM         PWMA--------->TIM1_CH1(PA8)
5     VCC        AIN2--------->GPIOB_12
6     GND        AIN1--------->GPIOB_13
7     AO1        STBY--------->GPIOB_14
8     AO2        BIN1--------->GPIOB_15
9     BO2        BIN2--------->GPIOA_12
10     BO1        PWMB--------->TIM1_CH2(PA9)
11     GND        GND
12    2号TB6612引脚分配:
13     VM         PWMA--------->TIM1_CH3(PA10)
14     VCC        AIN2--------->GPIOB_5
15     GND        AIN1--------->GPIOB_6
16     AO1        STBY--------->GPIOB_7
17     AO2        BIN1--------->GPIOB_8
18     BO2        BIN2--------->GPIOA_9
19     BO1        PWMB--------->TIM1_CH4(PA11)
20     GND        GND
21真值表
22     AIN1   0     1     0     1
23     AIN2   0     0     1     1
24     BIN1   0     1     0     1
25     BIN2   0     0     1     1
26           停止  正转  反转  刹车

电机所用到的定时器配置

1//初始化TIMX,设置TIMx的ARR,PSC
2//arr:自动重装载初值,psc为预分频值,两者配合控制定时器时钟的周期
3//定时器选择TIM1
4static void TB6612_ADVANCE_TIM1_Mode_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty)
5
{
6    //-----------------时基结构体初始化-------------------------/
7    TIM_TimeBaseInitTypeDef TIM_TimeStructure;
8    /*开启定时器1时钟,即内部时钟CK_INT=72M*/
9    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
10    TIM_DeInit(TIMx);
11    /*内部时钟作为计数器时钟,72MHZ*/
12    TIM_InternalClockConfig(TIMx);
13    /*自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断*/
14    TIM_TimeStructure.TIM_Period=arr;
15    /*时钟预分频系数为71,则驱动计数器的时钟CK_CNT=CK_INT/(71+1)=1MHZ*/
16    TIM_TimeStructure.TIM_Prescaler=psc-1;
17    /*设置时钟分割,TIM_CKD_DIV1=0,PWM波不延时*/
18    TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;
19    /*向上计数模式*/
20    TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;
21    /*重复计数器*/
22    TIM_TimeStructure.TIM_RepetitionCounter=0;
23    /*初始化定时器*/
24    TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);
25    /*使能ARR预装载寄存器(影子寄存器)*/
26    TIM_ARRPreloadConfig(TIMx,ENABLE);
27    //-----------------输出比较结构体初始化-----------------------/
28    TIM_OCInitTypeDef   TIM_OCInitStructure;
29    /*PWM模式设置,设置为PWM模式1*/
30    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
31    /*PWM输出使能相应的IO口输出信号*/
32    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
33    /*设置占空比大小,CCR1[15:0]: 捕获/比较通道1的值,若CC1通道配置为输出:CCR1包含了装入当前捕获/比较1寄存器的值(预装载值)。*/
34    TIM_OCInitStructure.TIM_Pulse=duty;
35    /*输出通道电平极性设置*/
36    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
37    /*初始化输出比较参数*/
38    TIM_OC1Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道1
39    TIM_OC2Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道2
40    TIM_OC3Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道3
41    TIM_OC4Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道4
42    /*自动重装载*/
43    TIM_OC1PreloadConfig(TIMx,TIM_OCPreload_Enable);
44    TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);
45    TIM_OC3PreloadConfig(TIMx,TIM_OCPreload_Enable);
46    TIM_OC4PreloadConfig(TIMx,TIM_OCPreload_Enable);
47    /*使能计数器*/
48    TIM_Cmd(TIMx,ENABLE);
49    /*主输出使能,如果设置了相应的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),则开启OC和OCN输出。*/
50    TIM_CtrlPWMOutputs(TIMx,ENABLE);    
51}
52//高级定时器输出通道初始化函数
53static void TB6612_ADVANCE_TIM_Gpio_Config()
54
{
55    GPIO_InitTypeDef  GPIO_InitStruct;
56    /*----------通道1配置--------------*/
57    /*定时器1输出比较通道*/
58    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
59    /*配置为复用推挽输出*/
60    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
61    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
62    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
63    GPIO_Init(GPIOA,&GPIO_InitStruct);
64    /*-----------通道二配置-------------*/
65    /*定时器1输出比较通道*/
66    /*配置为复用推挽输出*/
67    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
68    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11;
69    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
70    GPIO_Init(GPIOA,&GPIO_InitStruct);
71     /*-----------通道三配置-------------*/
72    /*定时器1输出比较通道*/
73    /*配置为复用推挽输出*/
74    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
75    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
76    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
77    GPIO_Init(GPIOA,&GPIO_InitStruct);
78     /*-----------通道四配置-------------*/
79    /*定时器1输出比较通道*/
80    /*配置为复用推挽输出*/
81    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
82    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
83    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
84    GPIO_Init(GPIOA,&GPIO_InitStruct);
85}



超声波模块


采用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。

注意:在硬件操作上需要首先让模块地端先连接,否则会影响模块工作。测距时,被测物体的摆放不能太过于杂乱,否则会影响测试结果。

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

1/* 获取接收到的高电平的时间(us*/
2uint32_t Get_HC_SR04_Time(void)
3{
4    uint32_t t=0;
5    t=Acoustic_Distance_Count*1000;//us
6    t+=TIM_GetCounter(TIM2);//获取us
7    TIM2->CNT =0;
8    Acoustic_Distance_Count=0;
9    Systic_Delay_us(100);
10    return t;
11}
12/*获取距离*/
13void Get_HC_SR04_Distance(void)
14
{
15    static uint16_t count=0;
16    switch(count)
17    {
18        case 1:
19        {
20            GPIO_SetBits(Acoustic_Port,HC_SR04_Trig);//Trig发送一个大于10us的高电平
21        }break;
22
23        case 15:
24        {
25            count=0;
26            GPIO_ResetBits(Acoustic_Port,HC_SR04_Trig);
27            while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==0);//当Echo为0时打开定时器 计时
28            Open_Tim2();
29            while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==1);//当Echo为0时打开定时器 计时
30            Close_Tim2();
31            HC_SR04_Distance=(float)(Get_HC_SR04_Time()/5.78);
32
33        }break;
34        default:break;
35    }
36    count++;
37}


舵机模块     


本系统使用的是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%, 这就是具体的算法。

舵机重要代码(可参考)

1/**PWM引脚初始化*/
2static void SERVO_Gpio_Init(void)
3
{
4    GPIO_InitTypeDef  GPIO_InitStruct;
5    /*----------通道2配置--------------*/
6    /*定时器3输出比较通道*/
7    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
8    /*配置为复用推挽输出*/
9    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
10    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
11    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
12    GPIO_Init(GPIOA,&GPIO_InitStruct); 
13}
14//定时器3初始化,设置TIMx的ARR,PSC
15//arr:自动重装载初值,psc为预分频值,两者配合控制定时器时钟的周期
16static void SERVO_TIM_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty)
17
{
18    //-----------------时基结构体初始化-------------------------/
19    TIM_TimeBaseInitTypeDef TIM_TimeStructure;
20    /*开启定时器3时钟,即内部时钟CK_INT=72M*/
21    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
22    TIM_DeInit(TIMx);
23    /*内部时钟作为计数器时钟,72MHZ*/
24    TIM_InternalClockConfig(TIMx);
25    /*自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断*/
26    TIM_TimeStructure.TIM_Period=arr;//1000 当定时器从0计数到999,即1000次,为一个定时周期
27    /*时钟预分频系数为71,则驱动计数器的时钟CK_CNT=CK_INT/(1440-1+1)=0.05MHZ*/
28    TIM_TimeStructure.TIM_Prescaler=psc-1;;//1400  //即定时器的频率为5KHZ   
29    /*设置时钟分割,TIM_CKD_DIV1=0,PWM波不延时*/
30    TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;
31    /*向上计数模式*/
32    TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;
33    /*重复计数器*/
34    TIM_TimeStructure.TIM_RepetitionCounter=0;
35        /*初始化定时器*/
36    TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);
37    /*使能ARR预装载寄存器(影子寄存器)*/
38    TIM_ARRPreloadConfig(TIMx,ENABLE);
39    //-----------------输出比较结构体初始化 开始-----------------------/
40    TIM_OCInitTypeDef   TIM_OCInitStructure;
41    /*PWM模式设置,设置为PWM模式1*/
42    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
43    /*PWM输出使能相应的IO口输出信号*/
44    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
45    /*设置占空比大小,CCR1[15:0]: 捕获/比较通道1的值,若CC1通道配置为输出:CCR1包含了装入当前捕获/比较1寄存器的值(预装载值)。*/
46    TIM_OCInitStructure.TIM_Pulse=duty;   //占空比大小
47    /*输出通道电平极性设置*/
48    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
49    /*初始化输出比较参数*/
50    TIM_OC2Init(TIMx,&TIM_OCInitStructure);
51    //-----------------输出比较结构体初始化 结束-----------------------/    
52    /*自动重装载*/
53    TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);
54    /*使能计数器*/
55    TIM_Cmd(TIMx,ENABLE);
56    /*主输出使能,如果设置了相应的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),则开启OC和OCN输出。*/
57    TIM_CtrlPWMOutputs(TIMx,ENABLE);    
58}
59/*舵机PWM初始化
60   每增加0.1ms 舵机对应增加9度
610.5ms---------0
621.0ms---------45   
631.5ms---------90
642.0ms---------135
652.5ms-----------180
662.1ms    turn_left=150
670.8ms    turn_right=25
681.3ms    turn_front=75
6920ms的时基脉冲,如果想让舵机转90度,就应该发生一个高电平为1.5ms,周期为20ms的方波,duty=1.5/20=7.5% ,而定时器自动重装载寄存器arr的值为 1000 ,所以duty=75,时占空比为75/1000=7.5%. 
70*/

71void SERVO_Init(void)
72
{
73    SERVO_Gpio_Init();
74    SERVO_TIM_Config(TIM3,1000,1440,turn_front);
75/** 我们把定时器设置自动重装载寄存器 arr 的值为 1000,设置时钟预分频器为 1440,则
76驱动计数器的时钟:CK_CNT = CK_INT / (1440-1+1)=0.05M,则计数器计数一次的时间等于:
771/CK_CNT=20us,当计数器计数到 ARR 的值 1000 时,产生一次中断,则中断一次的时间
78为:1/CK_CNT*ARR=20ms。
79PWM 信号的频率 f = TIM_CLK/{(ARR+1)*(PSC+1)}  TIM_CLK=72MHZ
80               = 72 000 000/(1000*1440)=5KHZ    
81*/
    
82}
83/*舵机角度控制*/
84void SERVO_Angle_Control(uint16_t Compare2)
85
{
86    TIM_SetCompare2(TIM3,Compare2);
87}


编码器模块


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


OLED显示模块


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


END



微信公众号:果果小师弟
关注可了解获取更多的免费资料;
如果你觉得文章对你有帮助,转发分享,欢迎赞赏

最后

10T资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、单片机、等等!在公众号内回复「更多资源」,即可免费获取,期待你的关注!!!
下面的是我的公众号二维码图片,欢迎关注。




免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

该系列产品有助于嵌入式设计人员在更广泛的系统中轻松实现USB功能

关键字: 单片机 嵌入式设计 USB

单片机编程语言是程序员与微控制器进行交流的桥梁,它们构成了单片机系统的软件开发基石,决定着如何有效、高效地控制和管理单片机的各项资源。随着微控制器技术的不断发展,针对不同应用场景的需求,形成了丰富多样的编程语言体系。本文...

关键字: 单片机 微控制器

单片机,全称为“单片微型计算机”或“微控制器”(Microcontroller Unit,简称MCU),是一种高度集成化的电子器件,它是现代科技领域的关键组件,尤其在自动化控制、物联网、消费电子、汽车电子、工业控制等领域...

关键字: 单片机 MCU

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

在当前的科技浪潮中,单片机作为嵌入式系统的重要组成部分,正以其强大的功能和广泛的应用领域受到越来越多行业的青睐。在众多单片机中,W79E2051以其卓越的性能和稳定的工作特性,成为市场上的明星产品。本文将深入探讨W79E...

关键字: 单片机 w79e2051单片机

单片机,又称为微控制器或微处理器,是现代电子设备中的核心部件之一。它集成了中央处理器、存储器、输入输出接口等电路,通过外部信号引脚与外部设备进行通信,实现对设备的控制和管理。本文将详细介绍单片机的外部信号引脚名称及其功能...

关键字: 单片机 微控制器 中央处理器

随着科技的飞速发展,单片机和嵌入式系统在现代电子设备中的应用越来越广泛。它们不仅提高了设备的智能化水平,还推动了各行各业的创新与发展。在单片机和嵌入式系统的开发中,编程语言的选择至关重要。本文将深入探讨单片机和嵌入式系统...

关键字: 单片机 嵌入式系统 电子设备

PLC(可编程逻辑控制器)和单片机是两种不同的控制设备,它们之间存在明显的区别:

关键字: 单片机 plc 控制器

超声波测距原理将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对超声波测距的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 超声波 超声波测距 测距仪

Holtek隆重推出全新一代32-bit Arm® Cortex®-M0+ 5V CAN MCU - HT32F53231/HT32F53241/HT32F53242/HT32F53252。这一系列单片机带有来自Bosc...

关键字: MCU 工业自动化 单片机
关闭
关闭