L298N驱动俩路电机按键控制正反转

一个L298N是带有俩路驱动电路的,就是可以驱动俩个电机同时去转动,在硬件部分因为以前弄小车的时候已经组装好了,一路驱动去控制俩个电机,俩路驱动就是控制四个电机,做的是四轮四驱的小车,嫌麻烦就没有去拆改装了。

博主主页里面有介绍过L298N的使用了,为了避免一些小伙伴不明白还是重新介绍一下,方便大家的使用。

一、L298N的结构介绍示意图如下

1.12v电压输入,GND供地端,5v我自己认为是输出一个5v的接口但上一节的时候不是很明白就没有去作过多的描述,现在可以确定了可以输出一个5v供电。

当vcc端接入一个7~12v的电压时,正5v不需要接电压,GND接单片机的GND,可以输出一个5v电压给单片机使用。

2.使能端,L298N有俩个使能端口,分别是ENA和ENB,用一个跳线帽接在板载5v上面,逻辑输入数字信号0,1就可以在相应得输出端输出信号,因为在只有数字信号0,1所以并不能实现电机的调速,只能实现电机的左右转。调速就把跳线帽拔下来,用一个PWM信号脉冲波接着使能端,也就是ENA或ENB,这样就能通过控制PWM的占空比来实现电机的调速。

3逻辑输入端口,IN1-IN4四个输入口,对应着相应的输出端口,给0,1就能控制电机的正反转

4.输出口,接电机的正反极,不分正负极随便接都行。

二、L298N的使用说明:

直流电机的驱动:

L298N能输出俩路控制俩个电机转动,使能端ENA和ENB高电平有效。

如图所示真值表:

  我们需要对电机进行调速,需要设置IN1,IN2确定电机的转动方向,然后拔掉跳线帽接上PWM信号。调整占空比就可以实现电机的调速,注意当使能端信号为0时电机处于停止状态,当使能端为1,逻辑输入全部为0或1的时候电机制动,会阻止电机转动,只有逻辑输入为01或10的时候电机才会正常转动。
 

 三、基于STM32的部分代码

1.PWM初始化,因为是要驱动俩路电机,所以初始化当中要使能俩路通道,不懂得小伙伴可以去主页看一下有讲。在实验中我们初始化了四路通道,任选其中俩路都是可以的。

定时器2初始化

// 通用定时器2中断初始化
// 这里时钟选择APB1的2倍,而APB1为36M
// arr自动重装值
// psc时钟分频数
void TIM2_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //  自动重装值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; // 时钟分频数
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //时候基数单位 

	TIM_Cmd(TIM2, ENABLE);  //使能
							 
}

PWM初始化 

void TIM2_PWM_Init(u16 arr,u16 psc)
{
	 GPIO_InitTypeDef GPIO_InitStructure;                
	 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;       
	 TIM_OCInitTypeDef  TIM_OCInitStructure;               //定义结构体
	
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  //使能定时器3时钟
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO| 
     RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟

     GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	 GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2 , ENABLE); //Timer2部分重映射


     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_15; //TIMx_CHx
     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(TIM2, &TIM_TimeBaseStructure);// 初始化时钟基数单位
   
 
	 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;   //脉宽调制模式2
 	 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       // 输出极性为高    
     TIM_OCInitStructure.TIM_OutputState=	TIM_OutputState_Enable;   //比较输出使能
     TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值

    //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
     TIM_OC1Init(TIM2, &TIM_OCInitStructure);  
     TIM_OC2Init(TIM2, &TIM_OCInitStructure);  //
     TIM_OC3Init(TIM2, &TIM_OCInitStructure);  //
     TIM_OC4Init(TIM2, &TIM_OCInitStructure);  //
    
 
     //使能预装载寄存器
     TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
     TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
     TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
     TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
	
	 TIM_ARRPreloadConfig(TIM2, ENABLE);      //使能自动装载允许位
 
	 TIM_Cmd(TIM2, ENABLE);   //使能定时器
 
}

2.电机初始化,采用的是直流减速电机不带编码器。

void motro_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);	 //使能GPIOF端口
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7;//端口设置			 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //设置速度
 GPIO_Init(GPIOF, &GPIO_InitStructure);					 //初始化GPIOF
 GPIO_SetBits(GPIOF,GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7);						 //输出高电平
}
 

3.按键初始化

void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	//使能 PORTA,PORTE时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉
 	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化io

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化io

}

3.1.按键扫描函数

u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键松开标志
	if(mode)key_up=1;  //支持连按	  
	if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
	{
		delay_ms(10);//去抖动
		key_up=0;
		if(KEY0==0)return KEY0_PRES;
		else if(KEY1==0)return KEY1_PRES;
		else if(WK_UP==1)return WKUP_PRES;
	}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; 	    
 	return 0;// 无按键按下
}

4.主函数

 int main(void)
{ 
  u8 key; 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统优先级分组2
  delay_init();  //延时函数初始化
	uart_init(115200);//初始串口波特率为115200
  KEY_Init();  //按键初始化
	motro_Init();//电机初始化
	TIM2_PWM_Init(899,0);	//PWM初始化  
   while(1) //ʵÏֱȽÏÖµ´Ó0-300µÝÔö£¬µ½300ºó´Ó300-0µÝ¼õ£¬Ñ­»·
	{
 	 	key=KEY_Scan(0);		//得到键值
	   	if(key)
		{						   
			switch(key)
			{				 
				case KEY0_PRES:	//控制电机翻转
				  F4=0;
				  F5=0;
				  F6=1;  
				  F7=1;
					break;
				case KEY1_PRES:	//
				  F4=1;
				  F5=1;
				  F6=0;  
				  F7=0;
					break;
			}
		}else delay_ms(10); 	 
        //设置占空比
		TIM_SetCompare1(TIM2,350);
        TIM_SetCompare2(TIM2,350);       
        TIM_SetCompare3(TIM2,350);         
        TIM_SetCompare4(TIM2,350);  
	}
}

四、实验效果:

PWM控制小车前后转

拍的不是很好,将就着看吧哈哈,需要完整工程文件的点赞加收藏评论区留邮箱,创作不易。

猜你喜欢

转载自blog.csdn.net/m0_63171897/article/details/127345321