历史上的今天
返回首页

历史上的今天

今天是:2024年09月22日(星期日)

正在发生

2021年09月22日 | 【STM32平衡小车】STM32定时器配置为编码器模式

2021-09-22 来源:eefocus

一、编码器原理

如果两个信号相位差为90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、根据每个信号脉冲数量的多少及整个编码轮的周长就可以算出当前行走的距离、如果再加上定时器的话还可以计算出速度。


二、为什么要用编码器

在这里插入图片描述

从上图可以看出,由于TI1,TI2一前一后有个90度的相位差,所以当出现这个相位差时就表示轮子旋转了一个角度。但有人会问了:既然都是脉冲,为什么不用普通IO中断?实际上如果是轮子一直正常旋转当然没有问题。仔细观察上图,如果出现了毛刺呢?这就是需要我们在软件中编写算法进行改正。于是,我们就会想到如果有个硬件能够处理这种情况那不是挺好吗?


对应的硬件的编码器就来了~

在这里插入图片描述

我们看到STM32的硬件编码器还是很智能的,当TI1,TI2脉冲是连续产生的时候计数器加一次或减一次,而当某个接口产生了毛刺或抖动,则计数器计数不变,也就是说该接口能够容许抖动。


在STM32中,编码器使用的是定时器接口,查阅STM32F103数据手册可知,定时器1,2,3,4,5和8有编码器的功能,而其他定时器没有。注意,在这几个定时器中也只有CH1和CH2可以设置为编码器模式~


三、STM32编码器配置相关

输入信号TI1,TI2后经过输入滤波,边沿检测产生TI1FP1、TI2FP2,然后接到编码器模块。通过配置编码器的工作模式,就可以对编码器进行正向/反向计数。


比如如果用的是定时器2,则对应的引脚是在PA0和PA1上。


通常为了提高精度我们会选择在上升沿和下降沿都进行计数!

在这里插入图片描述

还有一个非常重要的图这里也记录下

在这里插入图片描述

其中让人费解的应该是在第二列的相对信号的电平,这里就来详细谈一下吧。


其实也不难理解哈,我们上面也说了通常为了提高精度会在A、B两相的上升沿和下降沿都进行计数,那么对应在一个周期就可以计数四次,计数次数的增加也就意味着精度的提高!


编码器模式下,如果此时处于正转,那么这四次计数应该都是加的。同理,如果是反转,那么这四次计数都是减的。那么问题来了,如何判断正反转呢?


不就是在相对电平的基础上嘛!!!

在这里插入图片描述

仔细对照图中,在正转或者反转的情况下,A相对B的电平高低以及上表中列出的计数方向便可了然于心!!!


选择编码器接口模式的方法是:


如果计数器只在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上的有效跳变驱动。


配置范例:


CC1S=’01’ (TIMx_CCMR1寄存器, IC1FP1映射到TI1)

CC2S=’01’ (TIMx_CCMR2寄存器, IC2FP2映射到TI2)

CC1P=’0’ (TIMx_CCER寄存器, IC1FP1不反相, IC1FP1=TI1)

CC2P=’0’ (TIMx_CCER寄存器, IC2FP2不反相, IC2FP2=TI2)

SMS=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).

CEN=’1’ (TIMx_CR1寄存器,计数器使能)


四、STM32实战代码

对了,必须要再说明的是编码器模式下只能对应一个定时器的CH1/CH2通道,也就是刚好接A、B相! Perfect!!!


/*TIM2初始化为编码器接口*/

void Encoder_Init_TIM2(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  

TIM_ICInitTypeDef TIM_ICInitStructure;  

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入

GPIO_Init(GPIOA, &GPIO_InitStructure);       //根据设定参数初始化GPIOA


TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 

TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数  

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3

TIM_ICStructInit(&TIM_ICInitStructure);

TIM_ICInitStructure.TIM_ICFilter = 10;

TIM_ICInit(TIM2, &TIM_ICInitStructure);

TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

//Reset counter

TIM_SetCounter(TIM2,0);

TIM_Cmd(TIM2, ENABLE); 

}


/*TIM4初始化为编码器接口*/

void Encoder_Init_TIM4(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  

TIM_ICInitTypeDef TIM_ICInitStructure;  

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入

GPIO_Init(GPIOB, &GPIO_InitStructure);       //根据设定参数初始化GPIOB


TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 

TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数  

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3

TIM_ICStructInit(&TIM_ICInitStructure);

TIM_ICInitStructure.TIM_ICFilter = 10;

TIM_ICInit(TIM4, &TIM_ICInitStructure);

TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位

TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

//Reset counter

TIM_SetCounter(TIM4,0);

TIM_Cmd(TIM4, ENABLE); 

}


/*单位时间编码器计数 输入定时器 输出速度值*/

int Read_Encoder(u8 TIMX)

{

int Encoder_TIM;    

switch(TIMX)

{

case 2:  Encoder_TIM= (short)TIM2 -> CNT;  TIM2 -> CNT=0;break;

case 3:  Encoder_TIM= (short)TIM3 -> CNT;  TIM3 -> CNT=0;break;

case 4:  Encoder_TIM= (short)TIM4 -> CNT;  TIM4 -> CNT=0;break;

default:  Encoder_TIM=0;

}

return Encoder_TIM;

}


void TIM4_IRQHandler(void)

{           

if(TIM4->SR&0X0001)//溢出中断

{                 

}    

TIM4->SR&=~(1<<0);//清除中断标志位     

}


void TIM2_IRQHandler(void)

{           

if(TIM2->SR&0X0001)//溢出中断

{                 

}    

TIM2->SR&=~(1<<0);//清除中断标志位     

}


五、经验之谈

1、编码器有个转速上限,超过这个上限是不能正常工作的,这个是硬件的限制,原则上线数越多转速就越低,这点在选型时要注意,编码器的输出一般是开漏的,所以单片机的io一定要上拉输入状态。【平衡小车之家的编码电机已经有硬件上拉】


2、定时器初始化好以后,任何时候CNT寄存器的值就是编码器的位置信息,正转他会加,反转他会减。这部分是不需要软件干预的,初始化时给的TIM_Period 值是码盘整圈的刻度值,在减溢出会自动修正为这个数,加超过此数值就回0.。


3、如果要扩展成多圈计数需要溢出中断,程序上圈计数加减方向位就行了.。


4、每个定时器的输入脚可以通过软件设定滤波 。


5、应用中如果没有绝对位置信号,或者初始化完成后还没有收到绝对位置信号前的计数只能是相对计数,收到绝对位置信号后重新修改一次CNT的值就行了。码盘一般都有零位置信号,结合到定时器捕获输入就行,上电以后要往返运动一下找到这个位置。


6、即便是滤波计数,值偶尔也会有出错误的情况,一圈多计一个或少计一个数都是很正常的。特别是转速比较高的时候,尤其明显,有个绝对位置信号做修正是很有必要的。绝对位置信号不需要一定在零位置点,收到这个信号就将CNT修正为一个固定的数值即可.。


7、开启定时器的输入中断可以达到每个步计数都作处理的效果,但是高速运转的时候可能会处理不过来。


参考

[1] https://blog.csdn.net/Zach_z/article/details/75095061


[2] https://blog.csdn.net/qq_17280755/article/details/73770598


[3] https://blog.csdn.net/muyidian/article/details/79000721

推荐阅读

史海拾趣

Gigavac LLC公司的发展小趣事

对于数-模转换(D/A转换)用高稳定度稳压电源电路,网友可能提出多个方面的问题。以下是一些可能的问题及其详细回答:

问题一:为什么数-模转换需要高稳定度的稳压电源?

回答
数-模转换器(D/A转换器)将数字信号转换为模拟信号,其输出精度和稳定性直接受到供电电源的影响。高稳定度的稳压电源能够确保D/A转换器在转换过程中电压波动小,从而减小转换误差,提高转换精度。此外,稳定的电源还能保护D/A转换器免受电压波动可能引起的损坏,延长其使用寿命。

问题二:如何设计高稳定度的稳压电源电路?

回答
设计高稳定度的稳压电源电路通常需要考虑以下几个方面:

  1. 选择合适的稳压元件
    • 稳压二极管(齐纳二极管):具有稳定的反向击穿电压,可作为简单的稳压元件。
    • 线性稳压器(LDO):提供低噪声、高精度的输出电压,适用于对电源噪声敏感的场合。
    • 开关稳压器:效率高,但可能引入一定的纹波噪声,需要适当的滤波电路设计。
  2. 优化电源滤波
    • 在稳压电源的输出端加入滤波电容,以减小输出电压的纹波和噪声。
    • 对于开关稳压器,可能需要额外的LC滤波电路来进一步降低纹波。
  3. 考虑温度稳定性
    • 温度变化会影响元件的性能,因此在设计时应考虑元件的温度系数,并采取适当的温度补偿措施。
  4. 采用反馈控制
    • 通过引入电压反馈控制环路,可以实时监测输出电压并调整稳压元件的工作状态,以保持输出电压的稳定。
  5. 选用高质量的元件
    • 使用低漂移、高精度的电阻、电容等元件,以提高电源电路的整体稳定性。

问题三:如何评估稳压电源的稳定度?

回答
评估稳压电源的稳定度通常需要考虑以下几个方面:

  1. 输出电压的纹波和噪声
    • 使用示波器测量输出电压的纹波和噪声水平,确保其在可接受的范围内。
  2. 负载调整率
    • 在不同负载条件下测量输出电压的变化量,评估电源对负载变化的响应能力。
  3. 线性调整率
    • 在输入电压变化时测量输出电压的变化量,评估电源对输入电压变化的抵抗能力。
  4. 温度稳定性
    • 在不同温度条件下测量输出电压的变化量,评估电源的温度稳定性。
  5. 长期稳定性
    • 在长时间运行后测量输出电压的变化量,评估电源的长期使用稳定性。

问题四:有哪些常见的稳压电源故障及其解决方案?

回答
常见的稳压电源故障及其解决方案包括:

  1. 输出电压不稳定
    • 检查稳压元件是否损坏或老化。
    • 检查滤波电容是否失效或容量不足。
    • 检查反馈控制环路是否正常工作。
  2. 无输出电压
    • 检查输入电源是否正常。
    • 检查保险丝是否熔断。
    • 检查稳压元件是否短路或开路。
  3. 输出电压过高或过低
    • 调整稳压元件的工作参数。
    • 检查负载是否过大或过小。
    • 检查输入电压是否在正常范围内。
  4. 温度过高
    • 检查散热系统是否正常工作。
    • 考虑增加散热装置或降低负载。

通过以上问题和答案的梳理,可以帮助网友更全面地了解数-模转换用高稳定度稳压电源电路的设计、评估和维护等方面的知识。

Ampire Co Ltd公司的发展小趣事

Ampire Co., Ltd. 是一家总部位于中国深圳的汽车电子产品制造商,专注于汽车安全、娱乐和舒适性电子产品的研发、生产和销售。以下是关于 Ampire 公司发展的五个相关故事:

  1. 成立与初创阶段:Ampire 公司成立于 2002 年,起初主要从事汽车电子产品的贸易业务。公司的创始人致力于在汽车行业提供高品质的电子产品,以提升驾驶体验和车辆安全性。在公司初期,他们主要进口和销售一些汽车音响和影音产品。

  2. 技术创新与产品升级:随着市场需求的不断变化和技术的进步,Ampire 公司开始注重技术创新和产品升级。公司加大了对汽车安全和行车辅助系统的研发投入,推出了一系列高品质的后视摄像头、倒车雷达、行车记录仪等产品,以提高车辆的安全性和驾驶便利性。

  3. 品牌建设与市场拓展:Ampire 公司通过不断提升产品质量和服务水平,逐渐树立起了良好的品牌形象,并在国内外市场上获得了良好的口碑和知名度。公司积极参加国内外汽车电子展会和行业活动,拓展了国际市场,产品出口至欧美、东南亚等多个国家和地区。

  4. 生产基地建设与产能提升:为满足不断增长的市场需求,Ampire 公司逐步扩大了生产基地,并引进了先进的生产设备和技术。公司建立了完善的生产制造体系,实现了规模化生产和产能提升,保障了产品质量和交货期。

  5. 持续发展与未来规划:Ampire 公司持续致力于技术创新和产品升级,不断推出符合市场需求的新品。未来,公司计划进一步加大在汽车安全、智能驾驶和车载娱乐等领域的研发投入,积极探索人工智能、互联网车联网等新技术的应用,为客户提供更加智能、安全和便捷的汽车电子产品。

这些故事展示了 Ampire 公司从创立初期到如今在技术创新、产品升级、品牌建设、生产基地建设以及未来规划等方面取得的重要进展。

3E SECURITY公司的发展小趣事

随着网络安全威胁的不断加剧,电子安全行业面临着前所未有的挑战。3E SECURITY公司紧跟行业趋势,加强了网络安全服务的研发和推广。公司推出了一系列网络安全解决方案,帮助客户有效应对各类网络攻击和数据泄露风险。同时,公司还加强了对客户的安全培训和技术支持,提升了客户的安全意识和应对能力。

Condor公司的发展小趣事

随着公司业务的不断扩张,3E SECURITY积极寻求与国际同行的合作机会。通过与国外知名安全公司开展技术合作、市场共享等方式,公司成功打开了国际市场的大门。同时,公司还积极参与国际安全标准的制定和推广,提升了公司在国际舞台上的影响力和竞争力。

AINFO Inc公司的发展小趣事

为了进一步提升技术水平和市场竞争力,AINFO Inc公司积极寻求与国际知名企业的技术合作。通过与国外企业的合作,公司引进了先进的技术和管理经验,提升了自身的研发能力和管理水平。同时,公司也加快了国际化发展的步伐,拓展了海外市场,提升了品牌知名度。

DBLECTRO公司的发展小趣事

进入21世纪后,随着全球对环保和可持续发展的关注度不断提高,迪贝电子也积极响应这一趋势,将环保和社会责任融入到企业的经营理念中。公司投入大量资金研发更加环保、节能的产品,并积极参与各种环保公益活动。同时,迪贝电子还积极推广绿色制造理念,通过优化生产流程、降低能耗和减少废弃物排放等措施,实现了企业的可持续发展。

问答坊 | AI 解惑

嵌入式系统的C程序设计

看到还行就顶一下啊~~~…

查看全部问答>

双绞线传输与同轴电缆及光纤的图表比较

双绞线是将一对或一对以上的双绞线封装在一个绝缘外套中而形成的一种传输介质。 同轴电缆是由一根空心的外圆柱导体(铜网)和一根位于中心轴线的内导线(电缆铜芯)组成,并且内导线和圆柱导体及圆柱导体和外界之间都是用绝缘材料隔开。 ...…

查看全部问答>

第二课小结

以后这个地方做点总结 有的个人感觉和c差不多就没有怎么说,也不会怎么用到,有这个主要的基本语法就不错啦!…

查看全部问答>

PFAA-可编程模拟电路

很长时间就梦想着模拟电路能够像FPGA一样方便设计,现在终于看到FPAA技术了!希望大家踊跃讨论!其中ISPPAC发展的很快…

查看全部问答>

TI公司新出了Piccolo系列的C2000 DSC,大家觉得怎么样啊?

高效率32位CPU(TMS320C28xTM核) 具有40MHz/60MHz主频; 单周期执行一次32×32或两次16×16乘加(MAC);   改进型哈佛总线结构;   原子操作;   快速中断响应与处理;   统一的存储器设 ...…

查看全部问答>

一个简单的电路,不明白是什么作用,大家帮忙看看吧

一个简单的电路,不明白是什么作用,大家帮忙看看吧 PWM怎么控制电源VCC的呢? [ 本帖最后由 csworld 于 2009-12-20 11:27 编辑 ]-%-284546-%-…

查看全部问答>

音频设置

我在WinCE下做个音频(我用的是vb.net),但是想引用System.Media这个包,但是没有提示,该怎么引用啊?? 我用的是arm9 qq2440是不是要把底层修改,还是怎么搞啊?? 大家,帮个忙谢谢了!!…

查看全部问答>

如何买块合适的学习板

现在在职工作一年了,从事软件开发,经常和硬件打交道!算是一个嵌入式门口的程序员!发现在自己的能力增加到一定之后,对应用层代码的兴趣就没那么高啦。可是公司的产品很成熟,底层驱动都很稳定,不需要改动,所以平时也没有机会学到那方面知识, ...…

查看全部问答>

招人共同组建团队,不是外包,月五万,招有志者,共同创业,知识转化为金经,你不要看不起我们

团队公开所有源码,和调试技术,包括财务,所有的利润除去费用后,全属个人成员,优秀者我们重用 招聘要求:       * 热爱   旭日TOP团队,坚信   旭日TOP团队   会象   WinRAR  ...…

查看全部问答>