大道五十,天衍四十九,人遁其一!

# STM32 HAL 库 编码器模式配置

前几天准备电赛的时候,朋友编码器数值读不出来,我好奇也就凑合了一下,记录一下配置过程

PS: 开发环境 STM32 HAL 库 + STM32CubeMX + MDK + VSCode + Windows10

# 相关硬件

# 电机

用的是 370 电机,减速器为 513, 减速比为 1:30

# 编码器

用的和电机一体的霍尔编码器,不知直到从哪买的,淘宝上查出来是 13pr

# 主控

用的普中的 407 核心板,换了一个牛角座,没有使用它 usb 转串口
跳线帽一接上,对接 Xshell Jlink 直接红灯.
用了一对 lora 的无线串口,外部高速晶振 8M

# HAL 库配置

# 工欲善其事

学习一个功能最好的方法就是直接查阅数据手册.
脉冲计数最有可能是定时器的输入捕获功能,所以咱先去看看有没有定时器有没有对应的模式,这种工作模式基本都在 通用或者高级 定时器上,先去看看高级定时器

哎,有。那再看看通用定时器

也有,TIM2 和 TIM5 的 counter 还是 32 位的
这样子就齐活了,现在去看看 编码器转起来的波形密度,决定用哪个定时器
13 ppr 我实在是不明白什么意思,只能等转起来直接看数据了

啧,这只能用 TIM2 先顶着了。接下去就去新建工程啦

# 基本配置

新建 HAL 库的新工程我就不详细说了,不会的可以参见这篇博客: 传送门.
这里我就简单的说一下基本配置

# SYS 配置

为了防止锁死芯片,Debug 选项配置为 Serial Wire

# 时钟配置

我使用外部高速晶振,

外部晶振 8M, 主频 168M, 时钟树如下

然后为了便于查看结果开启一路串口 USART1
配置如下

由于 TIM2 的 Counter Period 是 32 位的所以我在这里选择了 TIM2
没有进行分频,计数值拉到最大,防止溢出中断,通道 1 和通道 2 被编码器模式复用,所以编程灰色, combined Channels 选择 Encoder Mode

然后成功工程即可

# 相关函数

我们这里就简单的使用 DMA 和 IT 模式以后再探索

# 启动编码器计数

Encoder Mode 的 初始化函数和开启函数如下 如下图:

HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel);

参数是 对应的定时器 htim2, 因为有 A 相位,B 相位 使用两个通道,所以使用参数 TIM_CHANNEL_ALL

# 获取编码器数值

获取脉冲方向,返回方向 0 或 1

__HAL_TIM_IS_TIM_COUNTING_DOWN();

获取脉冲次数函数,返回脉冲次数

__HAL_TIM_GET_COUNTER();

TIM2 定时器 Encoder 模式读出的数值自带方向 (正负)

# 简单读取数值测试

我这里写了一个简单的测试样例

int getEncoderValue(void)
{
  int Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2);
  int GetData = __HAL_TIM_GET_COUNTER(&htim2);
  printf("Encoder: %d\r\n", GetData);
}

结果如下

我测出这个电机转一圈会产生 600 次脉冲,TIM2 和 TIM5 读出的 脉冲数自带方向当从 0 开始反向选装 printf 打印出的数据自带符号,

使用 printf 记得重定向一下 printf
这里提供一下全版本的 编译器的 printf 重定向

#include <stdio.h>
#if defined ( __CC_ARM )
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)        
/*
 * Arm Compiler above 6.10.1 (armclang)
 
 */
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
/*
 * GNU Compiler
 */
#elif defined ( __GNUC__ )
/* With GCC, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#endif
PUTCHAR_PROTOTYPE
{
    // 具体哪个串口可以更改 huart1 为其它串口
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1 , 0xffff);
    return ch;
}

# END

大概小结一下,开启编码器模式:

  1. 选定定时器,选定 Encoder 模式
  2. 配置 分配因子 和 计数周期
  3. 使用相关函数 获取计数值

以上皆为个人简单实践,如有错误,望斧正.


大道五十,天衍四十九,人遁其一!