发新帖我要提问
123
返回列表
打印
[应用相关]

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

[复制链接]
楼主: ssyniuej
手机看帖
扫描二维码
随时随地手机跟帖
41
kangxuebin| | 2013-8-2 20:08 | 只看该作者 回帖奖励 |倒序浏览
学习了,看来此方法可以解决问题

使用特权

评论回复
42
ranqingfa| | 2013-10-25 11:34 | 只看该作者
非常好的方法  聪明  15#

使用特权

评论回复
43
dtlz| | 2014-10-15 14:25 | 只看该作者
可以试一下,用定时器的溢出中断,设置一个寄存器,在定时器溢出中断时,判断DIR标志位,是否减一还是加一,这个寄存器的数为高16位,和定时器的那个低16位合起来就是32位了,比设置一个从计数器更简单方便,从计数器只是加不能减,麻烦!

使用特权

评论回复
44
patrouille| | 2014-11-20 16:05 | 只看该作者
学习了

使用特权

评论回复
45
ersha4877| | 2014-12-23 22:21 | 只看该作者
auzxj 发表于 2010-4-23 19:51
STM32的硬件编码器是16位的,要是超过65536就会麻烦一些
目前我的项目中需要用到一个光栅尺,栅距是0.5um, ...

请问您的代码不需要处理中断吗??代码中没有定时器中断程序,谢谢

使用特权

评论回复
46
tianhaolan| | 2015-5-28 11:44 | 只看该作者
专门过来学习一下

使用特权

评论回复
47
hpf9017| | 2015-6-4 13:34 | 只看该作者
lxyppc 发表于 2010-4-23 23:12
这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)

非常感谢14楼提供的方法!

max这个值很关键,就是说相邻两次调用的时间内,编码器的数值不能超过这个。
之前自己测试一直忽略了这个。

使用特权

评论回复
48
逸翮孤风| | 2015-7-13 10:32 | 只看该作者
lxyppc 发表于 2010-4-23 23:12
这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)

想问一下,如果我的电机在短时间内做往复运动,还能测速吗?

使用特权

评论回复
49
梦翔青春| | 2015-7-31 19:01 | 只看该作者
lxyppc 发表于 2010-4-23 23:12
这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)

#include"zjbmq.h"


void ENC_Init(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;


        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_StructInit(&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


        TIM_DeInit(TIM3);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

        TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置预分频:
        TIM_TimeBaseStructure.TIM_Period = (4*1000)-1;;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

        TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);

        // Clear all pending interrupts
        TIM_ClearFlag(TIM3, TIM_FLAG_Update);
        TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM3->CNT = 0;


        TIM_Cmd(TIM3, ENABLE);
}

s16 ENC_Get_Electrical_Angle(void)
{
        static u16   lastCount =0;
        u16 curCount = TIM3->CNT;
        s32 dAngle =curCount - lastCount;
        if(dAngle >= 500)
        {
                  dAngle -=1000;
        }
        else if(dAngle < -500)
        {
                   dAngle += 1000;
        }
        lastCount = curCount;
        return (s16)dAngle;
}

使用特权

评论回复
50
梦翔青春| | 2015-7-31 19:02 | 只看该作者
auzxj 发表于 2010-4-26 13:13
您的这种方法依然规避不了我7楼的那种情况吧,计数器正向加,然后溢出,假如溢出后又累加了N个数,若此时 ...

请问一下,能否看看我的代码错在哪里,编码器没反应

使用特权

评论回复
51
梦翔青春| | 2015-7-31 19:05 | 只看该作者
auzxj 发表于 2010-4-27 16:30
我在这里写了篇学习笔记,有兴趣的可以看下:http://blog.**/auzxj/1473143/message.aspx ...

#include"zjbmq.h"


void ENC_Init(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;


        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_StructInit(&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


        TIM_DeInit(TIM3);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

        TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置预分频:
        TIM_TimeBaseStructure.TIM_Period = (4*1000)-1;;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

        TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);

        // Clear all pending interrupts
        TIM_ClearFlag(TIM3, TIM_FLAG_Update);
        TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM3->CNT = 0;


        TIM_Cmd(TIM3, ENABLE);
}

s16 ENC_Get_Electrical_Angle(void)
{
        static u16   lastCount =0;
        u16 curCount = TIM3->CNT;
        s32 dAngle =curCount - lastCount;
        if(dAngle >= 500)
        {
                  dAngle -=1000;
        }
        else if(dAngle < -500)
        {
                   dAngle += 1000;
        }
        lastCount = curCount;
        return (s16)dAngle;
}
请问一下我代码哪里改错了,怎么编码器没反应呀,谢谢啦

使用特权

评论回复
52
梦翔青春| | 2015-7-31 19:08 | 只看该作者
请问一下我的代码哪里出问题了,编码器没反应谁能帮帮我,感谢感谢。


#include"zjbmq.h"


void ENC_Init(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;


        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_StructInit(&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


        TIM_DeInit(TIM3);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

        TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置预分频:
        TIM_TimeBaseStructure.TIM_Period = (4*1000)-1;;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

        TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);

        // Clear all pending interrupts
        TIM_ClearFlag(TIM3, TIM_FLAG_Update);
        TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM3->CNT = 0;


        TIM_Cmd(TIM3, ENABLE);
}

s16 ENC_Get_Electrical_Angle(void)
{
        static u16   lastCount =0;
        u16 curCount = TIM3->CNT;
        s32 dAngle =curCount - lastCount;
        if(dAngle >= 500)
        {
                  dAngle -=1000;
        }
        else if(dAngle < -500)
        {
                   dAngle += 1000;
        }
        lastCount = curCount;
        return (s16)dAngle;
}

使用特权

评论回复
53
冰冷的游客| | 2015-8-10 14:01 | 只看该作者
标记

使用特权

评论回复
54
心染红尘| | 2015-10-8 22:20 | 只看该作者
lxyppc 发表于 2010-4-23 23:12
这个是我经常用的编码器读取方法

s16   Enc_GetCount(void)

这个MAX_COUNT的值如何求得?

使用特权

评论回复
55
tianhaolan| | 2016-1-14 11:29 | 只看该作者
心染红尘 发表于 2015-10-8 22:20
这个MAX_COUNT的值如何求得?

根据你的编码器的最大旋转速度算出来的。比如说,你的编码器最大旋转速度是1秒钟10圈(这里就是为了好计算,一般没有转这么快的编码器),通过另一个定时器来定时的话,如果定时器取10mS的话就是0.1圈也就是36°。如果分辨率是1000的编码器0.1圈的话会计数1000*4*0.1=400下,那么你这个MAX_COUNT就要取得比这个400还要大一些,比如500或者600都行。

使用特权

评论回复
56
zhenglingo| | 2016-2-26 11:53 | 只看该作者
非常好的设计。用一个定时器10MS定时读取编码器值也不会占用CPU很多时间,还是可以干其他事的,只是要将定时器中断优先级提升。

使用特权

评论回复
57
940126mc| | 2016-5-5 16:19 | 只看该作者
我是刚接触stm32,要用其做光栅尺数显表设计,光栅尺输出A,B两路信号我接到stm32的PA6和PA7,如何实现测距呢,显示部分已做出来,计数部分不懂,光栅尺分辨率5um,量程200mm,求教

使用特权

评论回复
58
SantaBunny| | 2023-2-23 19:54 | 只看该作者
搞个计数器溢出中断

使用特权

评论回复
59
Pretext| | 2024-4-4 15:54 | 只看该作者
为什么我们要反过来做? 我们不能再做一次吗?

使用特权

评论回复
60
香水城| | 2024-4-5 09:27 | 只看该作者
很难有完美的方法,编码器的加和减是基于硬件识别的。

第2级定时器只能基于溢出事件【更新事件】进行加,不能再减了。

要减的话在第一级就已经减了,而且第2级减1就不是减1个计数脉冲了,而是减掉前级的ARR+1个脉冲。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则