STM32编码器的学习笔记
编码器
编码器参数:
- 分辨率:指编码器能够分辨的最小单位。对于增量式编码器,其分辨率表示为编码器转轴旋转一圈所产生的脉冲数,即脉冲数/转 (Pulse Per Revolution 或 PPR)。码盘上透光线槽的数目其实就等于分辨率,也叫多少线,较为常见的有 5-6000 线。对于绝对式编码器,内部码盘所用的位数就是它的分辨率,单位是位 (bit),具体还分单圈分辨率和多圈分辨率。
- 精度:首先明确一点,精度与分辨率是两个不同的概念。精度是指编码器每个读数与转轴实际位置间的最大误差,通常用角度、角分或角秒来表示。例如有些绝对式编码器参数表里会写 ±20′′,这个就表示编码器输出的读数与转轴实际位置之间存在正负 20 角秒的误差,精度由码盘刻线加工精度、转轴同心度、材料的温度特性、电路的响应时间等各方面因素共同决定。
- 最大响应频率:指编码器每秒输出的脉冲数,单位是 Hz。计算公式:最大响应频率 = 分辨率 * 轴转速/60。
- 信号输出形式:对于增量式编码器,每个通道的信号独立输出 上图就是常规信号输出,还有正弦信号输出形式,输出电路形式通常有集电极开路输出、推挽输出、差分输出等。对于绝对式编码器,由于是直接输出几十位的二进制数,为了确保传输速率和信号质量,一般采用串行输出或总线型输出,例如同步串行接口 (SSI)RS485CANopen 或 EtherCAT 等,也有一部分是并行输出,输出电路形式与增量式编码器相同。
STM32编码器接口介绍,
- 如果计数器仅在 TI2 边沿处计数,在 TIMx_SMCR 寄存器中写入 SMS=“001”;
- 如果计数器仅在 TI1 边沿处计数,写入 SMS=“010”;
- 如果计数器在 TI1 和 TI2 边沿处均计数,则写入 SMS=“011”。
- 通过编程 TIMx_CCER 寄存器的 CC1P 和 CC2P 位,选择 TI1 和 TI2 极性。
- 如果需要,还可 对输入滤波器进行编程。CC1NP 和 CC2NP 必须保持低电平。
- TI1 和 TI2 两个输入用于连接增量编码器。如果使能计数器(在 TIMx_CR1 寄 存器的 CEN 位中写入“1”),则计数器的时钟由 TI1FP1 或 TI2FP2 上的每次有效信号转 换提供。
- TI1FP1 和 TI2FP2 是进行输入滤波器和极性选择后 TI1 和 TI2 的信号,如果不进行 滤波和反相,则 TI1FP1=TI1,TI2FP2=TI2。
- 将根据两个输入的信号转换序列,产生计数脉冲和方向信号。
- 根据该信号转换序列,计数器相应递增或递减计数,同时硬件对 TIMx_CR1 寄存器的 DIR 位进行相应修改。
- 任何输入(TI1 或 TI2)发生信号转换时,都会计算 DIR 位,无论计数器是仅在 TI1 或 TI2 边沿处计数,还是同时在 TI1 和 TI2 处计数。
- 编码器接口模式就相当于带有方向选择的外部时钟。
- 这意味着,计数器仅在 0 到 TIMx_ARR 寄存器中的自动重载值之间进行连续计数(根据具体方向,从 0 递增计数到 ARR,或从 ARR 递减计数到 0)。因此,在启动前必须先配置 TIMx_ARR。
- 同样,捕获、比较、预分频 器、重复计数器及触发输出功能继续正常工作。编码器模式和外部时钟模式 2 不兼容,因此 不能同时选择。
1. 下图就是电机正转的编码器输出波形,上表的红线计数方式
2. 通道A接TI1,通道B接TI2
3.TI1FP1的计数方向,需要参考TI2的电平
4. TI2FP2的计数方向,需要参考TI1的电平
顺时针旋转就是一个递增的计数器
逆时针旋转就是一个递减的计数器
STM32寄存器介绍
编码器的使用:
- 设置从模式寄存器的SMCR(SMS) 工作模式:编码器模式1,编码器模式2,编码器模式3;
- 设置输入引脚为TI1,TI2
- 设置触发的极性CCER(CC1P,CC2P)
- 设置滤波和分频 SCMR(IC1F,IC1PSC IC2F,IC2PSC)
- 使能计数器 CR1(CEN)
- 硬件会自动设置CR1(DIR)方向位;
不完整代码:
#ifndef __BSP_ENCOEDER_H
#define __BSP_ENCOEDER_H#include "stm32f4xx.h"/* 定时器选择 */
#define ENCODER_TIM TIM3
#define ENCODER_TIM_CLK_ENABLE() __HAL_RCC_TIM3_CLK_ENABLE()/* 定时器溢出值 */
#define ENCODER_TIM_PERIOD 65535
/* 定时器预分频值 */
#define ENCODER_TIM_PRESCALER 0 /* 定时器中断 */
#define ENCODER_TIM_IRQn TIM3_IRQn
#define ENCODER_TIM_IRQHandler TIM3_IRQHandler/* 编码器接口引脚 */
#define ENCODER_TIM_CH1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define ENCODER_TIM_CH1_GPIO_PORT GPIOC
#define ENCODER_TIM_CH1_PIN GPIO_PIN_6
#define ENCODER_TIM_CH1_GPIO_AF GPIO_AF2_TIM3#define ENCODER_TIM_CH2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define ENCODER_TIM_CH2_GPIO_PORT GPIOC
#define ENCODER_TIM_CH2_PIN GPIO_PIN_7
#define ENCODER_TIM_CH2_GPIO_AF GPIO_AF2_TIM3/* 编码器接口倍频数 */
#define ENCODER_MODE TIM_ENCODERMODE_TI12/* 编码器接口输入捕获通道相位设置 */
#define ENCODER_IC1_POLARITY TIM_ICPOLARITY_RISING
#define ENCODER_IC2_POLARITY TIM_ICPOLARITY_RISING/* 编码器物理分辨率 */
#define ENCODER_RESOLUTION 16/* 经过倍频之后的总分辨率 */
#if (ENCODER_MODE == TIM_ENCODERMODE_TI12)#define ENCODER_TOTAL_RESOLUTION (ENCODER_RESOLUTION * 4) /* 4倍频后的总分辨率 */
#else#define ENCODER_TOTAL_RESOLUTION (ENCODER_RESOLUTION * 2) /* 2倍频后的总分辨率 */
#endif/* 减速电机减速比 */
#define REDUCTION_RATIO 30extern __IO int16_t Encoder_Overflow_Count;
extern TIM_HandleTypeDef TIM_EncoderHandle;void Encoder_Init(void);#endif /* __BSP_ENCODER_H */
/********************************************************************************* @file bsp_motor_control.c* @author fire* @version V1.0* @date 2019-xx-xx* @brief 编码器接口******************************************************************************* @attention** 实验平台:野火 STM32 F407 开发板 * 论坛 :http://www.firebbs.cn* 淘宝 :http://firestm32.taobao.com********************************************************************************/ #include "./Encoder/bsp_encoder.h"/* 定时器溢出次数 */
__IO int16_t Encoder_Overflow_Count = 0;TIM_HandleTypeDef TIM_EncoderHandle;/*** @brief 编码器接口引脚初始化* @param 无* @retval 无*/
static void Encoder_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* 定时器通道引脚端口时钟使能 */ENCODER_TIM_CH1_GPIO_CLK_ENABLE();ENCODER_TIM_CH2_GPIO_CLK_ENABLE();/* 设置输入类型 */GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;/* 设置上拉 */GPIO_InitStruct.Pull = GPIO_PULLUP;/* 设置引脚速率 */GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;/* 选择要控制的GPIO引脚 */ GPIO_InitStruct.Pin = ENCODER_TIM_CH1_PIN;/* 设置复用 */GPIO_InitStruct.Alternate = ENCODER_TIM_CH1_GPIO_AF;/* 调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO */HAL_GPIO_Init(ENCODER_TIM_CH1_GPIO_PORT, &GPIO_InitStruct);/* 选择要控制的GPIO引脚 */ GPIO_InitStruct.Pin = ENCODER_TIM_CH2_PIN;/* 设置复用 */GPIO_InitStruct.Alternate = ENCODER_TIM_CH2_GPIO_AF;/* 调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO */HAL_GPIO_Init(ENCODER_TIM_CH2_GPIO_PORT, &GPIO_InitStruct);
}/*** @brief 配置TIMx编码器模式* @param 无* @retval 无*/
static void TIM_Encoder_Init(void)
{ TIM_Encoder_InitTypeDef Encoder_ConfigStructure;/* 使能编码器接口时钟 */ENCODER_TIM_CLK_ENABLE();/* 定时器初始化设置 */TIM_EncoderHandle.Instance = ENCODER_TIM;TIM_EncoderHandle.Init.Prescaler = ENCODER_TIM_PRESCALER;TIM_EncoderHandle.Init.CounterMode = TIM_COUNTERMODE_UP;TIM_EncoderHandle.Init.Period = ENCODER_TIM_PERIOD;TIM_EncoderHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;TIM_EncoderHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;/* 设置编码器倍频数 */Encoder_ConfigStructure.EncoderMode = ENCODER_MODE;/* 编码器接口通道1设置 */Encoder_ConfigStructure.IC1Polarity = ENCODER_IC1_POLARITY; //上升沿触发 有点不解,不是使用 编码器模式 3 在计数器在 TI1FP1 和 TI2FP2 的边沿计数,Encoder_ConfigStructure.IC1Selection = TIM_ICSELECTION_DIRECTTI;Encoder_ConfigStructure.IC1Prescaler = TIM_ICPSC_DIV1;Encoder_ConfigStructure.IC1Filter = 0;/* 编码器接口通道2设置 */Encoder_ConfigStructure.IC2Polarity = ENCODER_IC2_POLARITY;Encoder_ConfigStructure.IC2Selection = TIM_ICSELECTION_DIRECTTI;Encoder_ConfigStructure.IC2Prescaler = TIM_ICPSC_DIV1;Encoder_ConfigStructure.IC2Filter = 0;/* 初始化编码器接口 */HAL_TIM_Encoder_Init(&TIM_EncoderHandle, &Encoder_ConfigStructure);/* 清零计数器 */__HAL_TIM_SET_COUNTER(&TIM_EncoderHandle, 0);/* 清零中断标志位 */__HAL_TIM_CLEAR_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);/* 使能定时器的更新事件中断 */__HAL_TIM_ENABLE_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);/* 设置更新事件请求源为:计数器溢出 这个地方可能会忘记设置 */__HAL_TIM_URS_ENABLE(&TIM_EncoderHandle);/* 设置中断优先级 */HAL_NVIC_SetPriority(ENCODER_TIM_IRQn, 5, 1);/* 使能定时器中断 */HAL_NVIC_EnableIRQ(ENCODER_TIM_IRQn);/* 使能编码器接口 */HAL_TIM_Encoder_Start(&TIM_EncoderHandle, TIM_CHANNEL_ALL);
}/*** @brief 编码器接口初始化* @param 无* @retval 无*/
void Encoder_Init(void)
{Encoder_GPIO_Init(); /* 引脚初始化 */TIM_Encoder_Init(); /* 配置编码器接口 */
}/*** @brief 定时器更新事件回调函数* @param 无* @retval 无*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* 判断当前计数器计数方向 方向代表电机方向 */if(__HAL_TIM_IS_TIM_COUNTING_DOWN(&TIM_EncoderHandle))/* 下溢 */Encoder_Overflow_Count--;else/* 上溢 */Encoder_Overflow_Count++;
}/*********************************************END OF FILE**********************/
STM32编码器的学习笔记相关推荐
- STM32 Cube MX学习笔记——TOF 高速单线激光雷达 L10(usart)
STM32 Cube MX学习笔记--TOF 高速单线激光雷达 L10_串口中断通信 1. TOF 高速单线激光雷达 L10 2. STM32 Cube MX配置 3.代码配置 4.编译 烧录 显示 ...
- STM32 HAL库学习笔记1-HAL库简介
STM32 HAL库学习笔记1-HAL库简介 HAL库 SPL 库 和 HAL 库两者相互独立,互不兼容.几种库的比较如下 目前几种库对不同芯片的支持情况如下 ST 中文官网上有一篇<关于ST库 ...
- STM32 HAL库学习笔记4-SPI
STM32 HAL库学习笔记4-SPI 前言 一.SPI协议简介 SPI物理层 SPI协议层 1.基本通讯过程 2. 通讯的起始和停止信号 3. 数据有效性 4. CPOL/CPHA 及通讯模式 二. ...
- STM32中断回调函数定时器-STM32电控学习笔记06
STM32中断&定时器-STM32电控学习笔记06 day6:2022/9/24 [中断概述] 在 STM32 中,对信号的处理可以分为轮询方式和中断方式,轮询方式就是不断去访问一个信号的端口 ...
- 翻转电平函数实现LED闪烁-STM32电控学习笔记05
翻转电平函数实现LED闪烁-STM32电控学习笔记05 day5:2022/9/23 [函数介绍] 在前面帖子大致了解了一下HAL_GPIO_WritePin()函数和HAL_Delay()函数的用法 ...
- STM32 HAL库学习笔记2 HAL库介绍
STM32 HAL库学习笔记2 HAL库介绍 CMSIS标准 一.再次认识HAL库 HAL库设计思想 HAL库实现方式 以GPIO模块为例 GPIO外设数据类型 GPIO外设接口函数 二.使用HAL库 ...
- PWM控制LED亮度(2-呼吸灯)-STM32电控学习笔记10
PWM控制LED亮度(2-呼吸灯)-STM32电控学习笔记10 day10:2022/9/29 前面学了两三天的PWM了,PWM本身不难理解,至于为啥进度缓慢,还不是这时钟定时器分频值重装载啥的太难理 ...
- STM32上手-STWingSKIT_BC28学习笔记(一)环境搭建和LED灯点亮
嵌入式STM32上手学习笔记(一)LED灯点亮 STM32开发环境的搭建 1. 安装keil5 IDE 2. 下载STM32F1的支持包 3. 在Pack installer中找到F1支持包下载 4. ...
- 【单片机】STM32 最小板 学习笔记
目录&索引 前言 第一章 前期工作准备 软件获取 STM32 资料 相关下载 硬件准备 第二章 单片机系统介绍 第三章 库函数工程模板建立 第一步,下载固件库,文件分类 第二步,打开 mdk5 ...
最新文章
- Web目录全能扫描工具DirBuster
- 基于Kubernetes构建Docker集群管理详解
- zcmu2012(积性函数---因子和)
- html form int,is_int, is_numeric, is_float, and HTML form validation
- 微信支付中的刷卡支付和扫码支付测试
- 【无标题】自己动手写Docker系列 -- 6.3 手动配置容器网络(上)
- spring实现mqtt服务端_SpringBoot--实战开发--MQTT消息推送(六十)
- 存储容错:鱼与熊掌可以兼得
- JAVAEE智慧树第二次作业
- (三)IDEA部署Tomcat原理
- 计算机网络重置点命令,重置网络命令 重装系统如何重置网络命令
- 14届数独-真题标准数独-Day 10-20220125
- 字符移位 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 你能帮帮小Q吗? 输入描述: 输入数据有多组
- 机载计算机pdf,机载计算机系的故障诊断.pdf
- vue语法、跨域报错等问题集合
- 公司财务第一周作业(代理问题、财务管理)
- (深入.Net平台和C#编程)第五章.体检套餐管理项目.20170408
- 我27岁了,我现在慌的一逼
- AYIT-ACM实验室
- linux jdk1.8 64位下载永久地址,ubuntu,centos,java
热门文章
- endnote一打开就自动关闭_【EndNote文献管理】5分钟快速上手Endnote
- 无法解析 uafxcw.lib_吉利DMS系统一周热点问题解析
- 的garch预测_精品细读|基于隐含波动率、已实现波动率和GARCH模型波动率的预测...
- oel6mysql_OEL6.5_X86平台部署Oracle 11gR2 RAC并配置ACFS
- pandas拉长dataframe
- numeric转换varchar_将数据类型varchar转换为numeric时选择失败
- nodejs 本地php服务器,node.js创建本地服务器详解
- php5.6代码转换7.1,通过PHP5.6源代码在WINDOWS 7下进行编译生成(最详细步骤)
- PCIe的事务传输层的处理(TLP)
- php接收base64图片并保存