背景

买了个Arduino的旋转编码器模块,配合STM32定时器的编码器模式实现了旋转角度以及圈数的计数。这种旋转编码器我能想到的实际应用场景暂时只有实体音量旋钮,鼠标的滚轮等,所以只实现了计数。阅读Arduino关于该编码器的介绍,该编码器还可以实现旋转的速度、加速度的计算。应该算是算法层级的吧,还没做到实际应用,暂时不深究,本篇仅仅对旋转编码器的原理以及STM32编码器接口模式的配置使用方法做个简介。

正文

编码器分类:

按工作原理:光电式、磁电式和触点电刷式;

按码盘的刻孔方式:增量式和绝对式两类;

这是从网上看到一个简介,只接触过Arduino的编码器,其他暂未使用过。

Arduino的编码器属于增量式。它一共有5根线。分别为“CLK”、“DT”、“SW”、“+”、“GND”。

  • “+”、“GND”:勿用多说,VCC与GND,接至板子的VCC与GND即可。
  • “SW”:Arduino介绍说,当旋钮旋转完一圈时,该脚会放出一个电平跳变信号,相当于旋转编码器常说的“Z”信号,实际上我买的这个只是一个开关,即旋钮部分可以按下去(类似于汽车上的音量调节按钮),该接口会产生一个下降沿。然后由MCU去做相关处理。
  • “CLK”、“DT”:在该模块上显示的丝印名称为这两个,不明白为什么是这个丝印,应该实际对应于编码器常用的“A”、“B”信号吧,这两个信号的发生方式如下:

  1. 正旋:如上图当旋钮开始正向旋转时,“A”从低电平变为高电平,“B”保持不变;当旋钮旋转到预定位置时,“A”维持为高电平,“B”然后跟着从低电平跳变到高电平。也就是说,正旋时,“A”总是先与“B”开始电平变化。
  2. 反旋:与正旋相反,“B”总是先与“A”开始电平变化。

    所以在此处,丝印将该两个接线印成“CLK”、“DT”就让我有点困惑。也未找到相关资料,先暂时放放,下次有实际应用,就知道为什么了。

根据如上正旋反旋规律,就已经可以根据编码器输出的信息判断出编码器的旋转方向以及计算出其旋转角度了,具体做法如下:

将“CLk”、“DT”分别连接至MCU的任意具有外部中断的IO口,处理方式为:

  1. 将该两个IO口配置为双边沿外部中断。
  2. 当其中某个IO口检测到上升沿或者下降沿时,在中断函数内检测另一个IO口的电平状态。以正旋为例,正旋时,“A”先上升沿引起中断,得到的“A”、“B”的电平状态为“10”,紧接着,“B”上升沿,检测到“A”、“B”电平状态为“11”。
  3. 若一直正转,则“A”、“B”的电平状态为“10 - 11 - 01 - 00 - 10 - ...”。
  4. 若一直反转,则“A”、“B”的电平状态为“01 - 11 - 10 - 00 - 01 - ...”

    以此,即可判断出该编码器的旋转方向,同时在“A”、“B”同时跳变完成后,即可根据编码器的旋转方向对编码器的旋转计数进行增减。

以上为使用外部中断方式处理旋转编码器的输出信息,当然,本篇要用到STM32定时器的接口模式,所以也就不会用以上的方法进行判断。那么定时器的接口模式是如何对旋转编码器进行计数的呢?

其实原理一样,将旋转编码器的“CLK(A)”、“DT(B)”脚接入到TIMx的通道,将对应通道引脚配置为编码器接口模式,使能计数,然后STM32的值就会在硬件上按照上述规对计数器的值进行加减。

本实验接到的是STM32F103的“PB6(TIM4_CH1)”、“PB7(TIM4_CH2)”,具体配置如下:

  1. 配置IO口:
    // GPIO
// 使能对应的GPIO口时钟
RCC_APB2PeriphClockCmd(Enc_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = Enc_CLK_GPIO_PIN | Enc_DAT_GPIO_PIN | Enc_SW_GPIO_PIN;
// 该编码器模块已经做了外部上拉处理,配制成浮空输入即可
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(Enc_GPIO_PORT, &GPIO_InitStructure);
  1. 配置定时器基本单元:
    // TIM4
// PB6 ch1 A,PB7 ch2
// TIMxCLK = 36MHZ
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_DeInit(TIM4);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  1. 配置对应寄存器为编码器接口模式以及配置相关的输入捕获配置:
    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,  TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);

    TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
  1. 清除相关中断,以及清除对应的计数器,并启动定时器:

// Clear all pending interrupts
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
// 其实中断可以不用开,因为硬件自行对计数器进行加减。
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
//Reset counter
TIM4->CNT = 0; TIM_Cmd(TIM4, ENABLE); //启动TIM4定时器
  1. 如若开了中断,中断处理函数为:
void TIM4_IRQHandler(void)
{
if(TIM4->SR&0x0001)//溢出中断
{
LED_Toggle(1);
}
TIM4->SR&=~(1<<0);//清除中断标志位
}
  1. 主函数读取相应计数器值,并将其打印至串口:
int main(void)
{
// 读取计数器信息
Enc0Pos = TIM_GetCounter(TIM4);
// 取模2的原因是,两个引脚接到同一个定时器,每旋转一次会计数两次
Enc0Pos /= 2;
if(Enc0Pos != Enc_PinDATLast
{
Enc_PinDATLast = Enc0Pos;
printf("Position = %d\n\r", Enc0Pos);
}
}

参考文献:

"Reading Rotary Encoders Contents".

"Get Native 32Bit resolution for your encoder on STM32F4".

"STM32定时器---正交编码器模式详解".

至此,记录完毕

记录时间:2017-1-4

记录地点:深圳WZ

STM32f103 定时器之编码器接口模式的更多相关文章

  1. STM32伺服编码器接口

    在STM32的高级定时器和一般定时器中有Encoder interface mode(编码器接口),TI1和TI2分别对应TIM_CH1 和TIM_CH2 通道. 一.计数规则如下: 表55的是编码器 ...

  2. STM32 HAL库学习系列第5篇 定时器TIM---编码器接口模式配置

    cube基本配置,外设开启编码器,串口2 可能大家在设置的时候有这个错误 错误:error:  #20: identifier "TIM_ICPOLARITY_BOTHEDGE" ...

  3. Dell poweredge r210进BIOS改动磁盘控制器(SATA Controller)接口模式

    Dell poweredge r210进BIOS改动磁盘控制器(SATA Controller)接口模式 开机后按F2键进入BIOS设置,例如以下图: BIOS设置主界面: 使用上下键移动光标到&qu ...

  4. C#使用windows服务定时调用api接口

    使用VS创建windows服务项目: 创建好项目  会出现一个设计界面 右键弹出对话框 选择添加安装程序 名字什么的自己可以改: 项目目录: 打开项目中的ProjectInstaller.Design ...

  5. 重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关

    重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关 引言 重复造轮子系列是自己平时的一些总结.有的轮子依赖社区提供的轮子为基础,这里把使用过程的一些觉得有意思的做个分享.有些思路或者方法在 ...

  6. cocos2d-x 真正的定时器之schedule

    转载请注明,原文地址:http://blog.csdn.net/musicvs/article/details/8551066 正文: 1. 不调用update函数,调用自己的函数 其实原理是一样的, ...

  7. 《Java设计模式》之接口模式

    -----------模式是思想的体现,而非详细的实现. 抽象的讲,类的接口是类同意其它类对象訪问的方法与字段集.接口通常代表一种承诺,即方法须要实现接口方法名表示的操作,遵循代码凝视和其它文档说明. ...

  8. 外观模式(Facade)-子系统的协作与整合-接口模式

    对子系统进行整合,对外提供更强大或更便捷的接口. 在一个模块和几个子系统进行通信时考虑. 什么是外观模式? 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口 ...

  9. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储+服务+抽象接口模式

    本文梯子 本文3.0版本文章 前言 零.完成图中的粉色部分 2019-08-30:关于仓储的相关话题 一.创建实体Model数据层 二.设计仓储接口与其实现类 三.设计服务接口与其实现类 四.创建 C ...

随机推荐

  1. 【转】XenServer架构之XAPI

    一.XAPI对资源池的管理 作为XenServer的管理工具集,XAPI管理XenServer的主机,网络和存储.不管是OpenStack还是CloudStack,如果使用XenServer作为虚拟化 ...

  2. Webform:Session、Cookie对象的用法

    Session 优点:1.使用简单,不仅能传递简单数据类型,还能传递对象.  2.数据量大小是不限制的. 缺点:1.在Session变量存储大量的数据会消耗较多的服务器资源. 2.容易丢失. 使用方法 ...

  3. 绘制扇形效果线条小Bug解决

    绘制线条基本代码: 变量: CPoint m_ptOrigin;//起点坐标 bool m_bTrue;//检查鼠标左键是否按下 CPoint m_ptOldOrigin;//记录上一次绘制终点坐标, ...

  4. vs2013 error : cannot open source file "SDKDDKVer.h"

    改: 项目属性--常规--工具集--Visual Studio 2013-WindowsXP(v120_xp)

  5. jdbc java数据库连接 7)获取插入数据的自增长值

    我们创建一个sql表,里面的数据往往都会有自增长值. 那么,我们用jdbc插入数据的时候,要想同时获得这个增长值. 代码: /** * * 这是插入一条数据的同时,获取该数据的则增长列的值(该例子的自 ...

  6. [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)

    Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或 ...

  7. java 集合

    1. 2.for循环的时候会改变角标,所以删除需要--,增加需要++ 3.去除重复元素2(用的实质都是对象的equals方法) 4.Treeset 里面的add方法 5.treeSet里面addstu ...

  8. HTML 学习笔记 (canvas 基础)

    1.什么是Canvas canvas就是一个画布,可以进行画任何的线,图形,填充等一系列操作.这一切都是用Js操作的,另外Canvas不仅仅提供简单的二维矢量绘图,也提供了三维的绘图,以及图片处理等一 ...

  9. [笔记]ng2的webpack配置

    欢迎吐槽 前言 angular.cn教程中用的是systemjs加载器,那用webpack应该怎么配置呢?本文 demo: https://github.com/LeventZheng/angular ...

  10. PIC10F200/202/204/206/220/222/320/322芯片解密程序复制多少钱?

    PIC10F200/202/204/206/220/222/320/322芯片解密程序复制多少钱? PIC10F单片机芯片解密型号: PIC10F200解密 | PIC10F202解密 | PIC10 ...