打印
[STM32F1]

stm32编码器

[复制链接]
819|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Anlen|  楼主 | 2015-5-6 09:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
stm32编码器,刚开始读头在光栅上运动,然后有读数,之后一小段时间内光栅没有在这个读头上运动,过了一会才返回来,这样的话编码器的读数是在之前的读数的基础上加起来的吗?
沙发
s_f_tan| | 2015-5-6 10:15 | 只看该作者
一般用的光栅是相对式光栅,只是反映一个正向或反向的运动脉冲情况,单片机的计数器只是把脉冲按照方向累加起来而已。除非超出它的计数频率,否则不会漏数的

使用特权

评论回复
板凳
mmuuss586| | 2015-5-6 22:26 | 只看该作者
你移开的时候,数据已经变了;

使用特权

评论回复
地板
Anlen|  楼主 | 2015-5-7 10:04 | 只看该作者
mmuuss586 发表于 2015-5-6 22:26
你移开的时候,数据已经变了;

那变成什么数据了,是随机的吗,还是某个指定的值?

使用特权

评论回复
5
Anlen|  楼主 | 2015-5-7 10:38 | 只看该作者
我看了一下计数器内部的值,移开了之后寄存器的值不会变,但是如果不是在最大值或最小的地方数据会发生跳变,例如我刚开始移动光栅数值从0000加到00fc,然后换向从00FC减到0,然后还没减完等减完后数据编程FFEC ,所以我现在出现的问题就是从0000越变到FFEC

使用特权

评论回复
6
mmuuss586| | 2015-5-7 18:40 | 只看该作者
Anlen 发表于 2015-5-7 10:04
那变成什么数据了,是随机的吗,还是某个指定的值?

肯定固定值啊;
多少的话,看相对移动量;

使用特权

评论回复
7
zh113214| | 2015-5-7 22:19 | 只看该作者
新手表示不知道 。。。

使用特权

评论回复
8
Anlen|  楼主 | 2015-5-11 10:11 | 只看该作者
已经好了,是我自己理解有点错误,我一直以为不管怎样移动,初始的状态就是就一直处于增加状态,但实际上不是,与编码接口有关的,不过好在问题发现了。

使用特权

评论回复
9
翱翔云端的鸟| | 2015-5-11 11:52 | 只看该作者
编码器分绝对式和增量式的,绝对式是一个角度对应一个位置,增量式的是通过一个参考0  Z信号来判断当前角度的!

使用特权

评论回复
10
Anlen|  楼主 | 2015-5-12 13:50 | 只看该作者
如果没有用中断可以使用编码器模式吗?

使用特权

评论回复
11
Anlen|  楼主 | 2015-5-12 13:50 | 只看该作者
如果没有用中断可以使用编码器模式吗?

使用特权

评论回复
12
Anlen|  楼主 | 2015-5-12 16:33 | 只看该作者

输出波形

本帖最后由 Anlen 于 2015-5-12 16:49 编辑

有那位大侠帮我看一下我输出的波形是这样的,下面是我的代码:
#include "stm32f10x.h"
#include "stdlib.h"
#include <stdio.h>
#include "delay.h"


static s16 current_Count;
u8 flag;
uint16_t dma_buffer[100];


static uint16_t n_Count1,n_Count2 ;  //定时器读取的值
static uint16_t  last_Count1,last_Count2;
//static int16_t last_Count,n_Count;  //上次计数器的值
static int16_t         dpos,dpos1,dpos2;
int16_t last_dpos1,last_dpos2,last_dpos;



//const u16 da[12] = { 0,2,8,16,32,64,128,256,512,1024,2048};

#define MAXCOUNT 200
#define ENCODER_TIM_PERIOD 1000
#define Distance  600
#define DAC_DHR12R1_Address  0x00000008;

void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  {
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
    FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
              
    RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
    RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
         
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
    RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
   
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
    while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
    {
    }
  }
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //AFIO时钟
  
}


void TimConfig(void)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        //开放时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

         //GPIO初始化 使用重映射的功能PC6对应TI1,PC7-TI2
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC,&GPIO_InitStructure);  
        GPIO_PinRemapConfig(GPIO_FullRemap_TIM3 ,ENABLE);
        //编码器模式
        TIM_DeInit(TIM3);


        //GPIO初始化使用定时器4在PB6和PB7
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);  
        TIM_DeInit(TIM4);

        /**************设置TIM3CLK=72M,PREscale = 99;ARR=999
        F=72M/((ARR+1)(PSC+1))*********************/
        TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;         //(值要修改)
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        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 = 0x06 ;
//        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  // 在TIM每次捕获到一个边沿执行一次
        TIM_ICInit(TIM3,&TIM_ICInitStructure);
        TIM_SetCounter(TIM3,0);
        //使能TIM3计数器
        TIM_Cmd(TIM3,ENABLE);



         TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;         //(值要修改)
         TIM_TimeBaseStructure.TIM_Prescaler = 0;
         TIM_TimeBaseStructure.TIM_ClockDivision =  TIM_CKD_DIV1;  //不分频
         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
         TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
         TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
//         TIM_ICStructInit(&TIM_ICInitStructure);
         TIM_ICInitStructure.TIM_ICFilter = 0x06 ;
         TIM_ICInit(TIM4,&TIM_ICInitStructure);
         TIM_SetCounter(TIM4,0);
         TIM_Cmd(TIM4,ENABLE);


        //定时器2用来定时10ms
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period = 100-1;
        TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;
        TIM_TimeBaseStructure.TIM_ClockDivision =  TIM_CKD_DIV1;  //不分频
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
        TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update);
        TIM_Cmd(TIM2,ENABLE);
        TIM_ClearFlag(TIM2,TIM_FLAG_Update);
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
         
}

/********因为定时器属于MCU的外设,所以中断配置应该配置为外部中断************/


void NVIC_Config(void)
{

         NVIC_InitTypeDef NVIC_InitStructure;
         NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2全局中断
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级最高
         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级
         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
         NVIC_Init(&NVIC_InitStructure);
         

}  


void DAC_Config(void)
{
        DAC_InitTypeDef DAC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
        GPIO_SetBits(GPIOA,GPIO_Pin_4);

        DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;  //定时器2触发
        DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
        DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
        DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
        DAC_DMACmd(DAC_Channel_1,ENABLE);
        DAC_Init(DAC_Channel_1,&DAC_InitStructure) ;

        DAC_Cmd(DAC_Channel_1,ENABLE);
        
}


void DMA_Configuration(void)
{
        DMA_InitTypeDef DMA_InitStructure;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);
        DMA_DeInit(DMA2_Channel3);
        DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1_Address;        //DAC地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&dma_buffer;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设作为数据的目的地
        DMA_InitStructure.DMA_BufferSize = 100;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize =         DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA2_Channel3,&DMA_InitStructure);
        DMA_Cmd(DMA2_Channel3,ENABLE);
        DMA_ITConfig(DMA2_Channel3,DMA_IT_TC,ENABLE);//传输完成中断屏蔽
}


int16_t Get_Count()
{

        n_Count1 = TIM_GetCounter(TIM3);
        n_Count2 = TIM_GetCounter(TIM4);

        dpos1 = last_Count1 - n_Count1;        //测量速度
        dpos2 = last_Count2 - n_Count2;

        if(dpos1 >= MAXCOUNT)
                dpos1 = dpos1 - ENCODER_TIM_PERIOD ;
        else if (dpos1 <= -MAXCOUNT)
                dpos1 =  dpos1 + ENCODER_TIM_PERIOD ;


        if(dpos2 >= MAXCOUNT)
                dpos2 = dpos2 - ENCODER_TIM_PERIOD ;
        else if (dpos2 <= -MAXCOUNT)
                dpos2 =  dpos2 + ENCODER_TIM_PERIOD ;


        dpos1 = abs(dpos1);
        dpos2 = abs(dpos2);
        if(dpos2 == 0)
        {
                if(TIM3->CR1 == 0x0011)
                        dpos = dpos1;
                if(TIM3->CR1 == 0x0001)
                        dpos = -dpos1;
        }
        if(dpos1 == 0)
        {
                if(TIM4->CR1 == 0x0011)
                        dpos = dpos2;
                if(TIM4->CR1 == 0x0001)
                        dpos = -dpos2;
        }

        if((dpos1 != 0) && (dpos2 != 0))
        {
                if(TIM4->CR1 == 0x0011)
                        dpos = dpos2;
                if(TIM4->CR1 == 0x0001)
                        dpos = -dpos2;
        }
last_Count1 = n_Count1;
        last_Count2 = n_Count2;
        last_dpos1 = dpos1;
        last_dpos2 = dpos2;        
        last_dpos = dpos;
       return dpos;



}
void TIM2_IRQHandler(void)
{
        int16_t temp;
        TIM_ClearFlag(TIM2,TIM_FLAG_Update);



        temp =         Get_Count();
        current_Count = current_Count + temp;
        flag = 1;


        

                        
}
int main()
{
        int16_t i;
        RCC_Configuration();
        TimConfig();
        NVIC_Config() ;
        DAC_Config();
        DMA_Configuration();
while(1)
                        {
                                if(flag == 1)
                                {
                                        flag = 0;
                                        if(current_Count > Distance )
                                                current_Count = Distance;
                                        if(current_Count < -Distance )
                                                current_Count = -Distance;

                                        i = current_Count;
if(i & 0x8000 != 0)
                                        {
                                                i = abs(i);
                                                i = i << 2  ;
                                        //        i=        i + 2047 ;
                                        //        i = i << 4  ;
                                        }
                                         else
                                         {
                                                 i = i << 2  ;
        }
        DAC_SetChannel1Data(DAC_Align_12b_R,i);
               
                                        DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);
                        //        }
                        
                        }
        }
}

然后输出的波形是这样的


               

0cope_0.bmp (830.05 KB )

波形输入

波形输入

使用特权

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

本版积分规则

3

主题

19

帖子

1

粉丝