OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4644|回复: 3

编码器模式计数不准确问题求教!!!

[复制链接]

3

主题

12

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2021-5-25
在线时间
10 小时
发表于 2023-4-10 18:33:27 | 显示全部楼层 |阅读模式
20金钱
现象1:只能检测一个方向的脉冲,反向不计数现象2:引脚设置为浮空模式时,在不连接编码器的情况下,甚至是只接杜邦线的情况下,编码器会自动计数
现象3:引脚设置为上拉输入模式时,编码器接电后,在不转动的情况下依然会自动计数
现象4:定时器2在上拉输入模式下计数缓慢,跟不上转动速度,定时器3在上拉输入模式下,会自动计数。
现象5:编码器引脚在接电后,以万用电表检测脉冲引脚有±0.08v的电压跳变
现象6:编码器方向读取不准,时常出现:00010010001011010或11110111010111001,推测这是计数问题的原因之一

硬件信息:
以上用的编码器实则为拉线传感器,其内核还是增量式编码器(AB相);
传感器已送回商家检测过,对方以示波器检测,表明传感器准确无误;
单片机为STM32F103ZE核心板;也用NANO板尝试过,现象一致;

注:目前仅用多个定时器对单个拉线传感器脉冲数进行测量,并未同时测量3个编码器;

以下为代码部分:

void BianMQ_GPIO_Init()
{
       
        //                结构体
       
        GPIO_InitTypeDef                                  GPIO_InitStructure;  
        TIM_TimeBaseInitTypeDef          TIM_TimeBaseInitStructure;
        TIM_ICInitTypeDef                                        TIM_ICInitStructure;
        NVIC_InitTypeDef                                         NVIC_InitStructure;
       
        TIM_ICStructInit(&TIM_ICInitStructure);                                     //清空结构体
        TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);                     //清空结构体
       
        //                使能引脚及定时器
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);       //使能PA/B端口时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);               //使能定时器2、3、4端口时钟                               
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

        GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);                            //TIM4引脚复用
        GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);                    //TIM2引脚复用模式1               
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
//        GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);         

       
        //                引脚配置
        GPIO_StructInit(&GPIO_InitStructure);   
       
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7;                 //对应定时器3的通道1、2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;                 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;            //对应定时器4的通道1、2
        GPIO_Init(GPIOD, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                       //对应定时器2的通道1、2
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        //                定时器配置
        TIM_DeInit(TIM2);                                                                                                                                                                                //初始化
        TIM_DeInit(TIM3);
        TIM_DeInit(TIM4);

        TIM_TimeBaseInitStructure.TIM_Period=(2000-1)*4;                                        //设定计数器自动重装值
        TIM_TimeBaseInitStructure.TIM_Prescaler=0;                                                //预分频系数
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;                        //选择时钟分频:不分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;                //向上计数
       
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);                                                       
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);       
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);       

                //编码器配置
        TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);     //TIM_ICPolarity_Rising、TIM_ICPolarity_BothEdge,都尝试过,现象一致
        TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
        TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);

        TIM_ICStructInit(&TIM_ICInitStructure);                    //清空结构体
        TIM_ICInitStructure.TIM_ICFilter =10;                     //配置滤波器
        TIM_ICInit(TIM2,&TIM_ICInitStructure);
        TIM_ICInit(TIM3,&TIM_ICInitStructure);
        TIM_ICInit(TIM4,&TIM_ICInitStructure);
       

        //溢出中断设置
        NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
        NVIC_Init(&NVIC_InitStructure);
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
        NVIC_Init(&NVIC_InitStructure);
       
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );
       
        TIM_ClearFlag(TIM2,TIM_FLAG_Update);                 //清楚TIM的更新标志位
        TIM_ClearFlag(TIM3,TIM_FLAG_Update);
        TIM_ClearFlag(TIM4,TIM_FLAG_Update);
       
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
       
        //计数值清0
        TIM_SetCounter(TIM2,0);
        TIM_SetCounter(TIM3,0);
        TIM_SetCounter(TIM4,0);
       
        TIM_Cmd(TIM2,ENABLE);
        TIM_Cmd(TIM3,ENABLE);
        TIM_Cmd(TIM4,ENABLE);
               
}

/************************************************
函数名称 : ENCODER_Read
功    能 : 读取编码器数据
参    数 : Dir --- 方向
            Cnt --- 计数
返 回 值 : 无
*************************************************/
/*
void ENCODER_Read(int *Dir, int *Cnt)

{

  Dir[0]=        TIM2->CR1>>4 & 0x01;               //判断方向

  Cnt[0]= TIM_GetCounter(TIM2);              //读取计数值

}
*/


int circle_count[3]={0,0,0};                       //圈数


void TIM2_IRQHandler(void)

{

    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)       

    {      

        if((((TIM2->CR1)>>4) & 0x01)==0)                   //判断方向:DIR==0         

            circle_count[0]++;

        else if((((TIM2->CR1)>>4) & 0x01)==1)          //判断方向:DIR==1

            circle_count[0]--;

    }

    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);

}


void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
    {      
                       
        if((((TIM3->CR1)>>4) & 0x01)==0)
                                       
            circle_count[1]++;
                               
        else if((((TIM3->CR1)>>4) & 0x01)==1)
                                       
            circle_count[1]--;
                               
    }
               
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
               
}


void TIM4_IRQHandler(void)
{
       
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)
    {      
                       
        if((((TIM4->CR1)>>4) & 0x01)==0)
                                       
            circle_count[2]++;
                               
        else if((((TIM4->CR1)>>4) & 0x01)==1)
                                       
            circle_count[2]--;
                               
    }
               
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
               
}

还请各位大佬帮忙看看,已经尝试两周了,还没人指导,真找不着原因。拜谢!




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2021-5-25
在线时间
10 小时
 楼主| 发表于 2023-4-11 09:44:48 | 显示全部楼层
顶一顶!还请各位大佬赐教。
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2021-5-25
在线时间
10 小时
 楼主| 发表于 2023-4-11 15:07:14 | 显示全部楼层
再顶一顶!还请各位大佬帮忙看看。
回复

使用道具 举报

3

主题

12

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2021-5-25
在线时间
10 小时
 楼主| 发表于 2023-4-11 17:52:44 | 显示全部楼层
问题解决了,就当做是经验分享吧。

出现以上原因是:传感器(编码器)电压过大。因传感器标注的额定电压为12~24V,之前用的一直是12V电压给传感器供电,后来换成5V电压后也可以使用,且编码器读数正常。推测是单片机引脚难以接收过大的电流与电压导致编码器读数不准,而商家介绍该传感器常用PLC处理脉冲信号。也许是PLC接口能容忍更大的电压电流,而单片机不能。





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 05:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表