OpenEdv-开源电子网

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

增量式编码器如何辨别转动方向

[复制链接]

18

主题

64

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
383
金钱
383
注册时间
2015-11-1
在线时间
49 小时
发表于 2019-9-14 10:04:11 | 显示全部楼层 |阅读模式
5金钱
请问各位大佬,我想了解下增量式编码器判别方向的问题。
增量型编码器通常有三路信号输出(差分有六路信号):A、B和Z,一般采用TTL电平,A脉冲在前,B脉冲在后,A、B脉冲相差90度,每圈发出一个Z脉冲,可作为参考机械零位。一般利用A超前B或B超前A进行判向。我们通过A和B脉冲来辨别方向,通过Z脉冲来辨别圈数。
请问大佬,这个在代码领域如何应用?有给予思路和参考的么?



3.jpg
2.jpg

1

1

最佳答案

查看完整内容[请看2#楼]

以下代码是基于STM32定时器模式的代码, /******************************************************************************************* 函 数 名: 定时器3编码器模式初始化函数 调 用: TIM3_BMQMS_Init(u8 remap) 参 数: reamap 复用功能重映像 00,01,11 如果参数错误,则采用00参数 反 回 值: 无 说 明: 初始化编码器的AB信号接于 CH1,CH2上 四倍频输出 如果计数脉冲小于+- 32768 则可以不需要中 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2019-9-14 10:04:12 | 显示全部楼层
以下代码是基于STM32定时器模式的代码,
/*******************************************************************************************
函 数 名: 定时器3编码器模式初始化函数
调    用: TIM3_BMQMS_Init(u8 remap)
参    数: reamap 复用功能重映像 00,01,11 如果参数错误,则采用00参数
反 回 值: 无
说    明: 初始化编码器的AB信号接于 CH1,CH2上 四倍频输出
          如果计数脉冲小于+- 32768 则可以不需要中断处理,初始化计数器初值为32769
          取值时  Cnt = TIM3->CNT - 32768 就行了
********************************************************************************************/  
void TIM3_BMQMS_Init(u8 remap)
     {            
     switch(remap)//IO接器重映像处理
           {
           case 2: { //TM3_REMAP[1,0] = 10
                   RCC->APB2ENR |= 1<< 0;              //开启辅助功能时钟
                   BIT_ADDR((u32)& AFIO->MAPR,11) = 1; //高电平   
                   BIT_ADDR((u32)& AFIO->MAPR,10) = 0; //高电平  
                   RCC->APB2ENR |= 1<<3;               //使能PORTB时钟     
                   GPIOB->CRL &= 0xFF00FFFF;           //PB4,PB5
                   GPIOB->CRL |= 0x00440000;           //浮空输入                     
                   }break;
           case 3: {//TM3_REMAP[1,0] = 11
                   RCC->APB2ENR |= 1<< 0;              //开启辅助功能时钟
                   BIT_ADDR((u32)& AFIO->MAPR,11) = 1; //高电平   
                   BIT_ADDR((u32)& AFIO->MAPR,10) = 1; //高电平
                   RCC->APB2ENR |= 1<<4;               //使能PORTC时钟     
                   GPIOC->CRL &= 0x00FFFFFF;           //PC6,PC7
                   GPIOC->CRL |= 0x44000000;           //浮空输入  
                   }break;
           default:{////TM3_REMAP[1,0] = 00
                   RCC->APB2ENR |= 1<<2;               //使能PORTA时钟     
                   GPIOA->CRL &= 0x00FFFFFF;           //PA6,PA7
                   GPIOA->CRL |= 0x44000000;           //浮空输入  
                   }break;           
           }
     BIT_ADDR((u32)& RCC->APB1ENR,1) = 1;   //TIM3时钟使能         
     BIT_ADDR((u32)& RCC->APB1RSTR,1) = 1;  //复位TIM3定时器,使之进入初始状态
     BIT_ADDR((u32)& RCC->APB1RSTR,1) = 0;  //结束复位   
    // BIT_ADDR((u32)& TIM3->DIER,0) = 1;     //允许定时器更新中断                                   
     TIM3->PSC = 0;                         //预分频器,不分频
    // TIM3->ARR = ENCODER_TIM_PERIOD;        //设定计数器自动重装值   
     TIM3->CR1 &=~(3<<8);                   //选择时钟分频:不分频(在输入捕获中止参数无效)
     TIM3->CR1 &=~(3<<5);                   //选择计数模式:中央对齐模式(向上或向下计数)
     TIM3->CCMR1 |= 1<<0;                   //CC1S='01' IC1FP1映射到TI1
     TIM3->CCMR1 |= 1<<8;                   //CC2S='01' IC2FP2映射到TI2      
     TIM3->CCER &= ~(1<<1);                 //CC1P='0'        IC1FP1不反相,IC1FP1=TI1
     TIM3->CCER &= ~(1<<5);                 //CC2P='0'        IC2FP2不反相,IC2FP2=TI2
     TIM3->CCMR1 |= 3<<4;                   //IC1F='1000' 输入捕获1滤波器(可能影响采集响应速度)
     TIM3->SMCR |= 3<<0;                    //SMS='011' 所有的输入均在上升沿和下降沿有效(四倍频的输出)
     //TIM3->CNT = COUNTER_RESET;           //计数器的初值
     //CONSTER_DATA = COUNTER_RESET;        //清零中断计数累加器的值为初始值   
     //CHUCHANGZHI = 0;   
     TIM3->CNT = ENCODER_TIM_PERIOD;        //计数器的初值        
     //MY_NVIC_Init(0,0,TIM3_IRQn,4);         //抢占0,子优先级0,组4 设定时器3更新中断为最高级别中断  
     TIM3->CR1 |= 0x01;                     //CEN=1,使能定时器
     }     
/*******************************************************************************************
函 数 名: 定时器3中断函数
调    用: 无
参    数: 无
反 回 值: 无(这里在编码器模式中CPU唯于需要处理的函数)
说    明: 在编码器模式中,当计数方式设为中央模式时,控制寄存器的DIR位为只读, 在中断中读取该位
          的值来判断是向下或向上计数中断,累加编码器的计数值
********************************************************************************************  
void TIM3_IRQHandler(void)
     {              
     if(TIM3->SR&0x0001)//溢出中断
       {
       if(TIM3->CR1&0x10){CONSTER_DATA += ENCODER_TIM_PERIOD; CHUCHANGZHI= 1;} //向下计数                    
       else CONSTER_DATA -= ENCODER_TIM_PERIOD; //向上计数            
       }
     TIM3->SR&=~(1<<0);//清除中断标志位        
     }  
回复

使用道具 举报

4

主题

22

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
258
金钱
258
注册时间
2015-7-30
在线时间
60 小时
发表于 2019-9-14 16:42:22 | 显示全部楼层
可以采用定时器的编码器模式,通过比较定时器计数方向(递增or递减)来判断是正转还是反转。
ps:最近也在找资料,写驱动。
欢迎一起讨论,学习
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2019-9-15 10:09:27 | 显示全部楼层
本帖最后由 likunxue 于 2019-9-15 10:13 编辑

以下代码是当初用C51做试验的代码, 在中断中读取编码器的状态来做处理, 对现理编码器的计数及方向识别有一定的参考作用
试验中编码器接到P0口上
/*********************************************************************************************
函数名:记数器中断处理函数
调  用:无
参  数:无
返回值:无
结  果:完成编码器的采集工作,记录编码器的位置状态
/**********************************************************************************************/
void name(void) interrupt 1
     {
     unsigned char Bul, k,Cal;
     BCLK_STT =~ BCLK_STT;
     Bul = P0;
     Cal = Bul&0x03;//取得当前光电编码器输入状态值
     if(Cal != ShuChuZhuangTai)
       {
       k = (ShuChuZhuangTai << 2 )+ Cal;//得到4倍频编码输入状态值
       switch(k)
             {
             case 0x07:WeiZhiJiShuQi++;break;
             case 0x0E:WeiZhiJiShuQi++;break;
             case 0x08:WeiZhiJiShuQi++;break;
             case 0x01:WeiZhiJiShuQi++;break;
             case 0x0D:WeiZhiJiShuQi--;break;
             case 0x04:WeiZhiJiShuQi--;break;
             case 0x02:WeiZhiJiShuQi--;break;
             case 0x0B:WeiZhiJiShuQi--;break;
             }
       ShuChuZhuangTai = Cal; //输入状态存副本
       }
     Cal =(Bul>>2)&0x03;      //得到当前输入脉冲的状态值
     if(Cal != MaiChongZhuangTai) //如果与前一状态不同,则认为有变化
       {
       Tim_CLK = 100;         //重置延迟时间
       switch(Cal)
             {
             case 0:{MCCW = 0; MCLK = 0;}break;
             case 1:{MCCW = 1; MCLK = 0;}break;
             case 2:{MCCW = 0; MCLK = 1;MaiChongJiShuQi--;}break;
             case 3:{MCCW = 1; MCLK = 1;MaiChongJiShuQi++;}break;
             }
       MaiChongZhuangTai = Cal; //当前状态存副本
       }
     if(Tim_LED != 0)Tim_LED --;
     if(Tim_CLK != 0) Tim_CLK --;
     }
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-9 10:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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