#FPGA(超声波测距-数码管显示)

本文详细介绍了如何在QuartusII集成开发环境中,针对CycloneIIEP2C8Q208C8NFPGA进行超声波测距实验,并利用位运算处理数据,最后通过数码管显示测量结果。包括FPGA编程步骤、计数器设计和数码管控制代码示例。
摘要由CSDN通过智能技术生成

1.IDE:Quartus II


2.设备:Cyclone II  EP2C8Q208C8N  


3.实验:超声波测距-数码管显示


4.时序图:


5.步骤:

(1)FPGA乘除运算与单片机不同,特别需要注意位宽,同时尽量转换为位运算。

(2)注意计数器cnt不是无限制,0.5S已经足够。

(3)采用cnt计数,echo上升沿记下cnt,下降沿(一次捕获结束)则进行运算距离。

(4)数码管段码引脚对应

(5)实物运行图


6.代码:

smg.v

module smg
(
input      wire          clk,
input      wire        rst_n,
input      wire [14:0]  data,

output     reg        qw,      //用于共阳极数码管控制数码管的开关(千位)
output     reg        bw,      //用于共阳极数码管控制数码管的开关(百位)
output     reg        sw,      //用于共阳极数码管控制数码管的开关(十位)
output     reg        gw,      //用于共阳极数码管控制数码管的开关(个位)
output     reg [7:0]  smg      //映射到真实引脚中
);

parameter   show_zero   = 8'b11000000;
parameter   show_one    = 8'b11111001;
parameter   show_two    = 8'b10100100;
parameter   show_three  = 8'b10110000;
parameter   show_four   = 8'b10011001;
parameter   show_five   = 8'b10010010;
parameter   show_six    = 8'b10000010;
parameter   show_seven  = 8'b11111000;
parameter   show_eight  = 8'b10000000;
parameter   show_nine   = 8'b10010000;

reg [25:0] cnt;
reg [13:0] counter;     //数码管计数值
reg [3:0]  qw_value;    //数码管千位的值
reg [3:0]  bw_value;    //数码管百位的值
reg [3:0]  sw_value;    //数码管十位的值
reg [3:0]  gw_value;    //数码管个位的值
reg [1:0]  scan_ws;     //数码管扫描位数序列号(0 个位 1 百位 2 十位 3 千位)
reg [3:0]  scan_value;  //单个位扫描值


/*
 *计数器(时基20ns 50MHz)
 */
always @ (posedge clk or negedge rst_n) begin
   if(!rst_n)
	   cnt <= 26'd0;
	else begin
	   if(cnt < 26'd50000000)
		   cnt <= cnt + 1'b1;
		else
		   cnt <= 26'd0;
	end
	
end

/*
 *定时器(1s),用于数码管显示
 */
always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) 
		counter <= 14'd0;
   
	else if(cnt == 26'd50000000) begin
	   if(counter < 14'd9999) 
		   counter <= counter +1'b1;
      else
         counter <= 14'd0;
	end

end
		

/*
 *选择打开的数码管
 */
always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
		  qw <= 1'b1;
		  bw <= 1'b1;
		  sw <= 1'b1;
		  gw <= 1'b1;
	     scan_value <= 4'd0;
   end
   else if(!(cnt % 26'd200000)) begin      //4ms 
        bw <= 1'b1;                        //全关(因为程序执行中会打开部分数码管,每次单位数码管扫描前先关闭所有数码管)
        sw <= 1'b1;
        gw <= 1'b1;
        qw <= 1'b1;
		  case(scan_ws)                     //决定打开哪个数码管
		     2'b00  : begin
			  scan_value <= gw_value;
           gw <= 1'b0;			   
			  end                                     
			  2'b01  : begin                         
			  scan_value <= sw_value;                 
			  sw <= 1'b0;
			  end
			  2'b10  : begin
			  scan_value <= bw_value;
			  bw <= 1'b0;
			  end
			  2'b11  : begin
			  scan_value <= qw_value;
			  qw <= 1'b0;
			  end
			  default : ;
		  endcase
	end 
end

/*
 *向数码管写入数据
 */
always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
	   smg <= show_zero;
	end
   else begin
	    case(scan_value)            
          4'd0 : smg <= show_zero;
          4'd1 : smg <= show_one;
          4'd2 : smg <= show_two;
          4'd3 : smg <= show_three;
          4'd4 : smg <= show_four;
          4'd5 : smg <= show_five;
          4'd6 : smg <= show_six;
          4'd7 : smg <= show_seven;
          4'd8 : smg <= show_eight; 
          4'd9 : smg <= show_nine;  
          default : ;
		 endcase 
	end
end	
	

/*
 *扫描位号赋值
 */
always @ (posedge clk or negedge rst_n) begin
       if(!rst_n)
		  scan_ws <= 2'b00;
       else if(!(cnt % 26'd200000)) begin         //到达刷新时间
		  if(scan_ws == 2'b11)
		     scan_ws <= 2'b00;
		  else
		     scan_ws <= 2'b01 + scan_ws;
		 end
		 else
		     scan_ws <= scan_ws ;
end

/*
 *向扫描值千百十个位赋值
 */
always @ (posedge clk or negedge rst_n) begin
       if(!rst_n) begin
			qw_value <= 4'd0;
			bw_value <= 4'd0;
			sw_value <= 4'd0;
			gw_value <= 4'd0;
		 end
		 else begin
		   qw_value <= data/10'd1000;
		   bw_value <= data/7'd100%4'd10;
		   sw_value <= data/4'd10%4'd10;
		   gw_value <= data%4'd10;
		 end
end		   


		 
 
endmodule
	 

 csbcj.v

/*
 *超声波模块代码
 */
module csbcj(
input  wire sys_clk        ,
input  wire sys_rst_n      ,
input  wire echo           ,

output reg  trig           ,
output reg [29:0]   distance      
);

reg   [24:0]            cnt     ;
reg   [24:0]      echo_rise_cnt ;     //用于记录上升沿时刻



parameter  half_second_cnt = 25'd25_000_000;   //0.5s触发一次
parameter  trig_max = 9'd500;                 //10us

/*
 *触发控制
 */
always @ (posedge sys_clk or negedge sys_rst_n) begin
     if(sys_rst_n == 1'b0)
	      trig <= 1'b0 ;
	  else if(cnt == 25'd0)       //0.5s触发一次   
			trig <= 1'b1 ;               
	  else if(cnt == trig_max || echo == 1'b1)
	      trig <= 1'b0 ;
	  else
	      trig <= trig ;
end

/*
 *echo下降沿(完成一次接收)
 */
always @ (negedge echo) begin
		distance <= (cnt-echo_rise_cnt)* 25'd34 / 25'd10_0000 ;
end

/*
 *echo上升沿
 */
always @ (posedge echo) begin
       echo_rise_cnt <= cnt ;
end

/*
 *0.5秒计数器
 */
always @ (posedge sys_clk or negedge sys_rst_n) begin
         if(sys_rst_n == 1'b0)
              cnt <= 25'd0;
         else if(cnt == half_second_cnt)              //0.5s
              cnt <= 25'd0;
		   else
              cnt <= cnt + 1'b1;	  
end


endmodule

show_distance.v

module show_distance(

input  wire sys_clk            ,
input  wire sys_rst_n          ,
input  wire echo               ,
output wire  trig              ,

output wire  qw                ,
output wire  bw                ,
output wire  sw                ,
output wire  gw                ,
output wire  [7:0]   smg      
);

wire [29:0]  distance  ;

csbcj csbcj_inst(
.sys_clk                     (sys_clk         ),
.sys_rst_n                   (sys_rst_n       ),
.echo                        (echo            ),
                     
.trig                        (trig            ),
.distance                    (distance        )
);


smg smg_inst
(
.     clk                    (sys_clk         ),
.     rst_n                  (sys_rst_n       ),
.     data                   (distance        ),

.     qw                     (qw  ),
.     bw                     (bw  ),
.     sw                     (sw  ),
.     gw                     (gw  ),
.     smg                    (smg )
);

			
endmodule


  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值