2-STM32智能小车(4)舵机加超声波避障

1–安装及原理:
将超声波安装舵机上,调节舵机旋钮,使得当舵机复位时超声波指向正前方;
舵机使用方法:参考下面博客
https://blog.csdn.net/Nimbrethil/article/details/98475301
超声波使用方法:如下博客
https://blog.csdn.net/qq_41262681/article/details/95940707
2–代码:

#include "wave.h"
#include "delay.h"
#include "move.h"
#include "usart.h"
/超声波测距
void TIM3_Cap_Init(u16 arr,u16 psc)
{   
 RCC->APB1ENR|=1<<1;    //TIM2时钟使能
 RCC->APB2ENR|=1<<2;     //使能A时钟
 GPIOA->CRL&=0XF0FFFFFF; //超声波接收端
 GPIOA->CRL|=0X08000000;
 GPIOA->ODR|=0<<0;
 //采用输入捕获获取时间
  TIM3->ARR=arr;   //设定计数器自动装载值
 TIM3->PSC=psc;   //设定预分频数
 TIM3->CCMR1|=1<<0; //CC1S=01选择输入端,IC1映射到TI1上
  TIM3->CCMR1|=1<<4;  //IC1F=0001 配置输入滤波器,以Fck_int采样,2个事件后有效
  TIM3->CCMR1|=0<<10;  //IC2PS=00  配置输入分频,不分频
 TIM3->CCER|=0<<1;  //CC1P=0    上升沿捕获
 TIM3->CCER|=1<<0;  //CC1E=1    允许捕获计数器的值到捕获寄存器中
 TIM3->DIER|=1<<1;    //允许捕获中断  
 TIM3->DIER|=1<<0;    //允许更新中断 
 TIM3->CR1|=0x01;     //使能计数器2
 MY_NVIC_Init(2,0,TIM3_IRQn,2);//抢占2,子优先级0,组2   
}
//捕获状态2个全局变量
//[7]:0,没有成功捕获,1,成功捕获一次
//[6]:0,还没有捕获到高电平,1,已经捕获到高电平了
//[5:0]:捕获高电平后的溢出次数
u8  TIM3CH1_CAPTURE_STA=0;//输入捕获状态    
u16 TIM3CH1_CAPTURE_VAL;//输入捕获值-用来记录捕获到下降沿时,TIM2_CNT的值
//定时器2中断服务程序
void TIM3_IRQHandler(void)
{      
 u16 tsr;
 tsr=TIM3->SR;
  if((TIM3CH1_CAPTURE_STA&0X80)==0)//还没有成功捕获
 {
  if(tsr&0X01)//溢出
  {     
   if(TIM3CH1_CAPTURE_STA&0X40)                   //已经捕获到高电平了
   {
    if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)   //高电平太长了
    {
     TIM3CH1_CAPTURE_STA|=0X80;     //标记成功捕获了一次
     TIM3CH1_CAPTURE_VAL=0XFFFF;
    }else TIM3CH1_CAPTURE_STA++;
   }  
  }
  if(tsr&0x02)//捕获1发生捕获事件
  { 
   if(TIM3CH1_CAPTURE_STA&0X40)          //捕获到一个下降沿 
   {      
    TIM3CH1_CAPTURE_STA|=0X80;  //标记成功捕获到一次高电平的脉冲宽度
     TIM3CH1_CAPTURE_VAL=TIM3->CCR1;         //提取当前的捕获值
     TIM3->CCER&=~(1<<1);   //CC1P=0 设置为上升沿捕获
   }else        //还未开始,第一次捕获上升沿
   { 
    TIM3CH1_CAPTURE_VAL=0;
    TIM3CH1_CAPTURE_STA=0X40;  //标记捕获到了上升沿
    TIM3->CNT=0;    //计数器清空
    TIM3->CCER|=1<<1;    //CC1P=1 设置为下降沿捕获
   }      
  }                     
  }
 TIM3->SR=0;                                                     //清空中断标志位 
}
void ultrasonic_Init(void){    //发射端初始化
 RCC->APB2ENR |= 1<<2;
 GPIOA->CRL &= 0xfff0ffff;
 GPIOA->CRL |= 0X00030000;
}
 //
//舵机转动/
void TIM1_PWM_Init(u16 arr,u16 psc){ //对舵机输出PWM波
 RCC->APB2ENR|= 1<<11;
 RCC->APB2ENR|=1<<2;
 GPIOA->CRH &=0XFFFFFFF0;
 GPIOA->CRH |=0X0000000B;//开启复用功能,PWM
 TIM1->ARR=arr;
 TIM1->PSC=psc;
 TIM1->CCMR1|=7<<4;//CH1从第4位开始,设为111也就是7,PWM2模式
 TIM1->CCMR1|=1<<3;
 TIM1->CCER|=1<<0;//OC1输出使能
 TIM1->BDTR|=1<<15;//TIM1是高级计时器,需要配置15位为1
 TIM1->CR1 =0x0080;
 TIM1->CR1|=0x01;
}
void RIGHTROLL_Init(void)
{
 right(10);
 ROLL=9500;//复位成90度  
 delay_ms(1000);
}
void LEFTROLL_Init(void){
 int temp;
 ROLL=9000;
 delay_ms(1000);
 temp=distance();
 if(temp<=20){
 RIGHTROLL_Init();
 }
 else{
 left(10);
 ROLL=9500;//复位成90度  
  delay_ms(1000);
 }
}
void wave_init(void)
{    
 int temp=0;
 ultrasonic_Init();
  TIM3_Cap_Init(0XFFFF,72-1);  //以1Mhz的频率计数
 TIM1_PWM_Init(9999,143);//                     //延时初始化
 ROLL=9500;//复位成90度  
 delay_ms(1000);
 ///测距/
    while(1)
 {
    go(10);  
    temp=distance();//获取实测距离
    if(temp<30)//小于30
    {
     stop2();   
    }
 }
}
 ///
void stop2(){
 stop();
 LEFTROLL_Init();
}
int distance(){
 int temp;
 while(1)
  {
     PAout(4)=1;
     delay_us(15);  
     PAout(4)=0;
   delay_ms(500);  
   if(TIM3CH1_CAPTURE_STA&0X80)              //成功捕获到了一次高电平
   {
    temp=TIM3CH1_CAPTURE_STA&0X3F;
    temp*=65536;            //溢出时间总和
    temp+=TIM3CH1_CAPTURE_VAL;   //得到总的高电平的时间
    temp=temp*240/10000;
    printf("Distance:%d cm\r\n",temp);//打印总的高电平的时间,也就是转换后的高度了
    TIM3CH1_CAPTURE_STA=0;    //开启下一次捕获
    return temp;
   }   
  }
 }

思路:当超声波测得前方距离小于30cm时,小车停止,舵机左转测量左边距离,小于30则右转,否则左转,小车转完后舵机复位指向正前方,小车前进;

你可能感兴趣的:(2-STM32智能小车(4)舵机加超声波避障)