基于与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.运行效果

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/797112.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电子签章 签到 互动 打卡 创意印章 支持小程序 H5 App

电子签章 签到 互动 打卡 创意印章 支持小程序 H5 App 定制化

华为防火墙nat和智能选路配置

要求&#xff1a; 7&#xff0c;办公区设备可以通过电信链路和移动链路上网(多对多的NAT&#xff0c;并且需要保留一个公网IP不能用来转换) 8&#xff0c;分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的http服务器 9&#xff0c;多出口环境基于带宽比例进行选路&…

k8s集群新增节点

目前集群状态 如K8S 集群搭建中规划的集群一样 Masternode01node02IP192.168.100.100192.168.100.101192.168.100.102OSCent OS 7.9Cent OS 7.9Cent OS 7.9 目前打算新增节点node03 Masternode01node02node03IP192.168.100.100192.168.100.101192.168.100.102192.168.100.1…

NLP之词的重要性

文章目录 何为重要词TF*IDFTF*IDF其他版本TFIDF 算法特点TF*IDF的优势TF*IDF劣势 TF*IDF的应用搜索引擎文本摘要文本相似度计算 上一篇文章介绍了新词的发现&#xff0c;用内部凝固度和左右熵来发现新词。这时候机器对一篇文章有了对词的一定理解&#xff0c;这时我们让机器上升…

了解Maven

一.环境搭建 如果使用的是社区版 版本要求为&#xff1a;2021.1-2022.1.4 如果使用的是idea专业版就无需版本要求,专业版下载私信我&#xff0c;免费教你下载 二&#xff0c;Maven 什么是Maven&#xff0c;也就是一个项目管理工具&#xff0c;用来基于pom的概念&#xff0c…

k8s(五)---名称空间

五、名称空间 名称空间是k8s划分不同工作空间的逻辑单位,是k8s资源逻辑隔离的机&#xff0c;。可以给不同的租户&#xff0c;不同的环境、不同的项目创建对应的命名空间。 1、查看名称空间 kubectl get ns kubectl get namespaces 此处展示了四个命名空间 2、管理名称空间 1…

【数智化案例展】沃太能源——MES系统建设引领智能制造新篇章

‍ 联想集团案例 本项目案例由联想集团投递并参与数据猿与上海大数据联盟联合推出的《2024中国数智化转型升级创新服务企业》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 沃太能源股份有限公司&#xff0c;一家在储能产品及智慧能源管理方案领域享有盛誉的…

一 GD32 MCU 开发环境搭建

GD32 系列为通用型 MCU &#xff0c;所以开发环境也可以使用通用型的 IDE &#xff0c;目前使用较多的是 KEIL、 IAR 、 GCC 和 Embedded Builder &#xff0c;客户可以根据个人喜好来选择相应的开发环境。 目录 1、使用 Keil 开发 GD32 目前市面通用的MDK for ARM版本有Kei…

[笔记] SEW的振动分析工具DUV40A

1.便携式振动分析仪 DUV40A 文档编号&#xff1a;26871998/EN SEW是一家国际化的大型的机械设备供应商。产品线涵盖电机&#xff0c;减速机&#xff0c;变频器等全系列动力设备。DUV40A是他自己设计的一款振动分析工具。 我们先看一下它的软硬件参数&#xff1a; 内置两路传…

LiteOS增加执行自定义源码

开发过程注意事项&#xff1a; 源码工程路径不能太长 源码工程路径不能有中文 一定要关闭360等杀毒软件&#xff0c;否则编译的打包阶段会出错 增加自定义源码的步骤: 1.创建源码目录 2. 创建源文件 新建myhello目录后&#xff0c;再此目录下再新建源文件myhello_demo.c 3. 编…

Java常用排序算法

冒泡排序&#xff08;Bubble Sort&#xff09; arr[0] 与 arr[1]比较&#xff0c;如果前面元素大就交换&#xff0c;如果后边元素大就不交换。然后依次arr[1]与arr[2]比较&#xff0c;第一轮将最大值排到最后一位。 第二轮arr.length-1个元素进行比较&#xff0c;将第二大元素…

视频播放器的问题

<template><div class"app-container"><el-form :model"queryParam" ref"queryForm" :inline"true"><el-form-item label"题目ID&#xff1a;"><el-input v-model"queryParam.id" cle…

.NET MAUI开源架构_1.学习资源分享

最近需要开发Android的App&#xff0c;想预研下使用.NET开源架构.NET MAUI来开发App程序。因此网上搜索了下相关资料&#xff0c;现在把我查询的结果记录下&#xff0c;方便后面学习。 1.官方文档 1.1MAUI官方学习网站 .NET Multi-Platform App UI 文档 - .NET MAUI | Micro…

Rust 测试的组织结构

测试的组织结构 本章一开始就提到&#xff0c;测试是一个复杂的概念&#xff0c;而且不同的开发者也采用不同的技术和组织。Rust 社区倾向于根据测试的两个主要分类来考虑问题&#xff1a;单元测试&#xff08;unit tests&#xff09;与 集成测试&#xff08;integration test…

论文阅读 - Intriguing properties of neural networks

Intriguing properties of neural networks 经典论文、对抗样本领域的开山之作 发布时间&#xff1a;2014 论文链接: https://arxiv.org/pdf/1312.6199.pdf 作者&#xff1a;Christian Szegedy, Wojciech Zaremba, Ilya Sutskever, Joan Bruna, Dumitru Erhan, Ian Goodfellow,…

MongoDB教程(四):mongoDB索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

【RHCE】综合实验0710综合实验

题目&#xff1a; 主服务器192.168.244.130 防火墙允许服务的放行&#xff1a; selinux放行 [rootlocalhost ~]# ll -Z /nfs/rhce 总用量 4 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 8 7月 10 16:52 index.html -rw-r--r--. 1 nobody nobody system_…

【深度学习 pytorch】迁移学习 (迁移ResNet18)

李宏毅深度学习笔记 《深度学习原理Pytorch实战》 https://blog.csdn.net/peter6768/article/details/135712687 迁移学习 实际应用中很多任务的数据的标注成本很高&#xff0c;无法获得充足的训练数据&#xff0c;这种情况可以使用迁移学习(transfer learning)。假设A、B是两…

Dify中高质量索引模式时,通过线程池处理chunk过程

本文主要介绍了Dify中高质量索引模式时,如何通过线程池执行器来处理chunk的过程。源码位置:dify\api\core\indexing_runner.py\IndexingRunner._load。核心思想:假设一个数据集中有一个文档,该文档可以拆分为12个段(segment)。如果chunk_size=10,那么分为2批提交给线程池…

C语言——流程控制:if...else、switch...case

控制类语句&#xff1a; 逻辑运算符&#xff1a; 选择语句&#xff1a; if...else&#xff1a; if&#xff08;&#xff09;括号内的内容终究会被转换成0,1&#xff0c;满足的话即为1&#xff0c;不满足的话为0。因此要注意&#xff0c;&#xff08;&#xff09;括号内因为条件…