掌握驱动之道:L298N模块多方式驱动电机的优劣分析

文章介绍了四种使用STM32微控制器通过L298N模块控制直流电机的方法,包括使用高级定时器输出通道和互补输出通道、通用定时器、普通GPIO以及混合使用PWM和GPIO。每种方法都有其优缺点,适用于不同精度和资源需求的电机控制场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

L298N模块是一种常用的直流电机驱动模块,它可以通过控制输入端口来实现对电机的速度和方向的控制。L298N模块有3个输入端口:IN1、IN2和EN。

方法一:使用高级定时器输出通道和互补输出通道控制电机 将模块的IN1和IN2分别连接到STM32高级定时器输出通道引脚和互补输出通道引脚,通过配置定时器的输出通道和互补输出通道的PWM大小来控制电机的速度和方向。将一个普通的GPIO引脚连接到模块的EN端口来控制电机的制动和启动。

下面是使用STM32的HAL库来配置定时器和GPIO引脚的代码示例:

#include "stm32f4xx_hal.h"

// 定义L298N模块的引脚
#define IN1_Pin GPIO_PIN_0
#define IN1_GPIO_Port GPIOA
#define IN2_Pin GPIO_PIN_1
#define IN2_GPIO_Port GPIOA
#define EN_Pin GPIO_PIN_2
#define EN_GPIO_Port GPIOA

// 定义定时器和互补输出通道
#define TIM_PWM TIM_CHANNEL_1
#define TIM_COMPLEMENTARY PWM_CHANNEL_2

// 配置定时器和GPIO引脚
void MX_TIM_Config(void)
{
  // 定时器初始化
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Init.Prescaler = 0;
  htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim.Init.Period = 1000;
  htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim.Init.RepetitionCounter = 0;
  htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  HAL_TIM_PWM_Init(&htim);

  // GPIO引脚初始化
  GPIO_InitTypeDef GPIO_InitStruct;

  GPIO_InitStruct.Pin = IN1_Pin | IN2_Pin | EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 控制电机的速度和方向
void motorControl(uint16_t speed)
{
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Channel = TIM_PWM;

  // 设置PWM输出通道的比例,控制电机的速度
  HAL_TIM_PWM_Start(&htim, TIM_PWM);
  HAL_TIM_PWM_SetValue(&htim, TIM_PWM, speed);

  // 设置互补输出通道,控制电机的方向
  HAL_TIMEx_PWMN_Start(&htim, TIM_COMPLEMENTARY);
  HAL_TIMEx_PWMN_SetValue(&htim, TIM_COMPLEMENTARY, 100 - speed);
}

// 控制电机的启动和停止
void motorStartStop(uint8_t enable)
{
  GPIO_PinState state = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;
  HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, state);
}


该方法的优点是可以精确控制电机的速度和方向,缺点是需要使用高级定时器和互补输出通道,占用了宝贵的硬件资源。适用于需要精确控制电机的应用场景。

方法二:使用通用定时器控制电机 将模块的IN1和IN2分别连接到STM32通用定时器的两个输出通道引脚,通过配置定时器的这两个输出通道的PWM大小来控制电机的速度和方向。同样,将一个普通的GPIO引脚连接到模块的EN端口来控制电机的制动和启动。

#include "stm32f4xx_hal.h"

// 定义L298N模块的引脚
#define IN1_Pin GPIO_PIN_0
#define IN1_GPIO_Port GPIOA
#define IN2_Pin GPIO_PIN_1
#define IN2_GPIO_Port GPIOA
#define EN_Pin GPIO_PIN_2
#define EN_GPIO_Port GPIOA

// 定义定时器和输出通道
#define TIM_PWM TIM_CHANNEL_1

// 配置定时器和GPIO引脚
void MX_TIM_Config(void)
{
  // 定时器初始化
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Init.Prescaler = 0;
  htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim.Init.Period = 1000;
  htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim.Init.RepetitionCounter = 0;
  htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  HAL_TIM_PWM_Init(&htim);

  // GPIO引脚初始化
  GPIO_InitTypeDef GPIO_InitStruct;

  GPIO_InitStruct.Pin = IN1_Pin | IN2_Pin | EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 控制电机的速度
void motorSpeedControl(uint16_t speed)
{
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Channel = TIM_PWM;

  // 设置PWM输出通道的比例,控制电机的速度
  HAL_TIM_PWM_Start(&htim, TIM_PWM);
  HAL_TIM_PWM_SetValue(&htim, TIM_PWM, speed);
}

// 控制电机的方向
void motorDirectionControl(uint8_t direction)
{
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;

  // 停止对应的PWM信号,控制电机的方向
  if (direction == 0) {
    HAL_TIM_PWM_Stop(&htim, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1);
  } else {
    HAL_TIM_PWM_Stop(&htim, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2);
  }
}

// 控制电机的启动和停止
void motorStartStop(uint8_t enable)
{
  GPIO_PinState state = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;
  HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, state);
}


方法二可以通过停止对应的PWM信号来控制电机的方向,通过调用motorDirectionControl()函数,
传入0表示正向运动,1表示反向运动。同时,使用motorSpeedControl()函数来控制电机的速度,通过改变PWM的占空比来调节电机的转速。最后,使用motorStartStop()函数来启动或停止电机,传入1表示启动电机,传入0表示停止电机。

这种方法的优点是使用通用定时器控制电机,灵活性较高,可以同时控制电机的速度和方向。适用于需要精确控制电机运动的应用场景。

方法三:将模块的IN1和IN2分辨链接到STM32的普通GPIO引脚来控制电机的运转方向和启动、停止,将模块的EN端口连接到定时器的PWM端口来控制电机的速度,该控制方法的编程代码解析如下:

下面是使用STM32的HAL库来配置GPIO引脚的代码示例:

#include "stm32f4xx_hal.h"

// 定义L298N模块的引脚
#define IN1_Pin GPIO_PIN_0
#define IN1_GPIO_Port GPIOA
#define IN2_Pin GPIO_PIN_1
#define IN2_GPIO_Port GPIOA
#define EN_Pin GPIO_PIN_2
#define EN_GPIO_Port GPIOA

// 定义定时器和PWM通道
#define TIM_PWM TIM_CHANNEL_1

// 配置GPIO引脚
void MX_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  GPIO_InitStruct.Pin = IN1_Pin | IN2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 控制电机的速度
void motorSpeedControl(uint16_t speed)
{
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Channel = TIM_PWM;

  // 设置PWM输出通道的比例,控制电机的速度
  HAL_TIM_PWM_Start(&htim, TIM_PWM);
  HAL_TIM_PWM_SetValue(&htim, TIM_PWM, speed);
}

// 控制电机的方向和启动停止
void motorDirectionControl(uint8_t direction, uint8_t enable)
{
  GPIO_PinState state1 = direction ? GPIO_PIN_SET : GPIO_PIN_RESET;
  GPIO_PinState state2 = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;

  HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, state1);
  HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, state2);
}

该方法的优点是简单易实现,缺点是无法精确控制电机的速度和方向。适用于简单的电机控制应用场景。

方法四:就是将IN1链接到定时器的PWM通道引脚上,将IN2链接到一个普通的GPIO端口上,控制IN2端口的电平就可以控制电机方向,控制IN1上的PWM信号就可以控制电机的速度,控制EN端口的电平就可以控制到电机的启动、停止,只是电机控制控制在两个方向上的PWM的表达不一致,在IN2为低电平的正方向上PWM大速度就高,而在IN2为低电平的反方向运转则是PWM小速度高,
方法四中,将IN1连接到定时器的PWM通道引脚上,通过改变PWM的占空比来控制电机的速度。将IN2连接到一个普通的GPIO端口上,通过改变IN2引脚的电平来控制电机的方向。同时,使用EN引脚来控制电机的启动和停止。

#include "stm32f4xx_hal.h"

// 定义L298N模块的引脚
#define IN1_Pin GPIO_PIN_0
#define IN1_GPIO_Port GPIOA
#define IN2_Pin GPIO_PIN_1
#define IN2_GPIO_Port GPIOA
#define EN_Pin GPIO_PIN_2
#define EN_GPIO_Port GPIOA

// 定义定时器和PWM通道
#define TIM_PWM TIM_CHANNEL_1

// 配置定时器和GPIO引脚
void MX_TIM_Config(void)
{
  // 定时器初始化
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Init.Prescaler = 0;
  htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim.Init.Period = 1000;
  htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim.Init.RepetitionCounter = 0;
  htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  HAL_TIM_PWM_Init(&htim);

  // GPIO引脚初始化
  GPIO_InitTypeDef GPIO_InitStruct;

  GPIO_InitStruct.Pin = IN1_Pin | EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = IN2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 控制电机的速度
void motorSpeedControl(uint16_t speed , uint8_t direction)
{
  TIM_HandleTypeDef htim;

  htim.Instance = TIM1;
  htim.Channel = TIM_PWM;

  // 设置PWM输出通道的比例,控制电机的速度
  HAL_TIM_PWM_Start(&htim, TIM_PWM);
  uint16_t speed_ = direction ? speed :100 - speed ; 
  HAL_TIM_PWM_SetValue(&htim, TIM_PWM, speed);
}

// 控制电机的方向
void motorDirectionControl(uint8_t direction)
{
  GPIO_PinState state = direction ? GPIO_PIN_SET : GPIO_PIN_RESET;
  HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, state);
}

// 控制电机的启动和停止
void motorStartStop(uint8_t enable)
{
  GPIO_PinState state = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;
  HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, state);
}

该方法的优点是可以通过一个普通的GPIO引脚来控制电机的方向,同时使用定时器的PWM通道来控制电机的速度。相对于方法二而言,方法四减少了一个PWM通道的使用,并且方向控制更加直观和灵活。缺点是需要对PWM信号与方向的控制进行特殊的映射,需要根据具体需求来调整PWM占空比和方向控制的规则。

适用场景分析: 方法四适用于需要控制电机方向和速度的应用场景,且对PWM通道的资源需求较高的情况下,例如需要控制多个电机的时候。同时,方法四也适用于对控制精度要求不高的场景,例如一些简单的机械运动控制。

综上所述,不同的链接方式和驱动方法适用于不同的应用场景。方法一可以精确控制电机的速度和方向,适用于需要精细控制的应用场景;方法二适用于需要精确控制电机运动的应用场景。方法三简单易实现,适用于简单的电机控制应用场景。根据具体需求选择合适的方法来驱动电机。方法四也适用于对控制精度要求不高的场景,例如一些简单的机械运动控制。
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老白同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值