找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4697|回复: 8
打印 上一主题 下一主题
收起左侧

求增量式正交旋转编码器的Verilog HDL鉴相代码

[复制链接]
跳转到指定楼层
楼主
30黑币
求增量式正交旋转编码器的Verilog HDL鉴相代码

      需要使用大约13个增量式正交旋转编码器设定值,stm32的定时器不够用,用中断需要13个中断,不太方便,stm32的引脚也不太好分配。想用EPM1270(LQFP-144)读取13个旋转编码器的值,再串行传送给stm32进行处理。
      CSDN.NET上有代码,没有帐号,且需要购买。请问哪位前辈能提供?先感谢了!



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:199427 发表于 2018-12-29 13:38 | 只看该作者
本帖最后由 wxyz 于 2018-12-29 15:04 编辑

旋转编码器的A和B分别用5.1K电阻上拉到3.3V,再用0.1uF电容对地滤波消除抖动和干扰。
借助单片机中断模式的思路:

在上升边沿触发模式下,A和B进行电平比较:
对A触发的中断:同加异减
对B触发的中断:同减异加

采用对A触发的上升沿中断模式,简单的Verilog HDL如下:

  1. always @(posedge RotaryEncoder01Aphase)  // A的上升沿
复制代码

根据以前单片机中断模式的调试经验,编码器有漏计数情况,计数不连续递增或递减,编码器的抖动干扰会造成漏计数情况。单片机可以采用延时消除抖动干扰,但Verilog HDL中不知道如何解决?




回复

使用道具 举报

板凳
ID:439075 发表于 2018-12-30 11:18 | 只看该作者
简单的代码比较好做,可能对于抖动滤波做的不好,真正的消抖效果需要靠实际环境考核才能验证。
说个简单方法,先设法获取A、B相的上升沿和下降沿,每个沿都触发同一个移位寄存器,取本次(D1、D0)及上次(D3、D2)的锁存值共四位,即D3、D2、D1、D0。判断方式为D3和D0相同(D2和D1不同)则正向,相反则为反向。这个方法你通过波形图分析就可以推导出来。
回复

使用道具 举报

地板
ID:199427 发表于 2018-12-30 15:37 | 只看该作者
谢谢 bucker 答复!没有完全理解您的思路。简单写了如下代码:


复制代码
没有测试。不知道对不对?



回复

使用道具 举报

5#
ID:199427 发表于 2018-12-30 19:18 | 只看该作者
添加代码后,排版格式乱了。再发一次。
wire A, B;
reg [1:0] ABtimes;
reg period;
reg [3:0] shift_register,  [3:0] buffer0,   [3:0] buffer1;
reg [15:0] Counter;


always @(posedge A or posedge B or negedge A or negedge B)     
begin
   ABtimes = ABtimes +1;
   shift_register[3:0] = {shift_register[2:0], 1};   //  拼接1到最低位


   if(ABtimes == 3)  //  00-01-10-11  编码器经过了 A上升、B上升、A下降和B下降四步
   begin
           if(period == 0)
           begin
                  period = 1;    // 第二个周期
                  buffer1 =  shift_register;     //  暂存第二个周期的移位寄存器值
           end
           else
           begin
                 period = 0;     // 第一个周期
                 buffer0 =  shift_register;     //  暂存第一个周期的移位寄存器值
           end
   end
     
   if((ABtimes == 3)&& (period == 1))  //  编码器经过四步和第二个周期
   begin
       if ((buffer0[3:3]==buffer1[0:0])&& (buffer0[2:2]==buffer1[1:1])) // D3和D0相同(D2和D1不同)
            Counter <= Counter + 1;
      else
            Counter <= Counter - 1;


      shift_register <=  0;   //  清零
   end  


end



回复

使用道具 举报

6#
ID:199427 发表于 2018-12-31 08:56 | 只看该作者
      if ((buffer0[3:3]==buffer1[0:0])&& (buffer0[2:2]==buffer1[1:1])) // D3和D0相同(D2和D1不同)
修改为

      if ((buffer0[3:3]==buffer1[0:0])&& (buffer0[2:2]!=buffer1[1:1])) // D3和D0相同(D2和D1不同)
回复

使用道具 举报

7#
ID:199427 发表于 2019-1-2 09:49 | 只看该作者
又看了其他的资料,大概理解了鉴相的思路,如下图所示:

通过光时,A或B为低电平。遮挡光时,A或B为高电平。A的读出值序列为1-0-0-1,B的值序列为1-1-0-0,旋转编码器为顺时针旋转。A的读出值序列为1-1-0-0,B的值序列为1-0-0-1,与顺时针值相反,旋转编码器为逆时针旋转。

回复

使用道具 举报

8#
ID:199427 发表于 2019-1-6 11:28 | 只看该作者
在《阿莫电子论坛》上找到了代码,链接如下:
www点amobbs点com/thread-840211-1-1.html


CPLD应用:光栅旋转编码器的4倍频解码

发表于 2007-10-27 10:22:55 | 只看该作者 回帖奖励
CPLD应用:增量式光栅旋转编码器的4倍频解码

刚学了几天的CPLD,上传我的第一个应用,不知道实际工作情况如何,希望高手指点指点,谢谢

如果CLK时钟频率为25Mhz,则至少可以对输出频率2.5Mhz以下增量式光栅旋转编码器的进行4倍频解码

概念如下:

增量式光栅旋转编码器分辨率:2500p/r (常用伺服系统的编码器)
按工作时最大的输出频率为2.5Mhz计算,编码器可以工作到60000r/m,当然这样的旋转速度实际上是很难达到的,实际上的常用的伺服电机最大工作到5000r/m

CLK:倍频用时钟频率
A:编码器A相
B:编码器B相

CP:解码后的脉冲
DIR:旋转方向

仿真图片如下:





Verilog hdl代码:

module decoder(CLK, A, B, CP, DIR);
        input CLK;
        input A;
        input B;
        output CP;
        output DIR;

        reg CP;
        reg DIR;

        wire a_xor_b;
        reg a_xor_b_temp;
        reg[3:0] a_xor_b_counter;


        xor (a_xor_b, A, B);        

        always @(posedge CLK)
                begin               
                if(a_xor_b_temp != a_xor_b)
                        begin
                        CP = 1'b1;
                        a_xor_b_temp = a_xor_b;                        
                        a_xor_b_counter = 4'b0000;
                        end
                else
                        begin
                        a_xor_b_counter = a_xor_b_counter + 4'b0001;
                        if(a_xor_b_counter >= 4'b0010)                 // 根据实际应用,可以改变a_xor_b_counter上限值来改变输出脉宽
                                begin
                                CP = 1'b0;
                                end                                
                        end
                end

        always @(posedge A) begin
                DIR = ~B;
        end

endmodule

不明白,为什么编码器还要外接时钟?





回复

使用道具 举报

9#
ID:328014 发表于 2019-1-10 00:29 | 只看该作者
mark帮顶下
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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