基于与STM32的加湿器之旋转编码器驱动

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;//定时器3
  htim3.Init.Prescaler = 0;//与分频系数,工作频率为72MHZ
  htim3.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对应IC1
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;//无分频器,每个事件检测一次
  sConfig.IC1Filter = 0;//无滤波器,以fDTS采样
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;//在下降沿计数
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;//TI2对应IC2
  sConfig.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;//AFIO
		AFIO->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 Configuration
    PB4     ------> TIM3_CH1
    PB5     ------> 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;//PB
	RCC->APB2ENR|=1<<0;//AFIO
	AFIO->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;//tim3
	RCC->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;//反向,捕获在下降沿
	//CH2
	TIM3->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.运行效果

在这里插入图片描述
  通过旋转编码器实现无极调速效果示例:
在这里插入图片描述

相关推荐

  1. [ESP32] 编码旋钮驱动

    2024-07-14 15:24:04       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 15:24:04       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 15:24:04       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 15:24:04       62 阅读
  4. Python语言-面向对象

    2024-07-14 15:24:04       72 阅读

热门阅读

  1. 如何利用Gunicorn的日志记录监控Web应用

    2024-07-14 15:24:04       21 阅读
  2. AMD CPU加 vega 显卡运行ollama本地大模型

    2024-07-14 15:24:04       23 阅读
  3. 面试经验总结

    2024-07-14 15:24:04       26 阅读
  4. 14. DDL-约束的管理

    2024-07-14 15:24:04       21 阅读
  5. Spring Cloud

    2024-07-14 15:24:04       26 阅读
  6. 微信小程序 2024年更新内容汇总

    2024-07-14 15:24:04       18 阅读
  7. vite.config.js文件配置指南

    2024-07-14 15:24:04       25 阅读