差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
上一修订版 两侧同时换到之后的修订记录
旋转调节系统设计 [2018/10/22 13:43]
anran [实验原理]
旋转调节系统设计 [2018/10/22 13:59]
anran [实验原理]
行 38: 行 38:
  
 {{:​4-旋转编码器电路.png?​800|旋转编码器电路}} {{:​4-旋转编码器电路.png?​800|旋转编码器电路}}
 +
 +我们使用的旋转编码器为EC11系列的,支持按动开关,共有5个管脚,
 +  * 1、2管脚支持按动开关,就像我们之前用到的独立按键连接方式,
 +  * 3、4、5管脚支持旋转编码,4脚为公共端,3、5管脚分别为旋转编码器的A、B相输出,如上图所示,我们给4脚接地,3、5管脚则需要接上拉电阻,同时为了降低输出脉冲信号的抖动干扰,我们有增加了电容到地做硬件去抖。
  
 ===旋转编码器驱动设计=== ===旋转编码器驱动设计===
 +
 +{{:​4-编码器原理示意.jpg?​500|编码器原理示意}}
 +
 +上图是机械增量式旋转编码器的原理示意图,中间圆形齿轮连接到旋转编码器的公共端4管脚,STEP BaseBoard V3.0底板上我们将之接地处理,A、B两个触点连接到旋转编码器的A、B相输出端3、5管脚,当进行旋转操作时,A、B触点会先后接触和错开圆形齿轮,从而导致A、B相输出信号产生相位不同的脉冲信号:
 +  * 顺时针旋转时,A触点超前于B触点接触和错开圆形齿轮,A信号脉冲相位超前
 +  * 逆时针旋转时,B触点超前于A触点接触和错开圆形齿轮,B信号脉冲相位超前
 +
 +{{:​4-编码器顺时针旋转时序.png?​600|编码器顺时针旋转时序}}
 +
 +{{:​4-编码器逆时针旋转时序.png?​600|编码器逆时针旋转时序}}
 +
 +根据时序图可以看出旋转编码器顺时针或逆时针旋转时,A相信号超前或滞后B相信号,FPGA接收到旋转编码器的A、B信号时,可以根据A、B的状态组合判定编码器的旋转方向。 程序设计中我们可以对A、B信号检测,检测A信号的边沿及B信号的状态,
 +  * 当A信号上升沿时B信号为低电平,或当A信号下降沿时B信号为高电平,证明当前编码器为顺时针转动
 +  * 当A信号上升沿时B信号为高电平,或当A信号下降沿时B信号为低电平,证明当前编码器为逆时针转动
 +以上就是我们旋转编码器驱动设计的总体思路,下面我们就通过编程来实现它。
 +
 +前面电路连接部分我们使用了两个电容对A、B信号作去抖处理,可以起到一定的效果,为了驱动更加稳定,我们在程序中再简单处理一下,先对系统时钟分频得到2KHz的时钟,然后在2KHz时钟的节拍下对A、B信号采样,三级锁存消除亚稳态
 +
 +对A信号采样程序实现如下(对B信号一样):
 +<code verilog>
 +reg key_a_r,​key_a_r1,​key_a_r2;​
 +//​消除亚稳态
 +always@(posedge clk_500us) begin
 + key_a_r <​= key_a;​
 + key_a_r1 <​= key_a_r;​
 + key_a_r2 <​= key_a_r1;​
 +end 
 +</​code>​
 +
 +然后简单去抖处理程序实现如下(对B信号一样):
 +<code verilog>
 +reg A_state;​
 +//​简单去抖动处理
 +always@(key_a_r1 or key_a_r2) begin
 + case({key_a_r1,​key_a_r2})
 + 2'​b11:​ A_state <= 1'b1;
 + 2'​b00:​ A_state <= 1'b0;
 + default: A_state <= A_state;
 + endcase
 +end 
 +</​code>​
 +
 +检测A信号的边沿程序实现如下:
 +<code verilog>
 +reg A_state_r,​A_state_r1;​
 +//​对A_state信号进行边沿检测
 +always@(posedge clk) begin
 + A_state_r <= A_state; ​
 + A_state_r1 <= A_state_r;
 +end
 +wire A_pos = (!A_state_r1) && A_state_r;
 +wire A_neg = A_state_r1 && (!A_state_r);​
 +</​code>​
 +
 +最后根据A信号边沿与B信号的状态组合判定旋转的信息,
 +
 +逆时针旋转脉冲输出程序实现如下:
 +
 +<code verilog>
 +//​当A的上升沿伴随B的高电平或当A的下降沿伴随B的低电平 为向左旋转
 +always@(posedge clk or negedge rst_n) begin
 + if(!rst_n) L_pulse <= 1'b0;
 + else if((A_pos&&​B_state)||(A_neg&&​(!B_state))) L_pulse <= 1'b1;
 + else L_pulse <= 1'b0;
 +end 
 +
 +//​当A的上升沿伴随B的低电平或当A的下降沿伴随B的高电平 为向右旋转
 +always@(posedge clk or negedge rst_n) begin
 + if(!rst_n) R_pulse <= 1'b0;
 + else if((A_pos&&​(!B_state))||(A_neg&&​B_state)) R_pulse <= 1'b1;
 + else R_pulse <= 1'b0;
 +end 
 +</​code>​
 +
 +所以通过上面程序最终实现了左旋右旋的脉冲输出,脉冲的脉宽等于系统时钟的周期。
  
 ===系统总体实现=== ===系统总体实现===
 +
 +回顾旋转调节系统设计框架,刚刚我们已经学习完成了旋转编码器的驱动设计,在基础数字电路实验部分我们已经掌握了FPGA驱动独立显示数码管的原理及方法, 模块通过一个4位的输入传递要显示的数值,通过9位的输出控制数码管显示该数值,这里我们不再重复,还需要设计一个模块,通过旋转编码器模块脉冲输出控制变量在0~99范围内加减变化。
 + 关于BCD码在基础数字电路实验部分已经接触过,BCD码(Binarycoded Decimal),是用4位二进制码的组合代表十进制数的码制方法,这样显示更符合人的阅读习惯,所以BCD数值变化要求满9进1。
 +
 +脉冲控制变量在0~99范围变化,左旋减,右旋加,程序实现如下
 +<code verilog>
 +//key_pulse transfer to seg_data
 +always@(posedge clk or negedge rst_n) begin
 + if(!rst_n) begin
 + seg_data <= 8'h50;
 + end else begin
 + if(L_pulse) begin
 + if(seg_data[3:​0]==4'​d0) begin
 + seg_data[3:​0] <= 4'd9;
 + if(seg_data[7:​4]==4'​d0) seg_data[7:​4] <= 4'd9;
 + else seg_data[7:​4] <= seg_data[7:​4] - 1'b1;
 + end else seg_data[3:​0] <= seg_data[3:​0] - 1'b1;
 + end else if(R_pulse) begin
 + if(seg_data[3:​0]==4'​d9) begin
 + seg_data[3:​0] <= 4'd0;
 + if(seg_data[7:​4]==4'​d9) seg_data[7:​4] <= 4'd0;
 + else seg_data[7:​4] <= seg_data[7:​4] + 1'b1;
 + end else seg_data[3:​0] <= seg_data[3:​0] + 1'b1;
 + end else begin
 + seg_data <= seg_data;
 + end
 + end
 +end
 +</​code>​
 +
 +综合后的设计框图如下:
 +
 +{{:​4-rtl设计框图.png?​800|rtl设计框图}}