打印
[应用相关]

请问香主,用STM32的硬件编码器如何扩展成32位?

[复制链接]
20313|61
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ssyniuej|  楼主 | 2009-5-12 16:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用STM32的定时器2工作于编码器方式,可以正常得到编码器位置,但由于现在只有16位计数,位数不够,我想扩展到32位,经过试验未能解决,请帮忙提个思路。
    一、先用定时器内部连接,将定时器2 的溢出送到定时器3,用定时器3做高位,在正转的时候正常,但反向的时候出错。分析了一下,主要是定时器3的方向一直是正向计数,不知道如何能够将定时器2 的方向标志控制一下定时器3 的方向。
    请帮忙,谢谢。
沙发
ssyniuej|  楼主 | 2009-5-12 16:43 | 只看该作者

不知道大家有没有碰到这种用法?

使用特权

评论回复
板凳
sheepbaa| | 2009-5-13 08:25 | 只看该作者

我也遇到类似的问题.

我也遇到相同的问题.但是我只用了16位的,然后软件来计算扩展.
如果用2个计数器来实现32位的话,
如果在读取数据时读取了低16,在准备读取高16位的时候.发生了进位会不会读到错误的数据?

使用特权

评论回复
地板
auzxj| | 2010-4-23 12:18 | 只看该作者
恩,我也遇到这样的 困扰了

使用特权

评论回复
5
auzxj| | 2010-4-23 19:51 | 只看该作者
STM32的硬件编码器是16位的,要是超过65536就会麻烦一些
目前我的项目中需要用到一个光栅尺,栅距是0.5um,但我的行程是40cm,最大计数是80000,要是在计数器溢出的时候再反向走,就会出现错误
我考虑是否可以这样,每次计数器溢出都给赋32768,貌似有个auto-reload的,不知能否用在这,还没仔细研究,如果这样可行,就可以消除溢出后反向运动的误差

使用特权

评论回复
6
xsgy123| | 2010-4-23 20:02 | 只看该作者
计数器溢出的时候再反向走,这样为什么会出错,定时器溢出一般都是采取这种处理方式的

使用特权

评论回复
7
auzxj| | 2010-4-23 20:08 | 只看该作者
6# xsgy123
计数器溢出后值为0,要是反向走,计数器减一,是0了还能减1吗?

使用特权

评论回复
8
hsbjb| | 2010-4-23 21:09 | 只看该作者
为什么一定要是反向计呢,重新计数不行么?

使用特权

评论回复
9
auzxj| | 2010-4-23 21:14 | 只看该作者
8# hsbjb
这是码盘啊,他反向正向也不是我能控制的,你可能不知道我们在讨论啥,汗一个:L

使用特权

评论回复
10
lxyppc| | 2010-4-23 21:29 | 只看该作者
STM32的硬件编码器是16位的,要是超过65536就会麻烦一些
目前我的项目中需要用到一个光栅尺,栅距是0.5um,但我的行程是40cm,最大计数是80000,要是在计数器溢出的时候再反向走,就会出现错误
我考虑是否可以这样, ...
auzxj 发表于 2010-4-23 19:51


我能不能做这样一个假设:

若Timer从零开始计数,在T时间内一定不会溢出

这里T需要大于10us才比较有意义

如果这个假设能成立可以有work around的办法

使用特权

评论回复
11
lxyppc| | 2010-4-23 21:37 | 只看该作者
还一种MicroChip的Application note中的用法
大意如下:
给Timer设定一个预分频值,比如65535,这样再加上Timer本身的计数寄存器的16位就有32精度了
我们只能得到Timer计数器的值,在计数结束时只要想办法把预分频里的值读取出来就行了

使用特权

评论回复
12
auzxj| | 2010-4-23 21:55 | 只看该作者
本帖最后由 auzxj 于 2010-4-23 22:10 编辑

10# lxyppc
在我的项目中,你10楼的这种假设是成立的,1秒内都不会溢出,劳烦详述work around方法

预分频器怎么读出来是问题的关键

使用特权

评论回复
13
bsz84| | 2010-4-23 22:04 | 只看该作者
关注!

使用特权

评论回复
14
lxyppc| | 2010-4-23 23:12 | 只看该作者
10# lxyppc
在我的项目中,你10楼的这种假设是成立的,1秒内都不会溢出,劳烦详述work around方法

预分频器怎么读出来是问题的关键
auzxj 发表于 2010-4-23 21:55


这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)
{
  static  u16   lastCount = 0;
  u16  curCount = ENCODER_TIM->CNT;
  s32 dAngle = curCount - lastCount;
  if(dAngle >= MAX_COUNT){
    dAngle -= ENCODER_TIM_PERIOD;
  }else if(dAngle < -MAX_COUNT){
    dAngle += ENCODER_TIM_PERIOD;
  }
  lastCount = curCount;
  return (s16)dAngle;
}

既然你1s都不会溢出,那你可以做个每10ms产生一次的中断
在中断中调用上面的代码
上述代码中MAX_COUNT是 比 10ms内可能出现的计数最大值 还要大的值
ENCODER_TIM_PERIOD是定时器的period值,最好比MAX_COUNT大
然后定义一个32位的有符号变量,如currentCount
然后每隔10ms执行一次
currentCount += Enc_GetCount();
你只需要去读取currentCount的值就可以得到位移信息了。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
90chinazhu + 1 很给力!
15
auzxj| | 2010-4-26 13:13 | 只看该作者
这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)
{
  static  u16   lastCount = 0;
  u16  curCount = ENCODER_TIM->CNT;
  s32 dAngle = curCount - lastCount;
  if(dAngle >= MAX_COUNT){
    dAng ...
lxyppc 发表于 2010-4-23 23:12

您的这种方法依然规避不了我7楼的那种情况吧,计数器正向加,然后溢出,假如溢出后又累加了N个数,若此时计数器反向减超过N就会出现错误

使用特权

评论回复
16
香水城| | 2010-4-26 13:23 | 只看该作者
是否可以用上下溢中断进行处理呢?

使用特权

评论回复
评论
myxiaonia 2015-10-9 09:22 回复TA
这意思是说不用级联定时器了,外部再加一个高16位值啊 
17
lxyppc| | 2010-4-26 13:52 | 只看该作者
您的这种方法依然规避不了我7楼的那种情况吧,计数器正向加,然后溢出,假如溢出后又累加了N个数,若此时计数器反向减超过N就会出现错误
auzxj 发表于 2010-4-26 13:13

在这种情况下计数器的值变化是这样的,假设计数器周期值为999:
初始值    995
正转10   995+10=>1000+5=5
反转7     5-7=>-2+1000 = 998
最终值    998
因此总共转了998-995 = 3个步长,与实际情况相同

使用特权

评论回复
18
midway| | 2010-4-27 15:28 | 只看该作者
有办法解决啊,溢出中断中 判断计数方向是上计数还是下计数,来决定高16位是+还是-,实际当中已经测试过进行编码器计数。

使用特权

评论回复
19
auzxj| | 2010-4-27 16:28 | 只看该作者
17# lxyppc
用你的方法我已经测试成功了,感谢你的方法,哈哈

使用特权

评论回复
20
auzxj| | 2010-4-27 16:30 | 只看该作者
我在这里写了篇学习笔记,有兴趣的可以看下:http://blog.**/auzxj/1473143/message.aspx

使用特权

评论回复
评论
snails 2022-8-21 16:23 回复TA
这个链接打不开了,有新的链接吗?我感兴趣,想看看 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

5

帖子

0

粉丝