1.简介
旋转编码器,也被称为轴编码器或脉冲编码器(SPC),是一种将旋转的机械位移量转换为电气信号的传感器,其信号可用于检测位置、速度等。
2.工作原理
旋转编码器的工作原理主要基于光电转换或磁电转换。以光电式旋转编码器为例,其内部有一个中心有轴的光电码盘,码盘上有环形通、暗的刻线。当码盘随轴旋转时,光电发射和接收器件会读取这些刻线,并产生相应的电信号。这些电信号经过处理后,可以转换成数字量输出,用于表示旋转的位移、速度等。
测量转速:旋转编码器可以测量旋转速度,并将转速转换成电脉冲信号,以供控制系统使用。
方向检测:双路输出的旋转编码器可以输出两组A/B相位差90度的脉冲,通过这两组脉冲不仅可以测量转速,还可以判断旋转的方向。
3.EC11旋转编码器
EC11旋转编码器是一种将旋转的机械位移转换为电信号的装置,其输出信号可用于各种控制系统中,如频率、音量、速度、温度、电压、菜单选择、光线强弱等参数的控制。它广泛用于车载DVD、车载导航、汽车影音系统,以及家用小家电产品的旋转开关上。此外,EC11编码器还应用于汽车电子、多媒体音响、仪器仪表、家用电器、智能家居等领域。
EC11编码器通常具有多个引脚,包括用于检测旋转的A、B引脚,以及作为公共端的C引脚。此外,还可能有用于轻触按键的SW引脚(在某些型号中)。A、B引脚用于输出相位差为90度的脉冲信号,通过检测这两个信号的相位关系可以确定旋转的方向。C引脚通常接地,作为A、B信号的参考地。硬件实物如图所示:
硬件接口电路如下图所示,采用5V供电,C为GND,作为公共端引脚,A、B引脚用于旋转检测,二者相位相差90°。
4.定时器编码器
STM32定时器编码器是STM32微控制器中用于与旋转编码器接口的一种功能,它通过定时器的输入引脚直接连接到旋转编码器,利用定时器的计数器来跟踪编码器的相位变化,从而确定位置、速度和方向。
在STM32中,编码器接口(Encoder Interface)允许通过连接到定时器的输入引脚(通常为输入捕获的通道1和通道2,即CH1和CH2),来直接与旋转编码器进行接口。这一功能使得STM32能够利用定时器的计数器(CNT)来跟踪编码器的相位变化,进而实现位置、速度和方向的测量。
选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011。
通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以对输入滤波器编程。
两个输入TI1和TI2被用来作为增量编码器的接口。假定计数器已经启动(TIMx_CR1寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。TI1FP1和TI2FP2是TI1和TI2在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则TI1FP1=TI1,TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号的跳变顺序,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应的设置。不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数。在任一输入端(TI1或者TI2)的跳变都会重新计算DIR位。
编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计数)。所以在开始计数之前必须配置TIMx_ARR;同样,捕获器、比较器、预分频器、触发输出特性等仍工作如常。
在这个模式下,计数器依照增量编码器的速度和方向被自动的修改,因此计数器的内容始终指示着编码器的位置。计数方向与相连的传感器旋转的方向对应。下表列出了所有可能的组合,假设TI1和TI2不同时变换。
采用定时器编码器模式接口实现计数,运行效果如下:
5.HAL库代码生成
5.1定时器编码器软件配置
1.根据硬件原理图接口,选择对应定时器通道,本次编码器AB相引脚为PB4和PB5,因此选择TIM3_CH1和TIM3_CH2作为检测通道。
2.配置定时器计数周期和通道参数。
本次使用编码器主要是实现对加湿器雾化片的无极调速,雾化片工作频率为110KHZ,因此选择的工作频率为72MHZ,计数周期为654。
5.2代码生成
TIM3初始化配置:
void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *//* USER CODE END TIM3_Init 0 */TIM_Encoder_InitTypeDef sConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance = TIM3;//定时器3htim3.Init.Prescaler = 0;//与分频系数,工作频率为72MHZhtim3.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数模式htim3.Init.Period = 654;//计数周期htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//无时钟分频因子htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;//自动重装载预装载允许位sConfig.EncoderMode = TIM_ENCODERMODE_TI12;//编码器在TI1和TI2上均计数sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;//在下降沿计数sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;//TI1对应IC1sConfig.IC1Prescaler = TIM_ICPSC_DIV1;//无分频器,每个事件检测一次sConfig.IC1Filter = 0;//无滤波器,以fDTS采样sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;//在下降沿计数sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;//TI2对应IC2sConfig.IC2Prescaler = TIM_ICPSC_DIV1;//无分频器,每个事件检测一次sConfig.IC2Filter = 0;//无滤波器,以fDTS采样if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)//编码器初始化{Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 *//* USER CODE END TIM3_Init 2 */}
TIM3通道引脚配置:
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_encoderHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspInit 0 */RCC->APB2ENR|=1<<0;//AFIOAFIO->MAPR&=~(0x7<<24);AFIO->MAPR|=0x1<<24;//设置PB4作为普通IO使用/* USER CODE END TIM3_MspInit 0 *//* TIM3 clock enable */__HAL_RCC_TIM3_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**TIM3 GPIO ConfigurationPB4 ------> TIM3_CH1PB5 ------> TIM3_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);__HAL_AFIO_REMAP_TIM3_PARTIAL();/* TIM3 interrupt Init */HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM3_IRQn);/* USER CODE BEGIN TIM3_MspInit 1 */TIM3->CCMR1|=1<<0;//CH1配置为输入模式TIM3->CCMR1|=1<<8;//CH2配置为输入模式TIM3->CCER|=1<<0;//CH1捕获使能TIM3->CCER|=1<<4;//CH2捕获使能TIM3->DIER|=1<<1;//CH1中断TIM3->DIER|=1<<2;//CH2中断TIM3->CR1|=1<<0;//使能定时器/* USER CODE END TIM3_MspInit 1 */}
}
5.3 寄存器方式实现定时器编码器配置示例
/********定时器编码器配置*********
**硬件接口:
开启部分重映射
**PB4 -->TIM3_CH1
**PB5 -->TIM3_CH2
**配置模式:编码器模式
**
**********************************/
void TIM3_CodeMode(u16 psc,u16 arr)
{RCC->APB2ENR|=1<<3;//PBRCC->APB2ENR|=1<<0;//AFIOAFIO->MAPR&=~(0x7<<24);AFIO->MAPR|=0x1<<24;AFIO->MAPR&=~(0x3<<10);AFIO->MAPR|=0x2<<10;//开启部分重映射GPIOB->CRL&=0xFF00FFFF;GPIOB->CRL|=0x00880000;RCC->APB1ENR|=1<<1;//tim3RCC->APB1RSTR|=1<<1;//复位时钟RCC->APB1RSTR&=~(1<<1);//取消复位//计数功能配置TIM3->CR1|=1<<7;TIM3->PSC=psc-1;//预分频器TIM3->ARR=arr;//重装载值TIM3->CNT=50;//编码器模式配置TIM3->SMCR|=1<<0;//根据TI1电平计数TIM3->CCMR1|=1<<0;//配置为输入模式TIM3->CCMR1|=1<<2;//每2个事件捕获一次TIM3->CCMR1|=0xf<<4;//输入滤波器TIM3->CCER|=1<<1;//反向,捕获在下降沿//CH2TIM3->CCMR1|=1<<8;//CH2配置为输入TIM3->CCMR1|=1<<10;//每2个事件捕获一次TIM3->CCMR1|=0xf<<12;//输入滤波器TIM3->CCER|=1<<5;//反向,捕获在下降沿TIM3->DIER|=1<<1;//CH1中断TIM3->DIER|=1<<2;//CH2中断//STM32_NVIC_SetPriority(TIM3_IRQn,0,0);//设置优先级HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM3_IRQn);TIM3->CCER|=1<<0;//CH1捕获使能TIM3->CCER|=1<<4;//CH2捕获使能TIM3->CR1|=1<<0;//使能定时器}
5.4 定时器编码器中断处理
void TIM3_IRQHandler(void)
{/* USER CODE BEGIN TIM3_IRQn 0 *//* USER CODE END TIM3_IRQn 0 */HAL_TIM_IRQHandler(&htim3);/* USER CODE BEGIN TIM3_IRQn 1 */u16 cnt=TIM3->CNT;u8 dir=(TIM3->CR1&(1<<4));printf("cnt=%d,%d\r\n",cnt,dir);/* USER CODE END TIM3_IRQn 1 */
}
6.运行效果
通过旋转编码器实现无极调速效果示例: