STM32 nine road car Infrared tracking PWM speed control and steering servo

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_41050642/article/details/102689939

1, ready

Infrared tracking module, L298N motor drive module, STM32C8T6 minimum system, SG90 steering gear, KEIL5

2, theoretical knowledge involved


(1) Infrared tracking module

General is digital infrared output and analog output infrared Both can, ultimately detect infrared light return for compliance. Such as a digital infrared, upon detection of the black line, most of the infrared light is absorbed, an infrared module pin high when no black line, a low level output pin 0 infrared module.

 

(2) L298N drive module

This use of six-wire interface in WE L298N, i.e. ENA, ENB, IN1, IN2, IN3, IN4. According to the information described, since this code takes PWM control, so ENA, ENB as PWM receiver.

(3) SG90 steering gear

 SG90 servo control requires a 20ms time base pulse, the high portion of the pulse is generally range 0.5ms ~ 2.5ms

PWM period is 20ms = (7200 * 200) /72000000=0.02 so TIM_Period = 199, TIM_Prescaler = 7199

(. 4) STM32C8T6 minimum system

Universal Timer 2 and 4, GPIO, a clock configuration. There is a timer with details about the pin selection, we need to look at the minimum system basis chip schematics configurable timer.

 

3, coding practices (following code is a complete, self-debug)


(1) Configuration and functions of each control connecting pins



void OUT_Init(void)//控制电机引脚配置
{
	     GPIO_InitTypeDef GPIO_InitStructure;
	     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

		 PIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_12|GPIO_Pin_13;
	     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	     GPIO_Init(GPIOB,&GPIO_InitStructure);

		 GPIO_ResetBits(GPIOB,GPIO_Pin_13);
		 GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		 GPIO_ResetBits(GPIOB,GPIO_Pin_0);
		 GPIO_ResetBits(GPIOB,GPIO_Pin_1);

}
    
void TIM2_PWM_Init(u16 arr,u16 psc)//PWM控制调速电机输出配置
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启定时器2时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);  
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM2,ENABLE);
                                                       	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &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(TIM2, &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_OC3Init(TIM2, &TIM_OCInitStructure);  
    TIM_OCInitStructure.TIM_Pulse =0; 
	TIM_OC4Init(TIM2, &TIM_OCInitStructure); 

    TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);   	
	TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);   
	TIM_ARRPreloadConfig(TIM2, ENABLE); 
    TIM_Cmd(TIM2, ENABLE);  

}
   
void TIM4_PWM_Init(u16 arr1,u16 psc1)//PWM输出控制舵机角度引脚及功能配置
{ 
	 GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);                                        	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //B_8引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	TIM_TimeBaseStructure.TIM_Period = arr1; 
	TIM_TimeBaseStructure.TIM_Prescaler =psc1;  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
	TIM_OC3Init(TIM4, &TIM_OCInitStructure); 

	TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);   
	TIM_ARRPreloadConfig(TIM4, ENABLE); 
	TIM_Cmd(TIM4, ENABLE);  
 
	}
               
void INFR_Init(void)//红外引脚接收引脚配置
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//GPIOC时钟//此处由于引脚数量限制开启两个GPIO始终端口
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//此处配置为浮空输入模式,便于检测红外模块高低电平状态,以此判断循迹状态
 
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
  
 
GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	GPIO_ResetBits(GPIOC,GPIO_Pin_15);

	
		   
}
          

(2) motor movement Mode Configuration

void forward(void)
{	
	TIM_SetCompare3(TIM4,187);//-------PB_8----定时器4通道3控制舵机转向
	TIM_SetCompare3(TIM2,1000);//-------ENA--PB_10--定时器2通道3电机调速
	GPIO_SetBits(GPIOB,GPIO_Pin_12);//-----IN1--PB_12
	GPIO_ResetBits(GPIOB,GPIO_Pin_13);//----IN2--PB_13
	
	TIM_SetCompare4(TIM2,1000);//-------ENB---PB_11-定时器2通道4电机调速
	GPIO_SetBits(GPIOB,GPIO_Pin_0);//----IN3---PB_0	
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);//-----IN4---PB_1
}

void turnleft(void)//
{		
	TIM_SetCompare3(TIM4,150);
	TIM_SetCompare3(TIM2,50);//-------ENA--PB10--
	GPIO_SetBits(GPIOB,GPIO_Pin_12);//-----IN1
	GPIO_ResetBits(GPIOB,GPIO_Pin_13);//----IN2
	
	TIM_SetCompare4(TIM2,1000);//-------ENB---PB11-
	GPIO_SetBits(GPIOB,GPIO_Pin_0);//----IN3
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);//-----IN4
}
void turnright(void)//
{
  TIM_SetCompare3(TIM4,100);
	TIM_SetCompare3(TIM2,1000);//-------ENA--PB10
	GPIO_SetBits(GPIOB,GPIO_Pin_12);//-----IN1
	GPIO_ResetBits(GPIOB,GPIO_Pin_13);//----IN2	
	
	TIM_SetCompare4(TIM2,50);//-------ENB---PB11
	GPIO_SetBits(GPIOB,GPIO_Pin_0);//----IN3
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);//-----IN4
}
void stop(void)
{
	  TIM_SetCompare3(TIM2,1500);//pwm
	  TIM_SetCompare4(TIM2,1500);
	  GPIO_ResetBits(GPIOB,GPIO_Pin_12);//·
	  GPIO_ResetBits(GPIOB,GPIO_Pin_13);
	
	  GPIO_ResetBits(GPIOB,GPIO_Pin_0);//
	  GPIO_ResetBits(GPIOB,GPIO_Pin_1);
}



void turnleft2(void)//
{
  TIM_SetCompare3(TIM4,150);
	TIM_SetCompare3(TIM2,50);//-------ENA--PB10--
	GPIO_SetBits(GPIOB,GPIO_Pin_12);//-----IN1
	GPIO_ResetBits(GPIOB,GPIO_Pin_13);//----IN2
	
	TIM_SetCompare4(TIM2,1000);//-------ENB---PB11--
	GPIO_SetBits(GPIOB,GPIO_Pin_0);//----IN3
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);//-----IN4
}
void turnright2(void)//
{
	TIM_SetCompare3(TIM4,100);
	TIM_SetCompare3(TIM2,1000);//-------ENA--PB10
	GPIO_SetBits(GPIOB,GPIO_Pin_12);//-----IN1
	GPIO_ResetBits(GPIOB,GPIO_Pin_13);//----IN2	
	
	TIM_SetCompare4(TIM2,50);//-------ENB---PB11
	GPIO_SetBits(GPIOB,GPIO_Pin_0);//----IN3
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);//-----IN4
}

 

(3) to achieve the main function with the functional integration

int main(void)
{
	int LXJ0,LXJ1,LXJ2,LXJ3,XJ4,RXJ5,RXJ6,RXJ7,RXJ15=0;
	
                                 INFR_Init();
                                 OUT_Init();
                                 delay_init();
                                 TIM4_PWM_Init(2000,719);
                                 TIM2_PWM_Init(2000,719);
                                 delay_ms(500);
                                 elay_ms(500);
                                 delay_ms(500);
                                 delay_ms(500);¯
	


while(1) 
{ 
	        LXJ0=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);//读取红外引脚高低电平,
			LXJ1=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1);//以此判断是否在黑线上
		    LXJ2=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2);
			LXJ3=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3);	
		    XJ4=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);
		    RXJ5=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5);
		    RXJ6=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
			RXJ7=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7);
	        RXJ15=GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_15);
      		if((XJ4==1&&LXJ1==0&&LXJ2==0&&LXJ3==0&&RXJ5==0&&RXJ6==0&&RXJ7==0&&RXJ15==0&&LXJ0==0))
			 {		
				 forward();	 			 
			 }
			else if(LXJ3==1|XJ4==1&&LXJ0==0&&LXJ2==0&&LXJ3==0&&RXJ5==0&&RXJ6==0&&RXJ7==0&&RXJ15==0&&XJ4==0)
			 {		 
		    turnright();		 
			 }
			 else if(XJ4==1|RXJ5==1&&LXJ1==0&&LXJ0==0&&LXJ3==0&&RXJ5==0&&RXJ6==0&&RXJ7==0&&RXJ15==0&&XJ4==0)
			 {		
				  turnleft();						 	 
			 }
		   else if(LXJ0==1|LXJ1==1|LXJ2==1&&LXJ1==0&&LXJ2==0&&LXJ0==0&RXJ5==0&&RXJ6==0&&RXJ7==0&RXJ15==0&&XJ4==0)
			 {		
				  turnright2();	 
			 }
			
	  	 else if(RXJ6==1|RXJ7==1|RXJ15==1 &&LXJ1==0&&LXJ2==0&&LXJ3==0&&RXJ5==0&&RXJ6==0&&RXJ7==0&&RXJ15==0&&XJ4==0)
			 {		
				  turnleft2(); 	 
			 }
			

 

Guess you like

Origin blog.csdn.net/qq_41050642/article/details/102689939