【STM32入门】4.3旋转编码器计次

1.旋转编码器原理

旋转编码器旋转的时候A、B两个引脚会产生相位差90度的方波,这个地方要尤其注意:

1.方波的相位差决定了中断触发方式,是上升沿还是下降沿。

2.方波的相位差决定了判断逻辑。

逻辑:

1.A引脚的上升沿对应B引脚的低电平时,编码器是正转

2.B引脚的上升沿对应A引脚的低电平时,编码器是反转

因此,中断的触发方式我们选择上升沿触发,设置两个中断,一个由外部输入A触发,另一个由外部输入B触发,一旦监测到上升沿就进入中断程序,判断两个引脚的高低电平,从而判断出编码器是在正转还是反转。

2.新建工程(略)

3.硬件驱动

Encoder.c中首先要时钟使能和配置中断,使用中断的配置顺序见前面博文。主要是:

1.配置RCC时钟;

2.配置GPIO,端口配置为输入模式;

3.配置AFIO,选择GPIO链接到EXTI;

4.配置EXTI,选择边沿触发方式和触发的响应方式;

5.配置NVIC,配置中断优先级。

3.1配置RCC时钟

使能GPIOB和AFIO的时钟,因为编码器是接在了GPIOB0/1上,所以必须使能这一片区域。

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟,因为传感器引脚接在了GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//AFIO时钟开启

3.2配置GPIO

跟往常一样定义GPIO的结构体完成配置,GPIO_Mode选择上拉输入,使能的管脚是GPIOB_0和GPIOB_1。

    GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//EXTI输入,推荐配置是浮空,上拉或下拉GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;GPIO_Init(GPIOB, &GPIO_InitStructure);

3.3配置AFIO

其实就是AFIO中断线的定义,函数第一个参数是GPIO片区,我们用的是GPIOB,第二个参数是本片区的哪个管脚链接到AFIO,是0号和1号。(两个基佬???)

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//参见函数定义,实际上是用来选择GPIO_pin作为中断线,第一个参数是GPIO分区,GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

3.4配置EXTI

EXTI的配置也是采用结构体形式,首先是中断线,本次用了两个中断,分别为EXTI_Line0和EXTI_Line1。触发方式选择上升沿:EXTI_Trigger_Rsing。这个很重要

    EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1;//配置中断线EXTI_InitStructure.EXTI_LineCmd=ENABLE;//开启或关闭中断EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//定义中断模式EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//触发中断方式,选择上升沿触发EXTI_Init(&EXTI_InitStructure);

3.5.配置NVIC

因为由两个中断,因此NVIC配置两次,分组2方式,结构体只用定义一次,第二次配置NVIC的时候可以直接引用参数结构体。第一个中断的优先级是1,第二个是2.我现在还没整明白这一块。

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先集分组定义//调用NVIC初始化函数NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//指定NVIC的通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;//指定NVIC的通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitStructure);

3.6定义中断函数

分别定义两个中断函数EXTI0_IRQHandler和EXTI1_IRQHandler。基本逻辑跟第一小节讲的一样,先判断第一个中断是不是被触发了,即A管脚是否是上升沿。A管脚接的是GPIOB_0,对应的中断0.然后判断B管脚是不是低电平。如果是那就是在正转,因此Encoder_Count计数加一,否则就减去1.这里注意,教程里老师讲错了。

void EXTI0_IRQHandler(void)//正转:A的上升沿对应B的低电平;反转:B的上升沿对应A的低电平。
{if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断编码器A是否为高电平,中断是否触发{if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) ==0)//判断编码器B是否为低电平{Encoder_Count++;}EXTI_ClearITPendingBit(EXTI_Line0);//如果是,则清空标志位}}
void EXTI1_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断编码器B是否为高电平,中断是否触发{if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) ==0)//判断编码器A是否为低电平{Encoder_Count--;}EXTI_ClearITPendingBit(EXTI_Line1);//如果是,则清空标志位}}

3.7完整的Encoder.c

#include "stm32f10x.h"                  // Device headerint16_t Encoder_Count;//定义带符号变量,因为涉及正转和反转
void Encoder_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟,因为传感器引脚接在了GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//AFIO时钟开启//EXTI和NVIC的时钟默认打开,不需要配置;NVIC是内核外设,不用开时钟GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//EXTI输入,推荐配置是浮空,上拉或下拉GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;GPIO_Init(GPIOB, &GPIO_InitStructure);//AFIO外设并没有分配专门的库函数,它的库函数跟GPIO在同一个文件中,GPIO.h中第350行开始就是AFIO的库函数了GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//参见函数定义,实际上是用来选择GPIO_pin作为中断线,第一个参数是GPIO分区,GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//第二是引脚号,//第四步,配置EXTIEXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1;//配置中断线EXTI_InitStructure.EXTI_LineCmd=ENABLE;//开启或关闭中断EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//定义中断模式EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//触发中断方式,选择上升沿触发EXTI_Init(&EXTI_InitStructure);//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先集分组定义//调用NVIC初始化函数NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//指定NVIC的通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;//指定NVIC的通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitStructure);}
int16_t Encoder_Get(void)
{int16_t Temp;Temp = Encoder_Count;Encoder_Count=0;return Temp;
}
void EXTI0_IRQHandler(void)//正转:A的上升沿对应B的低电平;反转:B的上升沿对应A的低电平。
{if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断编码器A是否为高电平,中断是否触发{if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) ==0)//判断编码器B是否为低电平{Encoder_Count++;}EXTI_ClearITPendingBit(EXTI_Line0);//如果是,则清空标志位}}
void EXTI1_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断编码器B是否为高电平,中断是否触发{if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) ==0)//判断编码器A是否为低电平{Encoder_Count--;}EXTI_ClearITPendingBit(EXTI_Line1);//如果是,则清空标志位}}

4.主函数

首先定义一个有符号的整型变量Num。在死循环中,调用Encoder_Get()函数,这个函数的具体定义在完整的中断函数中,作用是返回当前的计数值。

在死循环中的操作就是:新的旋转计数=已有的计数+Encoder_Get(),而这个Encoder_Get()的返回值,如果是正转就是+1,反转就是-1.

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"int16_t Num;int main(void)
{OLED_Init();Encoder_Init();OLED_ShowString(1,1, "Num:");while(1){Num+= Encoder_Get();OLED_ShowSignedNum(1,5,Num,5);}
}

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

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

相关文章

【转载】【Unity】WebSocket通信

1 前言 Unity客户端常用的与服务器通信的方式有socket、http、webSocket。本文主要实现一个简单的WebSocket通信案例,包含客户端、服务器,实现了两端的通信以及客户端向服务器发送关闭连接请求的功能。实现上没有使用Unity相关插件,使用的就是…

【QT】解决QTableView鼠标点击合并单元格高亮显示问题

问题 正常显示 鼠标单击时只会选中当前行 异常显示 解决方案 在操作之前清除单元格合并,然后再合并单元格; 合并单元格是好的,说明合并没有问题,所以最简单的办法就是将单元格的状态恢复到初始的时候,在进行操作&…

maven构建单个模块,遇到错误:Could not find the selected project in the reactor

mvn install -pl modulename -am -pl 参数用于指定要构建的子模块,可以通过指定子模块的 artifactId 或者模块路径来指定。在命令中使用 -pl my-submodule 表示只构建名为 my-submodule 的子模块。 -am 参数用于自动构建依赖的模块。如果当前构建的模块依赖于其他…

bottom-up-attention-vqa-master 成功复现!!!

代码地址 1、create_dictionary.py 建立词典和使用预训练的glove向量 (1)create_dictionary() 遍历每个question文件取出所关注的question部分,qs 遍历qs,对每个问题的文本内容进行分词,并将分词结果添加到字典中&…

LabVIEW开发自动驾驶的双目测距系统

LabVIEW开发自动驾驶的双目测距系统 随着车辆驾驶技术的不断发展,自动驾驶技术正日益成为现实。从L2级别的辅助驾驶技术到L3级别的受条件约束的自动驾驶技术,车辆安全性和智能化水平正在不断提升。在这个过程中,车辆主动安全预警系统发挥着关…

Ubuntu基础操作和使用指南

Ubuntu基础操作和使用指南 Ubuntu是一款流行的开源操作系统,广泛应用于个人电脑、服务器和云计算环境。本文将介绍Ubuntu的基础操作和使用,帮助读者更好地使用这个操作系统。 1. 安装和设置 首先,你需要安装Ubuntu。你可以从Ubuntu官方网站…

LDAP的介绍以及JAVA使用LdapTemplate来进行AD域的操作

一、概念介绍 1.1 LDAP LDAP(轻型目录访问协议)是一种用于访问和维护分布式目录服务的开放标准协议。LDAP最初是从X.500标准中派生出来的,但相比于X.500,LDAP更加简化和灵活。LDAP协议定义了客户端和服务器之间进行通信的规范&a…

WebMvcConfigurer接口详解及使用方式(Spring-WebMvc)

简介 如下图所示WebMvcConfigurer是spring-webmvc jar包下的一个接口,spring-webmvc jar包又来源于spring-boot-starter-web,所以要使用WebMvcConfigurer要引入spring-boot-starter-web依赖。WebMvcConfigurer接口提供了常用的web应用拦截方法。通过实现…

Lazada物流禁运规则是什么?Lazada物流禁运商品有哪些?——站斧浏览器

Lazada物流禁运规则 Lazada平台对物流禁运商品的规则主要有以下几个方面: 1.卖家在上传商品时需要填写正确的商品信息,包括商品名称、描述、图片等。如果卖家填写不准确或者存在虚假信息,将会导致物流禁运商品的误判。 2.卖家需要遵守平台…

HQX System Performance Troubleshooting Overview

Ensure your gvm config contain below ftrace configs: #导出config配置 adb root adb shell proc/config.gz#确认下列ftrace config是否开启,如果没有开启在代码中进行配置 CONFIG_TASKS_TRACE_RCUy CONFIG_TRACEPOINTSy CONFIG_STACKTRACE_SUPPORTy CONFIG_TRAC…

H5网页流媒体播放器EasyPlayer播放H.265录像时,无法倍速回放是什么原因?

流媒体播放器EasyPlayer是我们流媒体组件系列中关注度较高的产品,经过多年的发展和迭代,目前已经有多个应用版本,包括RTSP版、RTMP版、Pro版,以及js版,其中js版本作为网页播放器,受到了用户的广泛使用。在功…

Python自适应调整Excel的列宽度

使用python调整列宽度的逻辑需要自己写,这里是参考参考文章中的内容,使用openpyxl打开文件后,将列宽度根据列的内容进行指定,使用max(列的内容宽度 2) * 1.2来指定列宽 示例程序 假设有一个测试.xlsx的文件,使用如下…

Mac M系列安装配置VSCode

一、终端输入 安装command line tools xcode-select --install 这里是已经下载了 如果没有下载点击安装,等待安装完成即可 检验是否安装成功,终端输入 clang 如图所示是代表之前的command line tools安装 是安装成功的(Clang会不断更新…

spring boot版本升级遇到的一些问题

背景:由于项目需求,需要将nacos 1.4.6版本升级到2.x版本,由此引发的springboot、springcloud、springcloud Alibaba一系列版本变更。 旧版本分别为: Spring Boot 2.3.5.RELEASE Spring Cloud Hoxton.SR9 Spring Cloud Alibaba 2.2…

数据库性能测试报告总结模板

1计划概述 目的:找出系统潜在的性能缺陷 目标:从安全,可靠,稳定的角度出发,找出性能缺陷,并且找出系统最佳承受并发用户数,以及并发用户数下长时间运行的负载情况,如要并发100用户&a…

虚拟化之问答

Q: Type 1 与 Type 2 虚拟机监控程序有何区别? A: Type 2 虚拟机监控程序运行在主机操作系统之上,而 Type 1 虚拟机监控程序则没有主机操作系统。 Q: Secure 状态和 Non-secure 状态分别有多少个 IPA 空间? A: Secure 状态有两个 IPA 空间…

集合工具类Collections

概述 java.utils.Collections:是集合工具类 作用:Collections并不属于集合,是用来操作集合的工具类。 Collections常用的API Collections排序相关API 使用范围:只能对于List集合的排序。 排序方式1: 注意:本方式…

SecureCRT for Mac/win强大安全的终端SSH工具,SecureCRT助您网络连接无忧

在当今数字化时代,网络连接已成为生活和工作中不可或缺的一部分。而对于需要进行远程访问和管理的用户来说,一个稳定、安全的终端SSH工具是至关重要的。SecureCRT作为一款强大的终端SSH工具,为用户提供了安全、高效的远程连接解决方案。 首先…

Linux 文本处理

在处理大文本时,使用VI打开会非常慢,通常只需要查看其中的少量信息,比如查看前多少行、或者文件尾多少行。这种情况下可以使用head和tail命令,这种方式查看起来会非常快。 查看文件1.txt 前1000行: head -n 1000 1.t…