|
用Verilog 处理正交编码器的计数。 长时间计数后发现计数器不准确了。。。
4倍频鉴相处理 :
module Phase(
clk, //时钟。8MHZ
lnA, //A相
lnB, //B相
clk_o, //输出的时钟
ph //输出相位 (正向或反向)
);
input clk; //8MHZ
input lnA,lnB; //
output reg clk_o,ph;//
reg [1:0] state1;
reg [1:0] state0;
reg [3:0] wide_counter; //输出脉宽控制.
always @(posedge clk) //上升沿处理
begin
state0 <= {lnA,lnB};
state1 <= state0;
case( {state1,state0} )
4'b0010,//B=0,A 0->1
4'b1011,//A=1,B 0->1
4'b1101,//B=1,A 1->0
4'b0100://A=0,B 1->0
begin
clk_o <= 1;
ph <= 0;
wide_counter <= 0;
end
4'b0001,//A=0,B 0->1
4'b0111,//B=1,A 0->1
4'b1110,//A=1,B 1->0
4'b1000://B=0,A 1->0
begin
clk_o <= 1;
ph <= 1;
wide_counter <= 0;
end
endcase
/////////////////////////////////////////////////////
if( clk_o )
begin
wide_counter <= wide_counter + 1;
if( wide_counter == 7) //让高电平保持N个时钟周期
begin
clk_o <= 0;
wide_counter <= 0;
end
end
end
endmodule
计数器:
module ECounter(
Clk, //时钟 8MHZ
cp, //鉴相输出的脉冲输入
ph, //鉴相输出的相位输入
Z, //编码器零点(Z相)
en, //使能
reset,//复位
write,//写初始标志
DI, //输入数据
DO //计数器输出
);
input Clk;
input cp,ph,Z,en,reset;
input write;
input [15:0] DI;
output reg [15:0] DO;
reg [2:0] cp_buf;
wire cp_flag;
reg [1:0] reset_buf;
wire reset_flag;
reg [1:0] Z_buf;
wire Z_flag;
//同步cp,reset,z 三个信号
always @(posedge Clk)
begin
cp_buf <= {cp_buf[1:0],cp};
reset_buf <= {reset_buf[0],reset};
Z_buf <= {Z_buf[0],Z};
end
assign cp_flag = cp_buf[0] & cp_buf[1] & !cp_buf[2];//0->1
assign reset_flag = !reset_buf[0] & reset_buf[1]; //1->0
assign Z_flag = !Z_buf[0] & Z_buf[1]; //1->0
always @(posedge Clk)
begin
if( reset_flag )
DO <= 0;
else if( Z_flag) //Encode Z pos
begin
//这里是编码器机械零位! 可以点做什么处理 呢?
end
else if( write )
DO <= DI;//写入初值
else if(cp_flag && en)
begin
if( ph ) //正向
DO <= DO + 1;
else //反向
DO <= DO - 1;
end
end
endmodule
测试方法, 接入编码器不停的转动,有正转,也有反转。。。 记位一个位置记下当前的计数器值。
运行一个晚上后。 转回原来标志的位置。
发现计数值不对了! 偏差了很多。。。。
如果短时间运行, 偏差分辨不出来。。。 长时间后累积多了就看到了。
估计是正反变换时丢失了某些脉冲没有记数!
请大家帮分析一下从什么地方下手才可以提高可靠性? |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|