精华内容
下载资源
问答
  • STM32 舵机+超声波避障一.直流电机二.L298N模块 寒假由于时间较长,自己就想做一个智能车玩玩,第一个做的是蓝牙小车,不过比较简单,我就不打算具体另开一个部分,到时候挑一些与避障小车不一样的部分说一下。我这...
  • 智能小车使用红外探头避障,适应不同颜色标志
  • 这个程序是基于STM32F103的循迹避障小车,需要的硬件有小车模型、电机驱动模块,直流电机、stm32F103芯片、还有两个红外传感器和一个红外对管
  • 舵机+超声波简介一.SG90舵机二.超声波数据处理 补充一下上一篇博客遗漏掉的一个问题,一般电机的PWM都是有一些频率限制的,而我的直流电机是10Khz来进行驱动的。 一.SG90舵机 这个是我买的舵机+超声波模块,这个...
  • 基于stm32f103vc的智能小车源码,运用超声波传感器HC-SR04实现避障,实现控制CDS5516舵机的旋转。
  • 基于STM32F103C8T6避障小车的代码模板

    千次阅读 2019-12-22 17:42:25
    #include "stm32f10x.h" #include "delay.h" #include "pwm_output.h" void RCC_Configuration(void); void Moto_Configuration(void); void SuperWave_Configuration(void); uint32_t SuperWave_Distance(void); ....
    #include "stm32f10x.h"
    #include "delay.h"
    #include "pwm_output.h"
    
    void RCC_Configuration(void);
    void Moto_Configuration(void);
    void SuperWave_Configuration(void);
    uint32_t SuperWave_Distance(void);
    void Car_Up(void);  //前进
    void Car_Right(void);  //PA0-IN1,PA1-IN2管左电机 ;PA2-IN3,PA3-IN4管右电机
    void Car_Left(void);  //PA0-IN1,PA1-IN2管左电机 ;PA2-IN3,PA3-IN4管右电机
    void Car_Stop(void);  //PA0-IN1,PA1-IN2管左电机 ;PA2-IN3,PA3-IN4管右电机
    
    
    int main(void)
    {
    	vu32 n=0;
    
    	
    	 RCC_Configuration();
       Moto_Configuration();
      SuperWave_Configuration();
    	
    	
    	SystemInit(); //配置系统时钟为72M   
    	
    	TIM1_PWM_Init(); //TIM1 PWM波输出初始化,并使能TIM1 PWM输出
        TIM1->CCR2 =28000;  //右轮
    		 TIM1->CCR3 =27000;  //左轮
    	while(1)
    	{
    		if(SuperWave_Distance()<=30)
    	 {
    		 Car_Stop();
    		 delay_ms(5);
    		 
    		 Car_Left();
    		 delay_ms(1000);
    		 Car_Up();
    		 delay_ms(5000);
    		 
    		 Car_Right();
    		 delay_ms(1000);
    		 Car_Up();
    		 delay_ms(10000);	
    		 
    	
    展开全文
  • 在家写的32智能小车小车通过接收红外遥控器信号,实现不同的运动状态。小车程序里还对红外循迹、超声波避障和OLED显示等都进行了初始化,但因为时间原因没有在程序中用到这些功能,有需要的同学可以自己编写。
  • 本代码基于STM32F103ZET6单片机,使用一个超声波传感器,四个万向轮,四轮驱动,实现小车自主换道避障
  • 智能小车使用红外探头避障,适应不同颜色标志
  • 基于STM32三路超声波避障小车

    万次阅读 多人点赞 2019-08-03 17:40:18
    一般学习单片机的第一步就是做智能小车,通过PWM控制调节车速,以及使用超声波模块进行输入捕获,而这篇文章在于多通道实现输入捕获,因为用到了3个超声波。详细讲解了输入捕获的原理以及一些重要功能的实现代码

    基于STM32的避障小车

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

    1.输入捕获简介

    输入捕获模式可以用来测量脉冲宽度或者测量频率。 我们以测量脉宽为例,用一个简图来说明输入捕获的原理,如图 15.1.1 所示:
    在这里插入图片描述
    如图 15.1.1 所示,就是输入捕获测量高电平脉宽的原理,假定定时器工作在向上计数模式,图中 t1~t2 时间,就是我们需要测量的高电平时间。测量方法如下:首先设置定时器通道 x 为上升沿捕获,这样, t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。 这样,根据定时器的计数频率,我们就可以算出 t1~t2 的时间,从而得到高电平脉宽。
    在 t1~t2 之间,可能产生 N 次定时器溢出,这就要求我们对定时器溢出,做处理,防止高电平太长,导致数据不准确。如图 15.1.1所示,t1~t2之间,CNT计数的次数等于:N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。输入捕获的原理。
    STM32F1 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能。 STM32F1 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。
    接下来,我们介绍我们需要用到的一些寄存器配置,需要用到的寄存器有: TIMx_ARR、TIMx_PSC、 TIMx_CCMR1、 TIMx_CCER、 TIMx_DIER、 TIMx_CR1、 TIMx_CCR1 ,我们这里针对性的介绍这几个寄存器的配置。
    捕获/比较模式寄存器 1: TIMx_CCMR1
    该寄存器的各位描述如图 15.1.2 所示:
    在这里插入图片描述
    当在输入捕获模式下使用的时候,对应图 15.1.2 的第二行描述,从图中可以看出,TIMx_CCMR1 明显是针对 2 个通道的配置,低八位[7: 0]用于捕获/比较通道 1 的控制,而高八位[15: 8]则用于捕获/比较通道 2 的控制,因为 TIMx 还有 CCMR2 这个寄存器,所以可以知道CCMR2 是用来控制通道 3通道 4
    捕获/比较使能寄存器: TIMx_CCER
    这里我们以通道1为例,具体的参考中文手册。我们要用到这个寄存器的最低 2 位, CC1E 和 CC1P 位。这两个位的描述如图 15.1.4所示:
    在这里插入图片描述
    所以,要使能输入捕获,必须设置 CC1E=1,而 CC1P 则根据自己的需要来配置。
    DMA/中断使能寄存器: TIMx_DIER
    我们需要用到中断来处理捕获数据,所以必须开启通道 1 的捕获比较中
    断,即 CC1IE 设置为 1。
    控制寄存器: TIMx_CR1
    我们只用到了它的最低位,也就是用来使能定时器的。
    捕获/比较寄存器 1: TIMx_CCR1
    该寄存器用来存储捕获发生时, TIMx_CNT的值,我们从 TIMx_CCR1 就可以读出通道 1 捕获发生时刻的 TIMx_CNT 值,通过两次捕获(一次上升沿捕获,一次下降沿捕获)的差值,就可以计算出高电平脉冲的宽度(注意,对于脉宽太长的情况,还要计算定时器溢出的次数)
    注意以上寄存器的配置均以通道1为例,具体的配置看中文参考书册。

    2、超声波模块简介

    !Alt
    这里我们用的是HC-SR04模块,此模块性能稳定,测度距离精确,模块高精度,盲区小。采用IO口TRIG触发测距,给至少10us的高电平信号;模块自动发送8个40khz的方波,自动检测是否有信号返回;有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离。如此不断的周期测,即可以达到你移动测量的值。

    3、小车设计思路

    3个超声波分别安装在正前方左边和右边各一个,具体情况见下图:
    !Alt
    在主函数里调用测距函数,分别计算出障碍物离小车前方、左边、右边的距离lenth1、lenth2、lenth3,如果前方距离大于20cm并且左边和右边的距离大于10厘米则前进(GO)负责判断左边和右边的距离。如果左边距离小于10cm(lenth2<10),则右转(YOU)。如果右边的距离小于10cm(lenth3<10),则左转(ZUO)。其它情况下则是:后退——>延时500ms——>左拐——>延时200ms。值得注意的是:小车在超声波测距时要保证小车处于静止状态为了避免小车在测距时小车依旧在运动从而增加误差。同时利用PWM调速尽量让小车速度慢下来,来减小误差。

    4、程序代码

    1、超声波测距初识化
    这里我们用的是定时2(TIM2)的通道2、3、4,在这段程序是对定时器2的4个通道进行初始化。在工程文件下新建一个HC6的文件,新建一个hc6.c和hc6.h文件。期中hc6.c代码如下:

    #include "hc6.h"
    #include "sys.h"
    void HCSR04_Init(u16 arr,u16 psc)
    {
     	RCC->APB1ENR|=1<<0;    //TIM2时钟使能
      	RCC->APB2ENR|=1<<2;    //使能PORTA时钟
    	RCC->APB2ENR|=1<<3;	 //使能PORTB时钟
    	RCC->APB2ENR|=1<<4; 	//使能PORTC时钟
       	GPIOA->CRL&=0XFFFF0000;//PA0~3清除之前设置
        GPIOA->CRL|=0X00008888;//PA0~3浮空输入
    	GPIOA->ODR|=0<<0;
        GPIOA->ODR|=0<<1;      //PA1下拉
    	GPIOA->ODR|=0<<2;
    	GPIOA->ODR|=0<<3;
    	
        GPIOB->CRL&=0X000FFFFF;
        GPIOB->CRL|=0X33300000;
        GPIOB->ODR|=1<<7;      //PB7 输出高
        GPIOB->ODR|=1<<6;
    	GPIOB->ODR|=1<<5;
    	
        TIM2->ARR=arr;         //设定计数器自动重装值
        TIM2->PSC=psc;         //预分频器
    	
    	TIM2->CCMR1|=1<<0;     //CC1S=01 选择输入端IC1映射到TI1
        TIM2->CCMR1|=1<<4;     //IC1F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR1|=0<<2;    //IC1PS=00 配置输入分频,不分频
    		
        TIM2->CCER|=0<<1;      //CC1P=0 上升沿捕获
        TIM2->CCER|=1<<0;      //CC1E=1 允许捕获计数器的值到捕获寄存器中
    	
        TIM2->CCMR1|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
        TIM2->CCMR1|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR1|=0<<10;    //IC2PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<5;      //CC2P=0 上升沿捕获
        TIM2->CCER|=1<<4;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    		
    	TIM2->CCMR2|=1<<0;     //CC3S=01 选择输入端IC1映射到TI1
        TIM2->CCMR2|=1<<4;     //IC3F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR2|=0<<2;    //IC3PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<9;      //CC3P=0 上升沿捕获
        TIM2->CCER|=1<<8;      //CC3E=1 允许捕获计数器的值到捕获寄存器中
    		
    	TIM2->CCMR2|=1<<8;     //CC4S=01 选择输入端IC1映射到TI1
        TIM2->CCMR2|=1<<12;     //IC4F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR2|=0<<10;    //IC4PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<13;      //CC4P=0 上升沿捕获
        TIM2->CCER|=1<<12;      //CC4E=1 允许捕获计数器的值到捕获寄存器中
    		
    	TIM2->DIER|=1<<1;
        TIM2->DIER|=1<<2;      //允许捕获中断
    	TIM2->DIER|=1<<3;      //允许捕获中断
    	TIM2->DIER|=1<<4;      //允许捕获中断
        TIM2->DIER|=1<<0;      //允许更新中断
        TIM2->CR1|=0X01;       //使能定时器2
        MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
    }
    
    u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH1_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH3_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH4_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    
    //定时器2中断服务程序
    void TIM2_IRQHandler(void)
    {
        u16 tsr;
        tsr=TIM2->SR;
    		if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH1_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH1_CAPTURE_STA++;
                }
            }
            if(tsr&0x02)//捕获1发生捕获事件
            {
                if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH1_CAPTURE_VAL=TIM2->CCR1;//获取当前的捕获值
                    TIM2->CCER&=~(1<<1);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH1_CAPTURE_VAL=0;
                    TIM2CH1_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;             //计数器清空
                    TIM2->CCER|=1<<1;        //CC1P=1 设置为下降沿捕获
                }
            }
        }
        if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH2_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH2_CAPTURE_STA++;
                }
            }
            if(tsr&0x04)//捕获1发生捕获事件
            {
                if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH2_CAPTURE_VAL=TIM2->CCR2;//获取当前的捕获值
                    TIM2->CCER&=~(1<<5);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH2_CAPTURE_VAL=0;
                    TIM2CH2_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;             //计数器清空
                    TIM2->CCER|=1<<5;        //CC1P=1 设置为下降沿捕获
    				TIM2->CR1|=0x01;
                }
            }
        }
    		
    		if((TIM2CH3_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH3_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH3_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH3_CAPTURE_STA++;
                }
            }
            if(tsr&0x08)//捕获1发生捕获事件
            {
                if(TIM2CH3_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH3_CAPTURE_VAL=TIM2->CCR3;//获取当前的捕获值
                    TIM2->CCER&=~(1<<9);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH3_CAPTURE_VAL=0;
                    TIM2CH3_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;  
    				TIM2CH3_CAPTURE_VAL=TIM2->CCR3;							//计数器清空
                    TIM2->CCER|=1<<9;        //CC1P=1 设置为下降沿捕获
    				TIM2->CR1|=0x01;
                }
            }
    	}
    		
    	if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH4_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH4_CAPTURE_STA++;
                }
            }
            if(tsr&0x10)//捕获1发生捕获事件
            {
                if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH4_CAPTURE_VAL=TIM2->CCR4;//获取当前的捕获值
                    TIM2->CCER&=~(1<<13);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH4_CAPTURE_VAL=0;
                    TIM2CH4_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;             //计数器清空
                    TIM2->CCER|=1<<13;        //CC1P=1 设置为下降沿捕获
    				TIM2->CR1|=0x01;
                }
            }
        }				
        TIM2->SR=0;//清除中断标志位	
    }
    

    hc6.h代码如下:

    #ifndef __HC6_H
    #define __HC6_H
    #include "sys.h"
    
    void HCSR04_Init(u16 arr,u16 psc);
    
    #endif
    

    2、电机模块初始化
    这里我们用的是定时3和定时器1,在工程文件下新建一个MOTER的文件夹,新建一个moter.c和moter.h文件。期中moter.c代码如下:

    #include "moter.h"
    #include "sys.h"
    #include "delay.h"
    void TIM_PWM1_Init(u16 arr,u16 psc)
    {		 					 
    	//此部分需手动修改IO口设置
    	RCC->APB1ENR|=1<<1; 	//TIM3时钟使能    
    	RCC->APB2ENR|=1<<2;		//GPIOA使能
    	RCC->APB2ENR|=1<<3;  	 //GPIOB使能
    	RCC->APB2ENR|=1<<4;
    	GPIOA->CRL&=0X00FFFFFF;	
    	GPIOA->CRL|=0XBB000000;
    	GPIOC->CRH&=0X000FFFFF;
    	GPIOC->CRH|=0X33300000;
    	GPIOB->CRL&=0XFFFFF000; //PB(0)是AIN1 PB(1)是AIN2
    	GPIOB->CRL|=0X00000333;
    	TIM3->ARR=arr;			//设定计数器3自动重装值 
    	TIM3->PSC=psc;			//预分频器设置
      
    	TIM3->CCMR1|=6<<4;  	//CH1 PWM2模式		 
    	TIM3->CCMR1|=1<<3; 		//CH1预装载使能	 
    	TIM3->CCMR1|=6<<12;  	//CH2 PWM2模式		 
    	TIM3->CCMR1|=1<<11; 		//CH2预装载使能	
    	
     	TIM3->CCER|=1<<0;   	//OC1 输出使能
    	TIM3->CCER|=1<<4;   	//OC1 输出使能	   
    	TIM3->CR1=0x0080;   	//ARPE使能 
    	TIM3->CR1|=0x01;    	//使能定时器3 
    
    	RCC->APB2ENR|=1<<11; //TIM1定时器使能
    	GPIOA->CRH&=0XFFFF0FF0;
    	GPIOA->CRH|=0X0000B00B;
    	
    	GPIOB->CRH&=0X0000FFFF;
    	GPIOB->CRH|=0X33330000;
    	
    	TIM1->ARR=arr;			//设定计数器自动重装值 
    	TIM1->PSC=psc;			//预分频器设置
    	
    	TIM1->CCMR1|=6<<4;  	//CH1 PWM2模式		 
    	TIM1->CCMR1|=1<<3; 		//CH1预装载使能	 
    	TIM1->CCMR2|=6<<12;  	//CH4 PWM2模式		 
    	TIM1->CCMR2|=1<<11; 		//CH4预装载使能	
    	
    	TIM1->CCER|=1<<0;   	//OC1 输出使能
    	TIM1->CCER|=1<<12;   	//OC4 输出使能	
    	TIM1->BDTR|=1<<15;   	//MOE 主输出使能	   
    
    	TIM1->CR1=0x0080;   	//ARPE使能 
    	TIM1->CR1|=0x01;    	//使能定时器1 
    	
    	STBY=1;
    	STBY1=1;
    }
    
    void GO(u16 a,u16 b)
    {
    	AIN1=0;
    	AIN2=1;
    	BIN1=0;
    	BIN2=1;
    	AIN3=1;
    	AIN4=0;
    	BIN3=1;
    	BIN4=0;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    }
    
    void STOP(void)
    {
    	AIN1=0;
    	AIN2=0;
    	BIN1=0;
    	BIN2=0;
    	AIN3=0;
    	AIN4=0;
    	BIN3=0;
    	BIN4=0;	
    }
    
    void HOU(u16 a,u16 b)
    {
    	AIN1=1;
    	AIN2=0;
    	BIN1=1;
    	BIN2=0;
    	AIN3=0;
    	AIN4=1;
    	BIN3=0;
    	BIN4=1;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    }
    
    void YOU(u16 a,u16 b)
    {
    	AIN1=1;
    	AIN2=0;
    	BIN1=0;
    	BIN2=1;
    	AIN3=0;
    	AIN4=1;
    	BIN3=1;
    	BIN4=0;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    }
    
    void ZUO(u16 a,u16 b)
    {
    	AIN1=0;
    	AIN2=1;
    	BIN1=1;
    	BIN2=0;
    	AIN3=1;
    	AIN4=0;
    	BIN3=0;
    	BIN4=1;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    }
    

    上面这段代码主要包括定时器PWM的初始化,还有定义了5个函数。前后左右对应有两个参数a和b,通过改变这两个参数就可以控制电机的速度。同时也能保证左边和右边的两个轮子的速度相同。
    moter.h电机如下:

    #ifndef __MOTER_H
    #define __MOTER_H
    #include "sys.h"
    
    #define AIN1 PBout(0)
    #define AIN2 PBout(1)
    #define BIN1 PCout(13)
    #define BIN2 PCout(14)
    #define STBY PCout(15) 
    #define AIN3 PBout(15)
    #define AIN4 PBout(14)
    #define BIN3 PBout(13)
    #define BIN4 PBout(12)
    #define STBY1 PAout(12)
    
    void TIM_PWM1_Init(u16 arr,u16 psc);
    void STOP(void);
    void GO(u16 a,u16 b);
    void HOU(u16 a,u16 b);
    void YOU(u16 a,u16 b);
    void ZUO(u16 a,u16 b);
    
    #endif
    

    3.主函数如下:

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "hc6.h"
    #include "moter.h"
    
    #define Trig1 PBout(7) // PB7
    #define Trig2 PBout(6)
    #define Trig3 PBout(5)
    
    extern u8 TIM2CH2_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值
    
    extern u8 TIM2CH3_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    
    extern u8 TIM2CH4_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    u32 DIS_Init(u8 *STA,u16 VAL)//定义计算距离函数
    {
    		u32 temp;
    		u32 lenth;
    	  if((*STA)&0X80)//成功捕获到了一次高电平
        {
            temp=(*STA)&0X3F;
            temp*=65536;               //溢出时间总和
            temp+=VAL; //得到总的高电平时间
            lenth=temp*0.017;           //计算长度
            *STA=0;     //开启下一次捕获
        }
    		return lenth;
    }
    int main(void)
    {				 
    	u32 lenth1;
    	u32 lenth2;
    	u32	lenth3;
    	Stm32_Clock_Init(9); //系统时钟设置
      	delay_init(72); //延时初始化
     	uart_init(72,9600); //串口初始化
    	HCSR04_Init(0XFFFF,72-1);//以1Mhz的频率计数
    	TIM_PWM1_Init(899,0); 
    	while(1)
    	{
    		Trig1=1;
    		delay_us(20);              //输入一个20us的高电平
    		Trig1=0;
    		lenth1=DIS_Init(&TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL);
    		delay_us(20);
    		Trig2=1;
    		delay_us(20);              //输入一个20us的高电平
    		Trig2=0;
    		lenth2=DIS_Init(&TIM2CH3_CAPTURE_STA,TIM2CH3_CAPTURE_VAL);
    		delay_us(20);
    		Trig3=1;
    		delay_us(20);
    		Trig3=0;
    		lenth3=DIS_Init(&TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL);
    		if((lenth1>30)&&(lenth3>10)&&(lenth2>10))
    		{
    			GO(400,400);
    		}
    		else if(lenth3<10)
    		{
    			ZUO(300,300);
    			delay_ms(20);
    		}
    		else if(lenth2<10)
    		{
    			YOU(300,300);
    			delay_ms(20);
    		}
    		else
    		{
    			HOU();
    			delay_ms(500);
    			ZUO(300,300);
    			delay_ms(300);
    		}
    		STOP();
    		delay_ms(20);
    	}
    } 
    

    主函数主要调用相关的文件和函数,同时定义了一个测距函数**u32 DIS_Init(u8 *STA,u16 VAL)**返回值是所测得的距离。同时每次调用以后要使得TIM2CHx_CAPTURE_STA的值为0所以传递的是TIM2CHx_CAPTURE_STA的地址,同时定义函数的参数为指针变量来使得为0。在while(1)里实现了小车的测距,同时根据相关的距离来判断小车的运动状态。

    展开全文
  • 基于stm32f103vc的智能小车——超声波避障部分

    千次阅读 多人点赞 2019-07-10 11:41:14
    在硬件综合训练这门课程中,我们以小组的形式完成了基于stm32f103vc的智能小车的制作,实现的主要功能有:遥控、避障、语音控制、人脸识别以及舵机控制摄像头旋转。其中我主要负责的是stm32板的开发,以下是超声波...

    智能小车的超声波避障实现过程

    在硬件综合训练这门课程中,我们以小组的形式完成了基于stm32f103vc的智能小车的制作,实现的主要功能有:遥控、避障、语音控制、人脸识别以及舵机控制摄像头旋转。其中我主要负责的是stm32板的开发,以下是超声波避障的实现过程。

    1. 超声波模块的介绍
      我们所用的是HC-SR04超声波测距模块,它可以测量 3cm – 4m 的距离,精确度可以达到 3mm。
      HC-SR04 实物图
    2. 超声波模块的工作原理
      (1)采用IO口TRIG触发测距,给至少10us的高电平信号;
      (2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
      (3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速/2;
      (4)本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离。如此不断的周期测,即可以达到你移动测量的值。
    3. 超声波模块电路图
      在这里插入图片描述
    4. 超声波模块时序图
      在这里插入图片描述
    5. 超声波模块实现代码
      时钟与GPIO初始化:
    void iniTim()
    {
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
     	TIM_TimeBaseInitStructer.TIM_Period=9999;// 定时周期 .1s 100ms overflow
     	TIM_TimeBaseInitStructer.TIM_Prescaler=71;  // 72 000 000 1mhz 1us
     	TIM_TimeBaseInitStructer.TIM_ClockDivision=0; 
     	TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;
     	TIM_TimeBaseInitStructer.TIM_RepetitionCounter = 0;
     	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructer);
    
    	TIM_Cmd(TIM2,ENABLE);
     	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
     
     	NVIC_InitTypeDef NVIC_InitStructure;
     	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
     	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
     	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
     	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    	 NVIC_Init(&NVIC_InitStructure);
     
     	TIM_Cmd(TIM2,DISABLE);// 关闭定时器使能
    
    	GPIO_InitTypeDef GPIO_InitStructure;
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
     
    	 /*TRIG 信号 */
     	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
     	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
     	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
     	GPIO_Init(GPIOB, &GPIO_InitStructure);
    	 /*ECOH 信号 */
    	 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
     	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
     	GPIO_Init(GPIOB, &GPIO_InitStructure);
     
     	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
     	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
     	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
     	GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
     	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
     	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
     	GPIO_Init(GPIOB, &GPIO_InitStructure);
     
     	GPIO_ResetBits(GPIOB,GPIO_Pin_9);//关闭距离过远led
    }

    测距函数:

    double get_length(void)
    {
     	GPIO_SetBits(GPIOB,GPIO_Pin_8);
     	 Delay_us(11);
      	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
     	 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6) == RESET);
       	TIM2->CNT = 0;//清零计时器
      	TIM_Cmd(TIM2,ENABLE);// 回响信号到来,开启定时器计数
      	while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==SET);
      	TIM_Cmd(TIM2,DISABLE);// 关闭定时器
      
     	if(!toofar) //没有完成一次计数周期,即距离不是很远 
      	{
       		t=TIM_GetCounter(TIM2);// 获取 TIM2 寄存器中的计数值
       		time = (double)t/(double)1000000; //往返时间,单位s 
       		length =  340*time/2; //单程长度,单位m 
       		TIM2->CNT=0; // 将 TIM2 计数寄存器的计数值清零
      	}
      	else
     	{
       		toofar = 0; 
       		length =99; //足够远,不用考虑 
       		TIM2->CNT=0; // 将 TIM2 计数寄存器的计数值清零
      	}
     	return length;
    }

    设置中断:

    void TIM2_IRQHandler(void) // 中断,当距离足够远时,设置toofar = 1,不必再计算 
    {
     	if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
       	{
       		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);// 清除中断标志
       		toofar = 1;
       		GPIO_ResetBits(GPIOB,GPIO_Pin_9);
       	}
    }

    主函数:

    int main(void) 
    {
     	SysTick_Init();
     	iniTim();
     	while(1) 
     	{
     		double len = 0;
      		len = get_length();
      		if ( len < 0.5 ) //如果距离够近
      		{
      			GPIO_SetBits(GPIOB,GPIO_Pin_7);//点亮距离过近led
       			GPIO_ResetBits(GPIOB,GPIO_Pin_9);//复位距离过远led
      		}
      		else 
       		{
       			if(toofar)//距离长到tim溢出,> 17m
       			{
        				GPIO_SetBits(GPIOB,GPIO_Pin_9);//点亮距离过远led
        				GPIO_ResetBits(GPIOB,GPIO_Pin_7);//复位距离过近led
       			}
       			else
       			{
         				GPIO_ResetBits(GPIOB,GPIO_Pin_7);//复位距离过近led
        				GPIO_ResetBits(GPIOB,GPIO_Pin_7);//复位距离过近led
        			}
      		}  
     	}
    }

    注:我添加了两个led灯来判断超声波测距功能的实现,其中
    PB7引脚上连接的是距离过近led,如果近距离内出现障碍,它会亮起;
    PB9引脚上连接的是距离过远led,如果在很远的距离范围里都没有障碍,它会亮起。

    展开全文
  • stm32f103为主控芯片的蓝牙遥控四路循迹超声波避障小车,,用keil打开编辑即可运行,简单明了
  • 该程序源代码用于STM32F103ZET6智能小车超声波避障运动。 1、采用KEIL5软件开发。 2、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 3、程序对应处理器:STM32F103ZET6 4、电机驱动芯片L293D。 5、液晶模块型号:...
  • 基于STM32超声波避障小车

    千次阅读 多人点赞 2020-10-05 17:15:38
    超声波避障小车原理就是通过给超声波模块超过10us的高电平信号,自动发送8个40KHZ的方,来检测是不是有信号的返回,如果有信号的返回,那么就判断为前方有障碍物,并且通过舵机云台,来实现180度的旋转,检测左右...

    超声波避障小车原理就是通过给超声波模块超过10us的高电平信号,自动发送8个40KHZ的方波,来检测是不是有信号的返回,如果有信号的返回,那么就判断为前方有障碍物,并且通过舵机云台,来实现180度的旋转,检测左右两边是否的有障碍物,从而进行避障的功能。

    说完原理,接下来就是根据各部件的原理来进行编程,我的超声波避障小车主要涉及了超声波HC-SR04模块,L298N电机驱动模块,舵机sg90模块。
    首先是最基本的电机驱动模块的相关代码:

    #include "bsp_motor.h"
    #include "delay.h"
    #include <math.h>
    
    void TIM4_PWM_Motor(unsigned int arr,unsigned int psc)
    {	
    	GPIO_InitTypeDef					GPIO_InitStuct;
    	TIM_TimeBaseInitTypeDef		TIM_TimeBaseInitStuct;
    	TIM_OCInitTypeDef					TIM_OCInitStuct;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
    	
    	
    	GPIO_InitStuct.GPIO_Pin=GPIO_Pin_7;						//左电机控制
    	GPIO_InitStuct.GPIO_Mode=GPIO_Mode_Out_PP;
    	GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStuct);
    	
    	GPIO_InitStuct.GPIO_Pin=GPIO_Pin_8;						//左电机PWM
    	GPIO_InitStuct.GPIO_Mode=GPIO_Mode_AF_PP;
    	GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStuct);
    	
    	GPIO_InitStuct.GPIO_Pin=GPIO_Pin_9;						//右电机PWM
    	GPIO_InitStuct.GPIO_Mode=GPIO_Mode_AF_PP;
    	GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStuct);
    		
    	GPIO_InitStuct.GPIO_Pin=GPIO_Pin_4;						//右电机方向控制
    	GPIO_InitStuct.GPIO_Mode=GPIO_Mode_Out_PP;
    	GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStuct);
    	
    	TIM_TimeBaseInitStuct.TIM_ClockDivision=0;
    	TIM_TimeBaseInitStuct.TIM_CounterMode=TIM_CounterMode_Up;
    	TIM_TimeBaseInitStuct.TIM_Period=arr;
    	TIM_TimeBaseInitStuct.TIM_Prescaler=psc;
    	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStuct);
    	
    	TIM_OCInitStuct.TIM_OCMode = TIM_OCMode_PWM2; 
    	TIM_OCInitStuct.TIM_OutputState = TIM_OutputState_Enable; 
    	TIM_OCInitStuct.TIM_Pulse = 0; 
    	TIM_OCInitStuct.TIM_OCPolarity = TIM_OCPolarity_High; 
    	TIM_OC3Init(TIM4, &TIM_OCInitStuct);  
    	TIM_OC4Init(TIM4, &TIM_OCInitStuct);  
    	
    	TIM_CtrlPWMOutputs(TIM4,ENABLE);	
      
    	TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  
    	TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); 
    	
     	TIM_Cmd(TIM4, ENABLE);
    }
    
    void car_run(unsigned char ucChannel,signed char cSpeed)
    {
    		short PWM;	
       	PWM = 7201 - fabs(cSpeed)*72;
    	switch(ucChannel)
    	{
    		case 0://右轮
    			TIM_SetCompare3(TIM4,PWM);
    			if (cSpeed>0) 
    				GPIO_ResetBits(GPIOA,GPIO_Pin_4);
    			else if(cSpeed<0) 
    				GPIO_SetBits(GPIOA,GPIO_Pin_4);		
    			break;
    		case 1://左轮
    		  TIM_SetCompare4(TIM4,PWM); 
    			if (cSpeed>0) 
    				GPIO_SetBits(GPIOB,GPIO_Pin_7);
    			else if (cSpeed<0)
    				 GPIO_ResetBits(GPIOB,GPIO_Pin_7);
    			break;			
    	}
    }
    
    
    void Run_Go(signed char speed,int time)  //前进函数
    {
    		  signed char f_speed = - speed;
    	    car_run(1,f_speed);
    			car_run(0,speed);
    			delay_ms(time);                
    }
    
    void Run_stop(int time) //刹车函数
    {
    	  car_run(1,0);
    	  car_run(0,0);
    	  GPIO_ResetBits(GPIOA,GPIO_Pin_4);;
    	  GPIO_ResetBits(GPIOB,GPIO_Pin_7);;
    		delay_ms(time);           
    }
    
    void Run_left(signed char speed,int time) //左转
    {
    	  car_run(1,0);     
    	  car_run(0,speed);    
    		delay_ms(time);                 
    }
    void Run_Spin_left(signed char speed,int time) //左旋转
    {
    	  signed char u_speed = 100 - speed; 
     	  car_run(1,speed);  
    	  car_run(0,u_speed);          
    		delay_ms(time);                 
    
    }
    void Run_right(signed char speed,int time)  //右转
    {
    	  signed char f_speed = - speed;
    	  car_run(1,f_speed);   
    	  car_run(0,0);                
    		delay_ms(time);                  
    }
    void Run_Spin_right(signed char speed,int time) //右旋转
    {
    	  signed char u_speed = 100 - speed;
    	  signed char f_speed = - speed;
    	  car_run(1,-u_speed);   
    	  car_run(0,f_speed);           
    		delay_ms(time);                   
    }
    void Run_back(signed char speed,int time) //后退
    {
    	  signed char u_speed = 100- speed;
    	  signed char f_speed = - u_speed;
    	  car_run(1,u_speed);
    	  car_run(0,f_speed);
    		delay_ms(time);                 
    }
    

    超声波检测距离的相关代码:

    #include "bsp_hc.h"
    #include "delay.h"
    #define	TRIG_PORT      GPIOC		
    #define	ECHO_PORT      GPIOC		
    #define	TRIG_PIN       GPIO_Pin_0   
    #define	ECHO_PIN       GPIO_Pin_1
    
    float UltrasonicWave_Distance;     
    void UltrasonicWave_Configuration(void)
    {
      GPIO_InitTypeDef GPIO_InitStructure;	
    	EXTI_InitTypeDef EXTI_InitStructure;
     	NVIC_InitTypeDef NVIC_InitStructure;
    	
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
        
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;					  
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	         
      GPIO_Init(GPIOC, &GPIO_InitStructure);	      
    
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;				   
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;		 
      GPIO_Init(GPIOC,&GPIO_InitStructure);				
    	
    
     	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1);
    
     	EXTI_InitStructure.EXTI_Line = EXTI_Line1;
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);		                        
    		
    			
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			     
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	 
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			  
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;						
      NVIC_Init(&NVIC_InitStructure);  	                       
    }
    
    void EXTI1_IRQHandler(void)
    {
    	delay_us(10);		                     
      if(EXTI_GetITStatus(EXTI_Line1) != RESET)
    	{
    			TIM_SetCounter(TIM2,0);
    			TIM_Cmd(TIM2, ENABLE);                                      
    		
    			while(GPIO_ReadInputDataBit(GPIOC,ECHO_PIN));	         
    
    			TIM_Cmd(TIM2, DISABLE);			                                
    			UltrasonicWave_Distance=TIM_GetCounter(TIM2)*5*34/200.0;			
    			EXTI_ClearITPendingBit(EXTI_Line1); 
    	}
    }
    void Timerx_Init(uint16_t arr,uint16_t psc)
    {
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    	TIM_TimeBaseStructure.TIM_Period = 5000;
    	TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); 
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 
     
    	TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_Trigger,ENABLE);
    	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    	NVIC_Init(&NVIC_InitStructure);  
    							 
    }
    
    void TIM2_IRQHandler(void)   
    {
    	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) 
    		{
    		TIM_ClearITPendingBit(TIM2, TIM_IT_Update  ); 
    		}
    }
    
    int UltrasonicWave_StartMeasure(void)
    {
      int temp;
    	GPIO_SetBits(TRIG_PORT,TRIG_PIN); 		  
      delay_us(20);		                    
      GPIO_ResetBits(TRIG_PORT,TRIG_PIN);
    	temp = UltrasonicWave_Distance*10;
    	return temp;
    }
    

    舵机云台的相关代码:

    #include "bsp_duoji.h"
    
    void TIM5_PWM_Init(u16 arr,u16 psc)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
      TIM_OCInitTypeDef TIM_OCInitStructure;
    	
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    
    	 TIM_TimeBaseStructure.TIM_Period = arr;
    	 TIM_TimeBaseStructure.TIM_Prescaler =psc;
    	 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    	 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	 TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); 
    	
    	 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    	 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    	 TIM_OCInitStructure.TIM_Pulse = 0;
    	 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    	 TIM_OC1Init(TIM5, &TIM_OCInitStructure);
    	 
    	 TIM_CtrlPWMOutputs(TIM5,ENABLE);	
    	 TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable); 
       TIM_OC2Init(TIM5, &TIM_OCInitStructure);
    	 
    	 TIM_ARRPreloadConfig(TIM5, ENABLE); 
       TIM_Cmd(TIM5, ENABLE); 
    }
    
    

    最后是主函数:

    #include "stm32f10x.h"
    #include "bsp_motor.h"
    #include "bsp_duoji.h"
    #include "bsp_hc.h"
    #include "delay.h"
    
    void duojizhuantou(float angle)
    {
    	angle=(u16)(50.0*angle/9.0+249.0);
    	TIM_SetCompare1(TIM5,angle);
    }
    
    int front_detection()
    {
    	duojizhuantou(90);
    	delay_ms(100);
    	return UltrasonicWave_StartMeasure();
    }
    int left_detection()
    {
    	duojizhuantou(175);
    	delay_ms(300);
    	return UltrasonicWave_StartMeasure();
    }
    int right_detection()
    {
    	duojizhuantou(5);
    	delay_ms(300);
    	return UltrasonicWave_StartMeasure();
    }
    
    int main(void)
    {
      Timerx_Init(4999,7199);   
    	HC_GPIO();              
    	TIM4_PWM_Motor(7199,0);
    	TIM5_PWM_Init(9999,143); 
    	
    	while(1)
    	{  		
    		if(front_detection()<60 && front_detection()>0) 
    		{
    			Run_stop(500);		
    			Run_back(60,500);	
    			Run_stop(1000);			
    			left_detection();
    			delay_ms(500);
    			right_detection();
    			delay_ms(500);
    			if((left_detection() < 60 ) &&( right_detection() < 60 ))
    			{
    				Run_Spin_left(60,1000);
    			}				
          else if(left_detection() > right_detection())
    			{
    				Run_left(60,1000);
    				Run_stop(500);
    			}	
          else
    			{
    				Run_right(60,1000);
    				Run_stop(500);					
    			}							
    		}	
    		else
    		{
    			Run_Go(60,10);
    		}
    	}
     }
    
    展开全文
  • 该程序源代码用于STM32F103ZET6智能小车超声波避障运动+PM2.5监测实验。 01、采用KEIL5软件开发。 02、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 03、程序对应处理器:STM32F103ZET6 04、电机驱动芯片L293D。 ...
  • 该程序源代码用于STM32F103ZET6智能小车超声波避障运动+温湿度监测实验。 01、采用KEIL5软件开发。 02、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 03、程序对应处理器:STM32F103ZET6 04、电机驱动芯片L293D。...
  • 【项目分享】基于STM32超声波避障小车

    千次阅读 多人点赞 2020-01-21 16:10:45
    不管是对于初学者还是对于一个玩过单片机的电子爱好者来说,或多或少都接触到过小车项目,今天给大家介绍的的一个项目基于STM32超声波避障小车。这也是我曾经的一个课设,在此开源分享给大家,全文5000多字,干货满...
  • 基于STM32F103C8T6的循迹避障小车完整制作过程 由于本人的一个小项目,要做一个基于STM32的循迹避障小车,前后花了约1周的时间,这个过程种也参考了很多大神分享的资料,学到很多的东西。但是资料都比较分散,有些...
  • 该程序源代码用于STM32F103ZET6智能小车超声波避障运动+空气环境监测实验。空气环境监测包含:温湿度监测,气体监测和PM2.5监测。 01、采用KEIL5软件开发。 02、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 03、...
  • 该程序源代码用于STM32F103ZET6智能小车红外循迹运动+超声波避障运动实验。 1、采用KEIL5软件开发。 2、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 3、程序对应处理器:STM32F103ZET6 4、电机驱动芯片L293D。 5...
  • 该程序源代码用于STM32F103ZET6智能小车超声波避障运动+气体监测实验。 01、采用KEIL5软件开发。 02、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 03、程序对应处理器:STM32F103ZET6 04、电机驱动芯片L293D。 ...
  • 该程序源代码用于STM32F103ZET6智能小车红外避障跟随循迹超声波避障运动综合实验。 1、采用KEIL5软件开发。 2、用到的库文件:Keil.STM32F1xx_DFP.2.3.0.pack。 3、程序对应处理器:STM32F103ZET6 4、电机驱动芯片L...
  • 基于STM32F103C8T6的循迹避障小车完整制作过程(详细)----中篇(第456点) 上篇主要是讲一些基础的东西,中篇讲了如何制作循迹,本篇讲一下制作避障小车。 七,如何用使用pwm让舵机旋转到相应的角度 这位博主讲的很...
  • stm32超声波避障小车

    2020-11-08 21:00:17
    STM32f103为控制芯片的超声波避障小车程序,带舵机,keil打开编译后即可运行,简单明了。。。。
  • 链接:基于STM32F103C8T6的循迹避障小车完整制作过程(详细)----上篇(第123点) 其实上篇就是一些基础的东西,本篇讲一下如何让小车循迹 四,如何通过pwm调整电机的转速(调节小车的快慢) 1,为何pwm能调速度? ...
  • STM32 蓝牙遥控一.蓝牙简述二.蓝牙遥控 一.蓝牙简述 我这次把小车的坑补上,这是小车的最后一个部分,蓝牙遥控。这个部分重点在于蓝牙,其实蓝牙可以相当于一个串口,用串口通信就可以进行手机与单片机之间的通信 ...
  • 玄学表象:超声波模块不能正常工作。(模块测出距离一直是固定值) 分析可能原因:板子硬件问题,祖传的超声波模块硬件问题,代码问题, 挖掘本质: 1.模块供电不足!  一直忽略了这个问题,虽然板子上有引出5V...
  • 包含红外线遥控,超声波避障,PID调速等多种功能,源码都有,F103zet6可以直接使用

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 131
精华内容 52
关键字:

stm32f103超声波避障小车