两相编码器的FPGA驱动

两相编码器的驱动原理

根据A,B相的相位差,即相位的领先或落后来判断编码器转轴旋转方向,根据编码器旋转产生的脉冲来计数。
二、输出信号
1、信号序列
在这里插入图片描述
一般编码器输出信号除A、B两相(A、B两通道的信号序列相位差为90度)外,每转一圈还输出一个零位脉冲Z。
当主轴以顺时针方向旋转时,按下图输出脉冲,A通道信号位于B通道之前;当主轴逆时针旋转时,A通道信号则位于B通道之后。从而由此判断主轴是正转还是反转。
摘自:原创置顶 李逍遥~
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42562514/article/details/89435902

两相旋转编码器的FPGA驱动代码

//编码器驱动
//作者:杨成煜
//日期:2020/4/11
//==================defines=====================
`define SIM
module	encoder(
	//================System Signal================
	input				clk,
	input				rst_n,
	//================Interface====================
	input				a,
	input				b,
	output reg[31:0]	cnt
);
	//================parameters===================
	`ifndef SIM
	
	`else
	
	`endif
	localparam	S_IDLE			= 5'b00001;
	localparam	S_PLUS_CHECK	= 5'b00010;
	localparam	S_PLUS			= 5'b00100;
	localparam	S_MINUS_CHECK	= 5'b01000;
	localparam	S_MINUS			= 5'b10000;
	//================System regs==================
	reg 			a_t0;
	reg 			a_t1;
	reg 			b_t0;
	reg 			b_t1;
	reg[4:0] 		state;
	wire 			a_pedge;
	wire 			b_pedge;
	wire 			a_nedge;
	wire 			b_nedge;
	//================Main Codes===================
	//a,b  temp
	always	@(posedge clk)begin
		a_t0 <= a;
		a_t1 <= a_t0;
		b_t0 <= b;
		b_t1 <= b_t0;
	end
	assign a_pedge = a_t0&(~a_t1);
	assign a_nedge = ~a_t0&a_t1;
	assign b_pedge = b_t0&(~b_t1);
	assign b_nedge = ~b_t0&b_t1;
	//state machine
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			state <= S_IDLE;
		else case(state)
			S_IDLE:begin
				if(a_pedge==1'b1)
					state <= S_PLUS_CHECK;
				else if(b_pedge==1'b1)
					state <= S_MINUS_CHECK;
				else
					state <= S_IDLE;
			end
			S_PLUS_CHECK:begin
				if(b_pedge==1'b1)
					state <= S_PLUS;
				else if(a_pedge==1'b1)
					state <= S_IDLE;
				else
					state <= S_PLUS_CHECK;
			end
			S_PLUS:begin
				state <= S_IDLE;
			end
			S_MINUS_CHECK:begin
				if(a_pedge==1'b1)
					state <= S_MINUS;
				else if(b_pedge==1'b1)
					state <= S_IDLE;
				else
					state <= S_MINUS_CHECK;
			end
			S_MINUS:begin
				state <= S_IDLE;
			end
			default:state <= S_IDLE;
		endcase
	end
	//cnt
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			cnt <= 'd0;
		else if(state==S_PLUS)
			cnt <= cnt + 1'b1;
		else if(state==S_MINUS)
			cnt <= cnt - 1'b1;
	end	
endmodule

仿真脚本

//编码器仿真脚本
//日期:2020/4/11
//作者:杨成煜
`timescale	1ns/1ns		//时间精度
`define clock_period 20	//时钟周期
module tb_encoder;	//实体名称

//=====================<系统端口>=============================
reg				clk;
reg				rst_n;

//=====================<外设端口>=============================
reg			a;
reg 		b;
wire[31:0]	cnt;
integer		i;
integer 	j;

encoder encoder_inst(
	//================System Signal================
	.clk			(clk),
	.rst_n			(rst_n),
	//================Interface====================
	.a				(a),
	.b				(b),
	.cnt			(cnt)
);
//=====================<时钟信号>=============================
initial begin
	clk = 1;
	forever
		#(`clock_period/2)	clk = ~clk;
end

//=====================<复位信号>=============================
initial begin
	rst_n = 0;#(`clock_period*20+1);
	rst_n = 1;
end

//=====================<激励信号>=============================
initial begin
	a = 0;
	#(`clock_period*20+1);//初始化
	for(i=0;i<20;i=i+1)begin
		a=0;
		#1000;
		a=1;
		#2000;
		a=0;
		#1000;
	end
	a=0;
	#5000;
	for(i=0;i<20;i=i+1)begin
		a=0;
		#2000;
		a=1;
		#2000;
	end
end	
initial begin
	b = 0;
	#(`clock_period*20+1);
	for(j=0;j<20;j=j+1)begin
		b=0;
		#2000;
		b=1;
		#2000;
	end
	b=0;
	#5000;
	for(j=0;j<20;j=j+1)begin
		b=0;
		#1000;
		b=1;
		#2000;
		b=0;
		#1000;
	end
end

endmodule

仿真波形

正转逻辑
在这里插入图片描述
反转逻辑
在这里插入图片描述

发布了18 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43650722/article/details/105453006
今日推荐