|
下面是控制电路
当motor_a是高电平时,Q3,Q1,Q5导通,A端位高电平,B端为低电平,直流电机正转;由于Q5的集电极通过一个二极管连接到H桥的另外一个控制端motor_b,将motor_b的电压钳在1.0V以下,所以,不管motor_b输出高电平还是地电平,Q6、Q4、Q2都会截止,不会造成H桥短路;
当motor_a是低电平时,Q3,Q1,Q5截止,motor_b输出的电平可以控制电机的反转或停机。当motor_b输出高电平时,Q6,Q4,Q2导通,A端为低电平,B端为高电平,电机反转;当motor_b输出为低电平时,Q6,Q4,Q2截止;电机停机;
//程序实现的功能:利用FPGA产生PWM技术来控制直流电机的停、起;正、反转;加减速
module dc_motor
(
clk,
rst_n,
key1,
key2,
key3,
motor_a,
motor_b
);
input clk; //系统时钟 50MHZ;
input rst_n; //复位信号,低电平有效;
input key1; //控制电机加速、减速;
input key2; //控制电机启、停;
input key3; //控制电机正、反转;
output motor_a; //直流电机的两个控制端;
output motor_b;
wire[3:0] duty_ratio ; //占空比,
wire pwm_out ; //pwm输出;
wire pwm_en; //pwm使能信号;
pwm pwm
(
.clk(clk),
.rst_n(rst_n),
.duty_ratio(duty_ratio),
.pwm_en(pwm_en),
.pwm_out(pwm_out)
);
motor_control motor_control
(
.clk(clk),
.rst_n(rst_n),
.key1(key1),
.key2(key2),
.key3(key3),
.pwm_in(pwm_out),
.duty_ratio(duty_ratio),
.pwm_en(pwm_en),
.motor_a(motor_a),
.motor_b(motor_b)
);
endmodule
module pwm
(
clk,
rst_n,
pwm_en,
duty_ratio,
pwm_out
);
input clk;
input rst_n;
input pwm_en; //pwm使能信号;
input[3:0]duty_ratio; //占空比;
output pwm_out; //pwm输出;
reg[15:0] cnt; //PWM内部计数器;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt<=16'd0;
else if(pwm_en)
cnt<=cnt+1'b1;
end
reg pwm_out_r;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
pwm_out_r<=1'b0;
else if((pwm_en)&&(cnt[15:12]<=duty_ratio))
pwm_out_r<=1'b1;
else
pwm_out_r<=1'b0;
end
assign pwm_out=pwm_out_r;
endmodule
module motor_control
(
clk,
rst_n,
key1,
key2,
key3,
pwm_in,
pwm_en,
duty_ratio,
motor_a,
motor_b
);
input clk; //系统时钟 50MHZ;
input rst_n; //复位信号,低电平有效;
input key1; //控制电机加速、减速;
input key2; //控制电机启、停;
input key3; //控制电机正、反转;
input pwm_in; //pwm输入;
output pwm_en; //pwm使能;
output[3:0]duty_ratio; //占空比;
output motor_a; //直流电机的两个控制端;
output motor_b;
//键盘消抖;
reg[2:0] key_r1;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
key_r1<=3'b111;
else
key_r1<={key1,key2,key3} ;
end
reg[2:0] key_r2;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
key_r2<=3'b111;
else
key_r2<=key_r1;
end
wire[2:0] neg_key1;
assign neg_key1=(~key_r1)&key_r2; // 脉冲下降沿检测;
reg [19:0] time_cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
time_cnt<=20'd0;
else if(neg_key1) //检测到有按键按下,延时20ms;
time_cnt<=20'd0;
else
time_cnt<=time_cnt+1'b1;
end
reg[2:0] key_r3;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_r3<=3'b111;
else if(time_cnt==20'hfffff) //延时20ms后再次检测;
key_r3<={key1,key2,key3};
end
reg[2:0] key_r4;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
key_r4<=3'b111;
else
key_r4<=key_r3;
end
wire[2:0] neg_key2;
assign neg_key2=(~key_r3)&(key_r4);
//控制电机;
reg[3:0] duty_ratio_r;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
duty_ratio_r<=4'd0;
else if(neg_key2[2])
duty_ratio_r<=duty_ratio+1'b1; //电机加减速;
end
assign duty_ratio=duty_ratio_r;
reg pwm_en_r;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
pwm_en_r<=1'b0;
else if(neg_key2[1]) //电机停起;
pwm_en_r=~pwm_en_r;
end
assign pwm_en=pwm_en_r;
reg motor_dir;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
motor_dir<=1'b0;
else if(neg_key2[0])
motor_dir<=~motor_dir; //电机正反转;
end
assign motor_a=motor_dir? pwm_in:1'b0;
assign motor_b=motor_dir? 1'b0:pwm_in;
endmodule |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册
x
|