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上显示速度了

调试与测试

实现

相关推荐
茯苓gao4 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉7 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者8 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间9 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious9 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng13 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计14 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试一、基本概念
嵌入式硬件·通信与接口协议
wuyk5551 天前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机
☆cwlulu1 天前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu