STMCubeMX使用TB6612驱动编码轮并进行测速

硬件介绍

TB6612电机驱动模块功能与特性

电机方向控制

描述如何通过 TB6612 的 IN1 和 IN2 引脚控制电机的旋转方向。提供代码示例,展示如何通过 GPIO 控制电机的正反转。

速度控制与减速

解释如何通过调整 PWM 信号的占空比来控制电机的速度,并实现减速功能。提供代码示例,展示如何动态调整 PWM 占空比以实现速度控制。

编码减速电机的结构与工作原理

系统设计

TB6612的连接

编码减速电机的连接

原理图如下

软件STM32CubeMX实现

初始化代码:GPIO

控制电机的旋转方向AIN1和AIN2,使用PA4和PA5,设置成推挽输出,其他参数默认

PWM输出:

使用TIM2时钟的PWM通道1->PA0输出PWM,PWM的占空比调节范围0-100

占空比 = 1/(ARR+1)

开启定时器使能

编码器接口配置:

编码轮的测速中断使用TIM3,选择Encoder Mode使用TI1andTI2(四分频),其他默认

IO口使用PA6的TIM3_CH1和PA7的TIM3_CH2

设置测速计算的定时器TIM4,定时时间10ms

开启TIM4定时器使能

Keil软件的代码编写

fun.c函数

复制代码
#include "fun.h"
#include "tim.h"

/**
 * @description: 编码轮获取计数值函数
 * @return {*}
 */
float speed = 0;          // 当前速度
int16_t Encoder_Get(void) {
    int16_t cnt = (int16_t)__HAL_TIM_GET_COUNTER(&htim3);
    __HAL_TIM_SET_COUNTER(&htim3, 0);
    return cnt;
}

/**
 * @description: 
 * @param {TIM_HandleTypeDef} *htim
 * @return {*}
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == Encoder1_TIM_time)   // TIM4:10ms
    {
        int16_t count = Encoder_Get();  // 获取编码器计数值
    // 计算速度 (转/分钟)
    // 公式: (count / 11*4) / 10ms * 60000ms/min
        speed = (float)count * 545.45f / 44.0f;   //四分频11*4
    }
}

/**
 * @description: 编码轮正反转函数
 * @param {int} direction 0正转 1反转 2停止
 * @param {uint16_t} speed 速度0-100
 * @return {*}
 */
void Motor1_Set(int direction, uint16_t speed)
{
    switch (direction)
    {
    case FORWARD:
    {
        Motor1_AIN1_G->ODR |= Motor1_AIN1_P;  // AIN1=1
        Motor1_AIN1_G->ODR &= ~Motor1_AIN2_P; // AIN2=0
    }
    break;
    case BACKWARD:
    {
        Motor1_AIN1_G->ODR &= ~Motor1_AIN1_P; // AIN1=0
        Motor1_AIN2_G->ODR |= Motor1_AIN2_P;  // AIN2=1
    }
    break;
    case BRAKE:
    {
        Motor1_AIN1_G->ODR &= ~Motor1_AIN1_P; // AIN1=0
        Motor1_AIN1_G->ODR &= ~Motor1_AIN2_P; // AIN2=0
    }
    break;
    }
    Motor1_PWM_CCR1 = speed;
}

/**
 * @brief  控制小车运动
 * @param  direction: 运动方向(CAR_FORWARD/CAR_BACKWARD/CAR_LEFT/CAR_RIGHT)
 * @param  speed: 速度值(0~100)
 */
void Car_Move(int direction, uint16_t speed)
{
    switch (direction)
    {
    // 前进:所有电机正转
    case CAR_FORWARD:
    {
        Motor1_Set(0, speed); // 左前轮正转
    }
    break;

    // 后退:所有电机反转
    case CAR_BACKWARD:
    {
        Motor1_Set(1, speed); // 左前轮反转
    }
    break;

    // 左转:左侧反转,右侧正转(原地左旋)
    case CAR_LEFT:
    {
        Motor1_Set(1, speed); // 左前轮反转
    }
    break;

    // 右转:右侧反转,左侧正转(原地右旋)
    case CAR_RIGHT:
    {
        Motor1_Set(0, speed); // 左前轮正转
    }
    break;

    // 刹车:所有电机停止
    case CAR_BRAKE:
    {
        Motor1_Set(2, 0); // 左前轮刹车
    }
    break;
    }
}

fun.h函数

复制代码
#ifndef __FUN_H
#define __FUN_H

#include "main.h"

/* 一个编码电机IO定义===========================================================*/
#define Motor1_AIN1_G GPIOA           // 定义电机1的AIN1的GPIOx
#define Motor1_AIN1_P GPIO_PIN_8      // 定义电机1的AIN1的GPIO_PIN_x
#define Motor1_AIN2_G GPIOA           // 定义电机1的AIN2的GPIOx
#define Motor1_AIN2_P GPIO_PIN_9      // 定义电机1的AIN2的GPIO_PIN_x
#define Motor1_PWM_CCR1 TIM2->CCR3    // 定义电机1的PWM输出为TIM2的TIM_CHANNEL_1
#define Encoder1_TIM_time TIM4        // 定义用于编码器的测速定时器
#define Encoder1_TIM_time_htim htim4       // 定义用于编码器的测速定时器句柄
#define Encoder1_TIM TIM3             // 定义编码器定时器通道TIMx-ch1与TIMx-ch2
#define Encoder1_TIM_htim htim3       // 定义编码器定时器句柄
/* Motor1_Set:电机转动的数值定义=============================================== */
#define FORWARD  0  // 正转
#define BACKWARD 1  // 反转
#define BRAKE    2  // 不转
/* Car_Move:小车移动的数值定义================================================= */
#define CAR_FORWARD  0 // 前进
#define CAR_BACKWARD 1 // 后退
#define CAR_LEFT     2 // 原地左转
#define CAR_RIGHT    3 // 原地右转
#define CAR_BRAKE    4 // 刹车
/* 调用小车的封装函数========================================================== */
void Motor1_Set(int direction, uint16_t speed);
void Car_Move(int direction, uint16_t speed);
int32_t Encoder_Get(void);

#endif

main.c函数

在while循环前加初始化

复制代码
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);       //小车PWM输出 
  HAL_TIM_Base_Start_IT(&htim4);                  //计算速度定时器
  HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); // 开启编码器定时器
  extern float speed;                           //全局声明速度

while循环

复制代码
  while (1)
  {
     char ta[15];
     sprintf(ta,"c= %.3lf   ", speed);
     OLED_ShowString(2,2,ta);
     Motor1_Set(1, 30);
  }

这样子就可以在OLED上显示速度了

调试与测试

实现

相关推荐
昊昊昊昊昊明29 分钟前
十天学会嵌入式技术之51单片机—day-10
单片机·嵌入式硬件·51单片机
赵谨言1 小时前
基于单片机的车灯智能控制系统设计与实现
经验分享·单片机·毕业设计
剑鞘的流苏1 小时前
STM32-USART串口通信(9)
stm32·单片机·嵌入式硬件
集思广益的灰太狼3 小时前
静电的起因与静电效应:技术分析与应用
单片机·硬件工程
憧憬一下4 小时前
stm32之FLASH
stm32·单片机·嵌入式
@NachoNEKO5 小时前
一种资源有限单片机处理cJSON数据的方法
单片机·嵌入式硬件
qq_301881696 小时前
XD08M3232接近感应单片机的接近感应模块的工作原理
单片机·嵌入式硬件·硬件架构
不脱发的程序猿7 小时前
MCU裸机程序如何移植到RTOS?
单片机·嵌入式硬件·rtos
PAQQ7 小时前
【python】windows实现与k230使用socket通信并传输文件
python·stm32·单片机