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();
}