目录

前言:
效果展示:
车体展示:


前言:

        在前两周的时间里,我对上个版本的小车进行了一个更新换代,将原本的4驱小车换成了4轮两驱小车,舍弃了树莓派4B作为上位机。新版小车采用两个520直流减速电机搭配AS4950电机芯片来差速行进,后面采用两个万向轮带着,5路灰度传感器循迹,用HC_SR04超声波模块中断式测距,用HC_08蓝牙模块与手机进行通信,同时搭载MPU6050模块来拐直角弯。

效果展示:

新版小车功能效果展示

车体展示:

 

 正文开始:

        本次改进依旧沿用上次制作的电路板,板载了AS4950电机芯片,在这款电机芯片的帮助下,我甚至连死区时间都不用配置,AS4950自行帮我们处理。

如图就是AS4950及其原理图

          根据AS4950的数据手册,我们可以整理一下,得到一个表格

IN1 IN2 电机驱动状态
任意 任意 停止
0 0 停止
0 1 正转
1 0 反转
1 1 刹车

从这里,我们就可以看到AS4950有4种驱动状态:

1:IN1端口输入PWM,IN2端口输入低电平,芯片输出正电流,电机正转;

2:IN1端口输入低电平,IN2端口输入PWM,芯片输出负电流,电机反转;

3:IN1端口输入高电平,IN2端口输入PWM,芯片输出正电流,电机正传;

4;IN1端口输入PWM,IN2端口输入高电平,芯片输出负电流,电机反转;

我这里就选择了方式1和方式4来控制电机正反转,利用两轮差速来循迹和拐弯,使用TIM8的CH2(PC7)CH3(PC8)作为PWM输出,CH2N(PB0)CH3N(PB1)作为推挽输出。在输出PWM上,我选择了输出比较模式,通过修改CCR寄存器来调整占空比

代码部分:


void Motor3_Init()
{
	//PC7 	    -> TIM8_CH2
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseStructure;
	TIM_OCInitTypeDef	TIM_OCInitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//PC7为PWM
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);//PC7
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//PB0用做推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB0
	GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET);// 0 0 状态是AS4950休眠状态
	
	TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 9999;
	TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 1000000) - 1;
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
//	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OutputNState_Disable;//CH2N通道失能
//	TIM_OCInitStructure.TIM_OCPolarity = ;
	TIM_OCInitStructure.TIM_Pulse = 0;                            //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM8, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	TIM_CtrlPWMOutputs(TIM8,ENABLE);	//MOE 主输出使能	
 
	TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Disable);  //CH2预装载使能	  
	
	TIM_ARRPreloadConfig(TIM8, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM8, ENABLE);  //使能TIM8
}
void Motor4_Init()
{
	//PC8 	    -> TIM8_CH3
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseStructure;
	TIM_OCInitTypeDef	TIM_OCInitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//PC8作为PWM
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);//PC8
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//PB1作为输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB1
	GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);// 0 0 状态是AS4950休眠状态
	
	TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 9999;
	TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 1000000) - 1;
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;                            //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
	TIM_OC3Init(TIM8, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	TIM_CtrlPWMOutputs(TIM8,ENABLE);	//MOE 主输出使能	
 
	TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Disable);  //CH3预装载使能	  
	
	TIM_ARRPreloadConfig(TIM8, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM8, ENABLE);  //使能TIM8
}


#define Motor3_reverse(pulse)        {TIM8->CCR2 = pulse; GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET);}    
#define Motor4_reverse(pulse)        {TIM8->CCR3 = pulse; GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);}
#define Motor3_stop()  	 			 {TIM8->CCR2 = 0; GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);}
#define Motor4_stop()  				 {TIM8->CCR3 = 0; GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);}
#define Motor3_forward(pulse)        {TIM8->CCR2 = pulse; GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);}
#define Motor4_forward(pulse)        {TIM8->CCR3 = pulse; GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);}
#define Move_stop()					 {Motor3_stop();Motor4_stop();}