1、编码器接口 ( EnCoder Interface )
- STM32编码器接口可以接收正交编码器信号,根据正交信号脉冲,自动控制计数器CNT的自增和自减,指示编码器的位置,旋转方向和旋转速度;
- 高级定时器和通用定时器有1个编码器接口,输入引脚借用了输入捕获的通道1和通道2;
- 软件资源和硬件资源:触发中断消耗软件资源;输出比较、输入捕获、编码器接口属于硬件资源;
2、正交编码器(正交信号抗噪声)
- 正交编码器(也称为增量编码器)是一种机电传感器,通过两个正交的输出信号(通常称为A相和B相)来提供位置信息。
- 这两个信号相位差为90度,通过监控脉冲的数目和两个信号的相对相位,可以跟踪旋转位置、旋转方向和速度

3、编码器接口的设计逻辑
A相和B相的边沿作为计数器的计数时钟,出现边沿信号时,就出现自增或者自减;
A相呈上升沿/下降沿时,判断B相的高低电平,如果B相状态上表,则自增;如果B相状态下表,则自减;
4、编码器接口的电路

- CH1 ----> 输入滤波器----> 边沿检测器----> 极性选择(表示高低电平的极性)----> TI1FP1 ---->编码器接口 ---->时基单元
- CH2 ----> 输入滤波器----> 边沿检测器----> 极性选择(表示高低电平的极性)----> TI2FP2 ---->编码器接口 ---->时基单元

工作模式

编码器接口测速实验

编码器模块 EnCoder.c
#include "stm32f10x.h"
void EnCoder_Init(void)
{
/* 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 配置GPIO */
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_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1; //预分频值
TIM_TimeBaseInitStruct.TIM_Period = 65536 -1; // 自动重装值
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
/* 配置输入捕获单元 */
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICStructInit(&TIM_ICInitStruct);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &TIM_ICInitStruct);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
TIM_ICInitStruct.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &TIM_ICInitStruct);
/* 配置编码器接口模式,输入捕获通道TI1和TI2都计数 */
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Rising);
/* 启用定时器 */
TIM_Cmd(TIM3, ENABLE);
}
int16_t EnCoder_Get(void)
{
int16_t Tmp = 0;
Tmp = TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0);
return Tmp;
}
定时器模块 Timer.c
#include "stm32f10x.h" // Device header
extern uint16_t uiNum;
void Timer_Init(void)
{
/* RCC开始TIM2定时器的时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
* RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
* RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
* RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4,
* RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
* RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
* RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
*/
/* 选择时基单元的时钟 */
TIM_InternalClockConfig(TIM2);
/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1; //预分频值
TIM_TimeBaseInitStruct.TIM_Period = 1000 -1; // 自动重装值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
/* 使能更新中断至NVIC */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // TIM_IT_Update 表示更新中断
/* 配置NVIC */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
/* 启动定时器 */
TIM_Cmd(TIM2, ENABLE);
}
void TIM2_IRQHandler(void)
{
if( SET == TIM_GetITStatus(TIM2, TIM_IT_Update) )
{
uiNum ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
主函数模块 main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "EnCoder.h"
uint16_t uiNum = 0;
int main(void)
{
OLED_Init();
Timer_Init();
EnCoder_Init();
while(1)
{
OLED_ShowSignedNum(1, 1, EnCoder_Get(), 4);
Delay_ms(1000);
}
}
编码器接口测速
浙公网安备 33010602011771号