大道五十,天衍四十九,人遁其一!
# 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
大概小结一下,开启编码器模式:
- 选定定时器,选定 Encoder 模式
- 配置 分配因子 和 计数周期
- 使用相关函数 获取计数值
以上皆为个人简单实践,如有错误,望斧正.
大道五十,天衍四十九,人遁其一!