打印
[应用相关]

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

[复制链接]
楼主: ssyniuej
手机看帖
扫描二维码
随时随地手机跟帖
21
lxyppc| | 2010-4-27 16:57 | 只看该作者 回帖奖励 |倒序浏览
我在这里写了篇学习笔记,有兴趣的可以看下:http://blog.**/auzxj/1473143/message.aspx
auzxj 发表于 2010-4-27 16:30


楼主的代码里面还有一个细节问题
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;
应该为:
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD - 1;

还一点ENCODER_TIM_PERIOD 最好定义为MAX_COUNT的两倍或更大
这里是我的一个开源项目的Encoder初始化代码

http://lxyppc-oled.googlecode.com/svn/trunk/%20lxyppc-oled/STM32/oleddrv/src/Encoder.c

使用特权

评论回复
22
火箭球迷| | 2010-4-27 18:41 | 只看该作者
很好的学习笔记

使用特权

评论回复
23
auzxj| | 2010-4-28 08:33 | 只看该作者
21# lxyppc
这是我的宏定义,可能名字起得不太合适容易误解
#define ENCODER_TIM_PERIOD (u16)0xFFFF
#define MAX_COUNT          (u16)0x0FFF

使用特权

评论回复
24
yunqian09| | 2010-7-17 14:43 | 只看该作者
qiangtie:)

使用特权

评论回复
25
hw5226349| | 2012-6-27 17:03 | 只看该作者
正在搞编码器,学习

使用特权

评论回复
26
abkleo| | 2012-6-28 17:03 | 只看该作者
我也遇到这类问题,求解决办法

使用特权

评论回复
27
dream-yi| | 2012-8-29 13:07 | 只看该作者
学习了

使用特权

评论回复
28
飞言走笔| | 2013-3-25 14:48 | 只看该作者
好帖好帖,标记之~~

使用特权

评论回复
29
xinyang666| | 2013-3-25 16:49 | 只看该作者
已经在用了,效果蛮好的,按照实际条件进行了微调,加了一些条件判断。

使用特权

评论回复
30
kangxuebin| | 2013-8-2 20:08 | 只看该作者
学习了,看来此方法可以解决问题

使用特权

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

使用特权

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

使用特权

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

使用特权

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

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

使用特权

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

使用特权

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

s16   Enc_GetCount(void)

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

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

使用特权

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

s16   Enc_GetCount(void)

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

使用特权

评论回复
38
梦翔青春| | 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;
}

使用特权

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

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

使用特权

评论回复
40
梦翔青春| | 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;
}
请问一下我代码哪里改错了,怎么编码器没反应呀,谢谢啦

使用特权

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

本版积分规则