本文主要是介绍【STM32】通用定时器TIM(编码器接口),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发
目录
前言
编码器接口简介
正交编码器
编码器接口配置
初始化IO口
输入捕获配置
编码器接口初始化
编码器接口测速代码
Encoder.h
Encoder.c
main.c
前言
建议先阅读这篇博客,理解定时器输入捕获的配置和旋转编码器的使用
【STM32】通用定时器TIM(输入捕获)-CSDN博客
旋转编码器模块(软件消抖)-CSDN博客
通过外部中断的方式处理编码器信号固然可以,而且任意两个可配置外部中断的GPIO口都可以进行,但是,如果处理转得非常快的电机的旋转编码器,那就会因为频发触发中断, 占用太多CPU软件计算资源,导致其他任务无法正常执行,而且电机太快的话 ,还很有可能软件处理跟不上 ,导致丢步问题。这节我们来使用定时器的编码器接口处理信号。
编码器接口简介
Encoder Interface 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT计数器自增或自减,从而指示编码器的位置、旋转方向和旋转速度
每个高级定时器和通用定时器都有1个编码器接口
两个输入引脚借用了输入捕获的通道1和通道2
编码器框图
STM32F10xxx通用定时器为TIM2、TIM3、TIM4和TIM5
正交编码器
正交编码器正反转由自己定义
编码器正交波形动态展示:视频时间段为00:50至1:57旋转编码器|从零开始认识各种传感器_哔哩哔哩_bilibili
编码器接口配置
初始化IO口
GPIO的其它参数的理解可以阅读下方博客,这里不再赘述。
【STM32】GPIO和AFIO标准库使用框架_gpio afio-CSDN博客
查找引脚定义表,将通用定时器3的输入捕获通道1(PA6)和通道2(PA7)配置为上拉输入,由GPIO输入至定时器输入捕获单元
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
输入捕获配置
TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量TIM_ICStructInit(&TIM_ICInitStructure); //结构体初始化,若结构体没有完整赋值//则最好执行此函数,给结构体所有成员都赋一个默认值//避免结构体初值不确定的问题TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动TIM_ICInit(TIM3, &TIM_ICInitStructure); //将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择配置定时器通道2TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动TIM_ICInit(TIM3, &TIM_ICInitStructure); //将结构体变量交给 TIM_ICInit,配置TIM3的输入捕获通道
编码器接口初始化
编码器接口基本结构
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//高低电平极性不反转,这个和TIM_ICInit中配置一样,重复覆盖配置//配置编码器模式以及两个输入通道是否反相//注意此时参数的Rising和Falling已经不代表上升沿和下降沿了,而是代表是否反相
//此函数必须在输入捕获初始化之后进行,否则输入捕获的配置会覆盖此函数的部分配置
参数二:
TIM_EncoderMode | 描述 |
TIM_EncoderMode_TI1 | 使用 TIM 编码模式 1 |
TIM_EncoderMode_TI2 | 使用 TIM 编码模式 2 |
TIM_EncoderMode_TI12 | 使用 TIM 编码模式 3 |
TIM_EncoderMode:
计数方向
编码器接口接管CNT计数器的计数模式,时基单元配置的计数模式设置无效
编码器接口测速代码
每隔固定时间(可用定时器中断来操作),读取一次编码器接管的CNT计数器,获取增量值,速度=增量值/固定时间
这个速度是CNT计数器计数的速度,比如旋转编码器向右拧一个段落,(本节代码是四次边沿变化都计数,即编码器模式3),定时器捕获到四次计数边沿,编码器接口控制CNT计数器的四次计数都增加或减少。
Encoder.h
#ifndef __ENCODER_H
#define __ENCODER_Hvoid Encoder_Init(void);
int16_t Encoder_Get(void);#endif
Encoder.c
#include "stm32f10x.h" // Device headervoid Encoder_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数模式设置无效,编码器接口接管TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR,值要大,避免CNT计数器溢出TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC,不分频TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);TIM_ICInitTypeDef TIM_ICInitStructure;TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;TIM_ICInitStructure.TIM_ICFilter = 0xF;TIM_ICInit(TIM3, &TIM_ICInitStructure);TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;TIM_ICInitStructure.TIM_ICFilter = 0xF;TIM_ICInit(TIM3, &TIM_ICInitStructure);TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_Cmd(TIM3, ENABLE);
}/*** 函 数:获取编码器的增量值* 参 数:无* 返 回 值:自上此调用此函数后,编码器的增量值*/
int16_t Encoder_Get(void)
{/*使用Temp变量作为中继,目的是返回CNT后将其清零*/int16_t Temp;Temp = TIM_GetCounter(TIM3);TIM_SetCounter(TIM3, 0);return Temp;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"int16_t Speed;int main(void)
{OLED_Init();Encoder_Init();OLED_ShowString(1, 1, "Speed:");while (1){Speed = Encoder_Get();Delay_ms(1000);OLED_ShowSignedNum(1, 7, Speed, 5);}
}
这篇关于【STM32】通用定时器TIM(编码器接口)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!