STM32利用TB6612驱动直流电机和电机调速

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

一、引言

在许多嵌入式系统和机器人项目中,直流电机是常用的执行机构,用于实现各种机械运动。而 TB6612 是一款常用的直流电机驱动芯片,它可以方便地驱动两个直流电机,并且能够控制电机的正反转和调速。STM32 作为一款高性能的微控制器,与 TB6612 结合使用,可以实现对直流电机的精确控制。本文将详细介绍如何使用 STM32 利用 TB6612 驱动直流电机并实现电机调速。

二、TB6612 芯片简介

2.1 主要特性

  • 能够同时驱动两个直流电机。
  • 输出电流大,单通道连续驱动电流可达 1.2A,峰值电流可达 3.2A。
  • 支持正反转控制和制动功能。
  • 内置过热保护和低压检测电路,提高了系统的可靠性。

2.2 引脚功能

TB6612 有多个引脚,主要引脚功能如下:

  • VM:电源输入引脚,连接电机电源。
  • VCC:逻辑电源输入引脚,一般连接 3.3V 或 5V。
  • GND:接地引脚。
  • AIN1、AIN2、BIN1、BIN2:电机控制信号输入引脚,用于控制电机的正反转。
  • PWMA、PWMB:PWM 信号输入引脚,用于控制电机的转速。
  • AO1、AO2、BO1、BO2:电机输出引脚,连接电机的正负极。
  • STBY:待机控制引脚,低电平使芯片进入待机模式。

三、硬件连接

以 STM32F103C8T6 为例,与 TB6612 的硬件连接如下:

STM32 引脚TB6612 引脚功能
PA0PWMA控制电机 A 的 PWM 信号
PA1AIN1控制电机 A 的正反转信号 1
PA2AIN2控制电机 A 的正反转信号 2
PA3PWMB控制电机 B 的 PWM 信号
PA4BIN1控制电机 B 的正反转信号 1
PA5BIN2控制电机 B 的正反转信号 2
PA6STBY待机控制信号
3.3VVCC逻辑电源
电机电源VM电机电源
GNDGND接地

四、软件实现

4.1 初始化 GPIO 和 PWM

首先,需要初始化 STM32 的 GPIO 引脚,用于控制 TB6612 的正反转信号和待机信号。同时,需要初始化 PWM 定时器,用于生成控制电机转速的 PWM 信号。

#include "stm32f1xx_hal.h"

TIM_HandleTypeDef htim2;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();

  // 使能 TB6612
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);

  // 启动 PWM 输出
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);

  while (1)
  {
    // 这里可以添加电机控制逻辑
    HAL_Delay(1000);
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 71;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim2);
}

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6, GPIO_PIN_RESET);

  /*Configure GPIO pins : PA1 PA2 PA4 PA5 PA6 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
  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 Error_Handler(void)
{
  while(1)
  {
  }
}

4.2 电机控制函数

为了方便控制电机的正反转和调速,可以编写以下电机控制函数:

// 控制电机 A 的正反转和调速
void motorA_control(int direction, int speed)
{
  if (direction == 1) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
  } else if (direction == -1) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
  } else {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
  }

  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, speed);
}

// 控制电机 B 的正反转和调速
void motorB_control(int direction, int speed)
{
  if (direction == 1) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  } else if (direction == -1) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  } else {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  }

  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, speed);
}

4.3 主函数中的电机控制逻辑

在主函数中,可以调用电机控制函数来实现电机的正反转和调速。

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();

  // 使能 TB6612
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);

  // 启动 PWM 输出
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);

  while (1)
  {
    // 电机 A 正转,速度为 500
    motorA_control(1, 500);
    // 电机 B 反转,速度为 300
    motorB_control(-1, 300);
    HAL_Delay(2000);

    // 电机 A 停止
    motorA_control(0, 0);
    // 电机 B 停止
    motorB_control(0, 0);
    HAL_Delay(2000);
  }
}

五、代码解释

5.1 初始化部分

  • SystemClock_Config():配置系统时钟,确保 STM32 以正确的时钟频率运行。
  • MX_GPIO_Init():初始化 GPIO 引脚,用于控制 TB6612 的正反转信号和待机信号。
  • MX_TIM2_Init():初始化定时器 2,用于生成 PWM 信号。设置了定时器的预分频器、计数模式、周期等参数,并配置了 PWM 输出通道。

5.2 电机控制函数

  • motorA_control(int direction, int speed):控制电机 A 的正反转和调速。direction 参数为 1 表示正转,-1 表示反转,0 表示停止;speed 参数表示 PWM 占空比,范围为 0 - 999。
  • motorB_control(int direction, int speed):控制电机 B 的正反转和调速,原理与 motorA_control 相同。

5.3 主函数

在主函数中,首先进行初始化操作,然后使能 TB6612 芯片,启动 PWM 输出。在循环中,交替控制电机 A 和电机 B 的正反转和停止,每个状态持续 2 秒。

六、注意事项

  • 电源供应:TB6612 的 VM 引脚需要连接合适的电机电源,确保电机能够正常工作。同时,要注意电源的稳定性和功率。
  • PWM 频率:PWM 频率会影响电机的运行效果。可以根据电机的特性和应用需求调整 PWM 频率。
  • 过热保护:TB6612 内置了过热保护电路,但在长时间大电流运行时,仍需注意芯片的散热问题。

通过以上步骤和代码,就可以使用 STM32 利用 TB6612 驱动直流电机并实现电机调速。在实际应用中,可以根据具体需求对代码进行扩展和优化,以实现更复杂的电机控制功能。

### 使用TB6612驱动四个直流电机 #### 控制方案概述 为了控制四个直流电机,由于单个TB6612仅能驱动两个电机[^3],因此需要两块TB6612芯片来分别控制两组电机。每块TB6612可以独立工作并通过微控制器(如STM32)统一协调。 #### 硬件连接说明 对于每个TB6612模块: - **电源接入** - VIN 接入外部电池或稳压源(最大不超过15V) - GND 连接到公共地线 - **逻辑电平接口** - STBY 设置为高电平时使能操作;低电平则停止所有动作。 - AIN1/AOUT1, BIN1/BOUT1 分别对应左/右轮的前进后退控制引脚。 - **PWM调速输入** - PWMA PWMB 可接收来自MCU发出的不同占空比脉宽调制(PWM)信号用于调节速度。 当扩展到四台电机时,则需额外准备另一套相同的配置并确保两者间共享同一参考地以及同步接受来自同一个处理器发送过来的方向指令与速度设定值。 #### 示例电路图解 假设采用STM32作为主控单元,其具体连线如下所示: | STM32 Pin | Function | Connected To | |-----------|----------------|--------------| | PA0 | PWM Output | TB6612_1.PWMA| | PB7 | Direction Ctrl.| TB6612_1.AIN1| | PC8 | Standby Enable | TB6612_1.STBY| | PD9 | PWM Output | TB6612_2.PWMA| | PE10 | Direction Ctrl.| TB6612_2.BIN1| | PF11 | Standby Enable | TB6612_2.STBY| 注意这里只列举了一部分必要的连接关系,完整的接线还需要考虑其他因素比如电流反馈监测等辅助功能。 #### 编程实例 下面给出一段简单的C语言代码片段展示如何初始化设置及基本运动控制命令: ```c #include "stm32f4xx_hal.h" // 定义GPIO端口映射 #define MOTOR_LEFT_FORWARD GPIO_PIN_SET #define MOTOR_RIGHT_FORWARD GPIO_PIN_RESET #define MOTOR_STANDBY HIGH void Motor_Init(void){ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 初始化PA0为PWM输出模式... HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动定时器产生PWM波形 } void SetMotorSpeed(uint8_t motorIndex,float speedPercentage){ uint16_t pwmValue; if(speedPercentage>100 || speedPercentage<0)return; switch(motorIndex){ case 0:// 左前轮 pwmValue=(uint16_t)(speedPercentage*TIM_MAX_COMPARE_VALUE/100); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,pwmValue); break; case 1:// 右前轮 ... default: ; } } ``` 此段伪码展示了针对特定编号电机调整转动速率的方法,并通过改变PWM周期内的有效宽度比例实现变速效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值