EC11编码器编码使用

文章目录

  • 前要
  • 原理
    • 脉冲与定位
    • 功能
    • 硬件设计
  • 编程
    • 轮询模式
    • 定时器Encoder模式
  • 结束语

前要

关于EC11编码器的了解可以参考两篇文章,比较详细,在此就不多介绍了:

  • 一篇文章带你了解——EC11编码器(关于硬件、原理图、上下拉等都有讲)
  • 认识EC11旋转编码器&编写驱动程序

原理

脉冲与定位

  • 15脉冲/30定位:每拨动一格,两个电平都相继翻转,是半个脉冲;再拨动一格,电平再相继翻转,也是半个脉冲;两个半脉冲形成一个完整脉冲。静止状态下,两个电平相同,都为高或低
  • 20脉冲/20定位:每拨动一格,形成一个完整脉冲
    对应下图如下:
    在这里插入图片描述
    示波器抓取部分波形:
    在这里插入图片描述
      (note: 两个脉冲跳变的间隔约为几十ms)

功能

通过2个pin负责编码器的波形检测,顺时针与逆时针波形不同

硬件设计

IO外部上拉与无上拉
在这里插入图片描述

编程

硬件条件:

  • MCU:    stm32f407
  • 编码器类型: EC11-15脉冲/30定位
  • 连接:    IO外部无上拉,设置MCU GPIO的内部上拉

下面使用两种方法来对编码器进行计数和使用。

轮询模式

直接就上代码了,随意两个GPIO

//GPIO初始化
void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin : PB6 */GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/*Configure GPIO pin : PB7 */GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}//判断检测
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */// exit_init();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint32_t count = 0;uint32_t wait_t = 0;bool encoder_switch = 0;uint8_t encoder_a_pre = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6);// uint8_t encoder_b_pre = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);int32_t steps = 0;while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */uint32_t t = HAL_GetTick();uint8_t encoder_a = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6);uint8_t encoder_b = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);if (encoder_a_pre != encoder_a && !encoder_switch) {wait_t = HAL_GetTick();encoder_switch = true;}if (encoder_switch && ((t - wait_t) >= 2 )) {//a 0->1, b 0 Clockwise; b 1 AntiClockwiseif (encoder_a == 1) {if (encoder_b == 0) {steps++;} else {steps--;}}//a 1->0, b 1 Clockwise; b 0 AntiClockwise else {if (encoder_b == 1) {steps++;} else {steps--;}}encoder_switch = false;encoder_a_pre = encoder_a;printf("%d\r\n", steps);}}/* USER CODE END 3 */
}

注意点:编码器电平发生变化时可能存在噪声,类似按键一样需要增加延时防抖,并且考虑到在系统中少加入延时死等这些不友善的代码,所以代码中有如上处理。

定时器Encoder模式

stm32中定时器有自带Encoder的功能,所以可以借助定时器的这个特性来实现我们的需求。
直接撸代码,GPIO必须使用复用功能有定时器的pin。

//定时器及IO初始化
TIM_HandleTypeDef htim4;/* TIM4 init function */
void MX_TIM4_Init(void)
{/* USER CODE BEGIN TIM4_Init 0 *//* USER CODE END TIM4_Init 0 */TIM_Encoder_InitTypeDef sConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM4_Init 1 *//* USER CODE END TIM4_Init 1 */htim4.Instance = TIM4;htim4.Init.Prescaler = 0;htim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.Period = 65535;htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;sConfig.EncoderMode = TIM_ENCODERMODE_TI1;sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC1Prescaler = TIM_ICPSC_DIV1;sConfig.IC1Filter = 3;sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC2Prescaler = TIM_ICPSC_DIV1;sConfig.IC2Filter = 3;if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM4_Init 2 */HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);/* USER CODE END TIM4_Init 2 */}void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_encoderHandle->Instance==TIM4){/* USER CODE BEGIN TIM4_MspInit 0 *//* USER CODE END TIM4_MspInit 0 *//* TIM4 clock enable */__HAL_RCC_TIM4_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**TIM4 GPIO ConfigurationPB6     ------> TIM4_CH1PB7     ------> TIM4_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USER CODE BEGIN TIM4_MspInit 1 *//* USER CODE END TIM4_MspInit 1 */}
}//获取编码器变化
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */// exit_init();MX_TIM4_Init();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */int32_t Enc_Count_pre =  __HAL_TIM_GET_COUNTER(&htim4);while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */int32_t Enc_Count =  __HAL_TIM_GET_COUNTER(&htim4);if (Enc_Count != Enc_Count_pre) {printf("%d\r\n", Enc_Count);Enc_Count_pre = Enc_Count;}}/* USER CODE END 3 */
}

结束语

此两种方式已做测试,稳得一批,如果细节问题可沟通。


— 2021.10.22-21:45于广东深圳

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3踩坑指南

vue.config.ts不起作用 关于项目 项目使用的还是vue-cli搭建的,底层还是webpack,没有使用新的vite搭建。 踩坑1:vue.config.ts不起作用 我本着既然是vue3 ts的项目,那么为了规范,项目中所有的js文件都得替换成ts文…

idea的debug调试

目录 断点条件设置(condition) 断点表达式(evaluate expression) 断点回退(reset frame) 断点条件设置(condition) 条件断点,一般是满足我们设置的某个条件时,debug断点才会生效。这种条件断点设置,我们一般用在多重循环中。 这儿我们以li…

vue3脚手架搭建

一.安装 vue3.0 脚手架 如果之前安装了2.0的脚手架,要先卸载掉,输入: npm uninstall vue-cli -g 进行全局卸载 1.安装node.js(npm) node.js:简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是…

Windows 安装 Java

1. 安装 JDK 从 Oracle 的官网下载的 JDK,例如 JDK 21 双击下载得到的 msi 文件,开始安装 JDK 选择要安装的文件路径(我一般都默认): 等待安装: 安装完成: 2. 验证是否安装成功 2.1. 打开 cmd…

antd vue 组件 使用下拉框的层级来显示后面的输入框

效果图&#xff1a; 代码&#xff1a; HTML: <dir><a-row><a-col :span"4"><a-form-model-item label"审批层级" ><a-selectplaceholder"请选择审批层级"v-model"form.PlatformPurchaseApproveLevel"cha…

Linux笔记之diff和vimdiff

Linux笔记之diff和vimdiff code review! 文章目录 Linux笔记之diff和vimdiff一.diff1.1.使用diff比较文件夹1.2.使用diff比较文件1.4.colordiff——带颜色输出差异 二.vimdiff2.1.vimdiff颜色差异2.2.vimfiff调整栏宽2.3.修改颜色变谈&#xff0c;使代码可以看清楚2.4.vimdif…

FreeRTOS深入教程(任务的引入及栈的作用)

文章目录 前言一、任务的引入二、深入理解C语言函数的调用1.ARM架构2.基础汇编指令3.函数运行流程分析 三.保存现场的几种情况1.函数调用2.中断处理3.任务切换 总结 前言 本篇文章开始带大家深入学习FreeRTOS&#xff0c;带大家学习什么是任务&#xff0c;并且深入学习栈的作用…

AWS SAA-C03考试知识点整理

S3&#xff1a; 不用于数据库功能 分类&#xff1a; S3 Standard &#xff1a;以便频繁访问 S3 Standard-IA 或 S3 One Zone-IA &#xff1a; 不经常访问的数据 Glacier&#xff1a; 最低的成本归档数据 S3 Intelligent-Tiering智能分层 &#xff1a;存储具有不断变化或未知访问…

使用按钮从 SAP 系统内打开 Excel 文件

了解如何通过 SAP 屏幕上创建的按钮打开所需的 Excel 文件。为了演示这一点&#xff0c;将指导您完成以下步骤。 使用 del 命令删除 SAP 上不必要的元素添加一个按钮&#xff0c;单击后打开弹出窗口创建一个函数来选择 excel 文件创建打开所需 excel 文件的函数 定制 登录 S…

231022|redis_demo

安装 https://github.com/tporadowski/redis https://github.com/redis/redis-py/ 解压后要先配置redis.windows.conf文件&#xff0c;里面有本地端口和密码设置 默认host:127.0.0.1 port:6379 打开命令行到redis文件夹下&#xff0c;redis-server.exe redis.windows.conf输入即…

C语言程序环境和预处理

大家好&#xff0c;我们今天来分享C语言程序环境和预处理方面的内容。 C语言程序的运行阶段 C语言程序的运行是把我们的test.c文件&#xff08;也就是我们通常所说的文本信息里面的代码&#xff09;通过翻译环境转化为test.exe文件&#xff08;这个就是可执行程序&#xff0c;但…

【ONE·C++ || 智能指针 特殊类的设计】

总言 主要介绍智能指针&#xff08;auto_ptr、unique_ptr、shared_ptr、weak_ptr&#xff09;和特殊类的设计&#xff08;单例模式&#xff09;。 文章目录 总言1、为什么需要智能指针&#xff1f;&#xff08;内存泄漏&#xff09;1.1、什么是内存泄漏1.2、内存泄漏的分类和常…

设计模式-单例模式 (Singleton)

单例模式 &#xff08;Singleton&#xff09; 单例模式是一种创建型设计模式&#xff0c;它确保类只有一个实例&#xff0c;并提供了一种访问该实例的全局方法。这种模式有助于确保系统中的某些组件只有一个实例&#xff0c;并提供了一种方便的方法来访问该实例。 1、单例类只…

【AOA-VMD-LSTM分类故障诊断】基于阿基米德算法AOA优化变分模态分解VMD的长短期记忆网络LSTM分类算法(Matlab代码)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

7.20 SpringBoot项目实战【图书详情-学生端】:图书信息 + 评论列表 + 是否收藏

文章目录 前言一、接口规划二、编写服务层三、编写数据访问层四、编写控制器五、PostMan测试1. getBook 根据id获取图书2. getBookCommentList 根据id获取图书详情 - 评论列表3. getFavoriteId 获取学生收藏了某图书的收藏id 最后 前言 学生的【借阅申请】审核通过以后&#x…

Node学习笔记之包管理工具

一、概念介绍 1.1 包是什么 『包』英文单词是package &#xff0c;代表了一组特定功能的源码集合 1.2 包管理工具 管理『包』的应用软件&#xff0c;可以对「包」进行 下载安装 &#xff0c; 更新 &#xff0c; 删除 &#xff0c; 上传 等操作 借助包管理工具&#xff0c;可…

C++前缀和算法:生成数组原理、源码及测试用例

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 动态规划&#xff0c;日后完成。 题目 给定三个整数 n、m 和 k 。考虑使用下图描述的算法找出正整数数组中最大的元素。 请你构建一个具有以下属性的数组 arr &#…

Go并发编程之一

一、前言 新年学新语言Go系列文章已经完结&#xff0c;用了最简单的例子去了解Go基础语法&#xff0c;但Go最牛B的是它对并发的友好支持&#xff0c;每一门语言都有它自己独特的优势&#xff0c;如Java适合大型工程化项目&#xff0c;Python适合做数据分析及运维脚本&#xff0…

AD9371 官方例程HDL详解之JESD204B TX_CLK生成 (一)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 参考资料&#xff1a; UltraScale Architecture GTH Transceive…

Android---OkHttp详解

OkHttp 是一套处理 HTTP 网络请求的依赖库&#xff0c;由 Square 公司设计研发并开源&#xff0c;目前可以在 Java 和 Kotlin 中使用。对于 Android App&#xff0c;OkHttp 现在几乎已经占据了所有的网络请求操作。RetroFit OkHttp 实现网络请求似乎成了一种标配。 因此&…