数码管动态扫描显示_单片机数码管动态扫描显示 - CSDN
精华内容
参与话题
  • 【verilog】数码管动态扫描实现方法

    千次阅读 2019-04-16 14:55:27
    数码管动态扫描实现方法 二. 实验内容 用模块化设计,实现 16*16bit 的寄存器文件 –具备 2 组读端口及 1 组写端口 –通过读端口可从 0~15 号的任意地址读取数据 –通过写端口可向 0~15 号的任意地址写入...

     

    *博客地址转至https://xisynotz.xyz

     

    一. 实验目的

    熟练掌握时序逻辑电路的设计方法

    掌握寄存器文件的实现原理掌握

    数码管动态扫描实现方法

     

    二. 实验内容

    用模块化设计,实现 16*16bit 的寄存器文件

    – 具备 2 组读端口及 1 组写端口

    – 通过读端口可从 0~15 号的任意地址读取数据

    – 通过写端口可向 0~15 号的任意地址写入数据

    – 读写端口为“全双工”的工作方式

    – 0~15 号寄存器的复位初值依次为:“0x0000,0x1100,0x2200,...,0xFF00”

    – 通过 1 组读端口及写端口,所有寄存器的值每 0.5s 秒钟加 1

    – 通过拨动开关做为另 1 组读端口地址输入,将读出结果以16 进制显示在七段数码管上

     

    三.实验结果

    1)编写 verilog代码

    Top 模块

     

    module regfile(  
    input clk, 
    input reset_n, 
    input [3:0]addr_a, 
    input [3:0]addr_b, 
    input [3:0]addr_c, 
    input [15:0]data_c, 
    input wen_c, 
    output reg[15:0]q_a, 
    output reg[15:0]q_b 
        );  	
    reg[15:0] a0;reg[15:0] a1;reg[15:0] a2;
    reg[15:0] a3;  	
    reg[15:0] a4;
    reg[15:0] a5;
    reg[15:0] a6;
    reg[15:0] a7;  	
    reg[15:0] a8;
    reg[15:0] a9;
    reg[15:0] a10;
    reg[15:0] a11;  	
    reg[15:0] a12;
    reg[15:0] a13;
    reg[15:0] a14;
    reg[15:0] a15;  	
        always @(posedge clk or negedge reset_n) 
     	 	if(~reset_n) 	 	 	 	 	 	//复位  	 	 	
                        begin  	 	 	 	
                           a0<=16'h0000;  	 	 	 	                  
                            a1<=16'h1100;  	 	 	 	
                            a2<=16'h2200;
      	 	 	 	a3<=16'h3300;
      	 	 	 	a4<=16'h4400;
      	 	 	 	a5<=16'h5500; 
     	 	 	 	a6<=16'h6600; 
     	 	 	 	a7<=16'h7700; 
     	 	 	 	a8<=16'h8800;  
    	 	 	 	a9<=16'h9900; 
     	 	 	 	a10<=16'haa00; 
     	 	 	 	a11<=16'hbb00;
      	 	 	 	a12<=16'hcc00; 
     	 	 	 	a13<=16'hdd00;
      	 	 	 	a14<=16'hee00;
      	 	 	 	a15<=16'hff00; 
     	 	 	end 
     	 	else  	 	 	
    begin
      	 	 	 if(wen_c)
      	 	 	 	begin 
     	 	 	 	 	case(addr_c)
      	 	 	 	 	 	4'b0000: a0<=data_c; 
     	 	 	 	 	 	4'b0001: a1<=data_c; 
     	 	 	 	 	  	4'b0010: a2<=data_c; 
     	 	 	 	 	  	4'b0011: a3<=data_c; 
     	 	 	 	 	  	4'b0100: a4<=data_c; 
     	 	 	 	 	  	4'b0101: a5<=data_c; 
    	 	 	 	 	        4'b0110: a6<=data_c; 
     	 	 	 	                4'b0111: a7<=data_c;
                                          	 	4'b1000: a8<=data_c; 
    	 	 	 	                4'b1001: a9<=data_c; 
    	 	 	                       4'b1010: a10<=data_c; 
    	 	                                4'b1011: a11<=data_c; 
     	 	 	                        4'b1100: a12<=data_c;
              	 	 	 	 	4'b1101: a13<=data_c; 
                                                    4'b1110: a14<=data_c;
                                                    4'b1111: a15<=data_c;
                                                    default: a0<=0;     
                                            endcase 
     	 	 	 	 	 	q_b[15:0]<=data_c; 
     	 	 	 	end  	 	 	 	
                                        else  	 	 	 	 	
                                                 begin 
     	 	 	 	 	 	case(addr_b) 
     	 	 	 	 	 	 	4'b0000: q_b[15:0]<=a0; 
     	 	 	 	 	 	 	4'b0001: q_b[15:0]<=a1; 
     	 	 	 	 	 	 	4'b0010: q_b[15:0]<=a2; 
     	 	 	 	 	 	 	4'b0011: q_b[15:0]<=a3; 
     	 	 	 	 	 	 	4'b0100: q_b[15:0]<=a4; 
     	 	 	 	 	 	 	4'b0101: q_b[15:0]<=a5; 
     	 	 	 	 	 	 	4'b0110: q_b[15:0]<=a6; 
     	 	 	 	 	 	 	4'b0111: q_b[15:0]<=a7; 
     	 	 	 	 	 	 	4'b1000: q_b[15:0]<=a8; 
     	 	 	 	 	 	 	4'b1001: q_b[15:0]<=a9; 
     	 	 	 	 	 	 	4'b1010: q_b[15:0]<=a10; 
     	 	 	 	 	 	 	4'b1011: q_b[15:0]<=a11; 
     	 	 	 	 	 	 	4'b1100: q_b[15:0]<=a12; 
     	 	 	 	 	 	 	4'b1101: q_b[15:0]<=a13; 
     	 	 	 	 	 	 	4'b1110: q_b[15:0]<=a14; 
     	 	 	 	 	 	 	4'b1111: q_b[15:0]<=a15;
      	 	 	 	 	 	 	default: q_b[15:0]<=16'h0000; 
     	 	 	 	 	 	endcase
      	 	 	 	 	end
      	 	 	end 
     	 	always@(posedge clk or negedge reset_n)
      	 	 	if(~reset_n)
      	 	 	 	q_a[15:0]<=16'h0000;
      	 	 	else 
     	 	 	 	case(addr_a) 
     	 	 	 	 	4'b0000: q_a[15:0]<=a0; 
     	 	 	 	 	4'b0001: q_a[15:0]<=a1; 
    	 	 	 	        4'b0010: q_a[15:0]<=a2; 
     	 	                        4'b0011: q_a[15:0]<=a3;
                                          	4'b0100: q_a[15:0]<=a4; 
    	 	                        4'b0101: q_a[15:0]<=a5; 
    	 	                        4'b0110: q_a[15:0]<=a6; 
    	 	                        4'b0111: q_a[15:0]<=a7; 
    	 	                        4'b1000: q_a[15:0]<=a8; 
    	 	                         4'b1001: q_a[15:0]<=a9; 
    	 	                         4'b1010: q_a[15:0]<=a10; 
    	 	                        4'b1011: q_a[15:0]<=a11; 
    	 	                        4'b1100: q_a[15:0]<=a12; 
    	 	                        4'b1101: q_a[15:0]<=a13; 
     	 	 	 	 	4'b1110: q_a[15:0]<=a14;
      	 	 	 	 	4'b1111: q_a[15:0]<=a15;
      	 	 	 	 	default: q_a[15:0]<=16'h0000;
     	 	 	 	endcase 
    endmodule 

     

     

     

     

     

     

     

    module inc(  	input clk,  	input reset_n,  	input [15:0]q_b,  	output reg[3:0] addr_b,  	output reg[3:0] addr_c,  	output reg[15:0] data_c,  	output reg wen_c 
        );  	reg [29:0]cnt;  	reg clk0;  	always@(posedge clk or negedge reset_n)  	 	if(~reset_n)  	 	 	cnt<=0;  	 	else  	 	 	begin  	 	 	 	cnt<=cnt+1;  	 	 	 	if(cnt==100000-1) 
     	 	 	 	 	clk0<=1; 
     	 	 	 	else if(cnt==1000000-1)  	 	 	 	 	begin  	 	 	 	 	 	clk0<=0;  	 	 	 	 	 	cnt<=0;  	 	 	 	 	end  	 	 	end 
     	always@(posedge clk0 or negedge reset_n) 
    if(~reset_n) begin 
    wen_c<=0; addr_b<=0; addr_c<=0; data_c<=0; 
    end else 
     	begin  	 	if(wen_c) 
     	 	 	begin  	 	 	 	wen_c<=~wen_c;  	 	 	 	 	 	addr_b<=addr_b;  	 	 	 	 	 	if(addr_c>=4'b1111)  	 	 	 	 	 	 	addr_c<=4'b0000; 
     	 	 	 	 	 	else 
     	 	 	 	 	 	 	addr_c<=addr_c+1;  	 	 	 	 	 	 	data_c<=data_c; 
     	 	 	 	 	end  	 	 	 	else  	 	 	 	 	begin 
     	 	 	 	 	 	wen_c<=~wen_c;  	 	 	 	 	 	if(addr_b>=4'b1111)  	 	 	 	 	 	 	addr_b<=4'b0000; 
     	 	 	 	 	 	else 
     	 	 	 	 	 	 	addr_b<=addr_b+1;  	 	 	 	 	 	 	data_c<=q_b+1'b1; 
     	 	 	 	 	end  	 	 	end 
    endmodule 
    
    module seg(  	input clk,  	input reset_n,  	input [15:0]q_a,  	output reg[7:0]data,  	output reg[3:0]sel 
        );  	reg [29:0]cnt;  	reg [1:0]scn_cnt;  	reg clk0;  	always@(posedge clk or negedge reset_n) 
    if(~reset_n) 
     	cnt<=0; else begin 
    cnt<=cnt+1; 
    if(cnt==10000-1)  	clk0<=1; 
    else if(cnt==100000-1) 
     	begin  	 	clk0<=0;  	 	cnt<=0;  	end 
     	 	 	end 
     	always@(posedge clk0 or negedge reset_n)  	 	if(~reset_n)  	 	 	scn_cnt<=2'b00;  	 	else  	 	 	begin 
     	 	 	 	if(scn_cnt==2'b11)  	 	 	 	 	scn_cnt<=2'b00;  	 	 	 	else 
     	 	 	 	 	scn_cnt<=scn_cnt+1'b1; 
     	 	 	end 
     	always@(posedge clk0 or negedge reset_n)  	 	if(~reset_n)  	 	 	sel<=4'b1111;  	 	else 
     	 	 	case(scn_cnt)  	 	 	 	2'b00: 	sel<=4'b1110; 
     	 	 	 	2'b01: 	sel<=4'b1101; 
        2'b10: sel<=4'b1011;     2'b11: sel<=4'b0111;     default: sel<=4'b1111;    endcase 
     	always @(posedge clk0 or negedge reset_n)  	if(~reset_n)  	 	data=8'b11111111;  	else 
     	 	begin 
     	 	 	if(sel==4'b0111)  	 	 	 	begin 
     	 	 	 	 	case(q_a[15:12])  	 	 	 	 	 	4'h0: data=8'b00000011; 
     	 	 	 	 	 	4'h1: data=8'b10011111; 
    	 	 	 	 	4'h2: data=8'b00100101; 
    	 	 	 	 	4'h3: data=8'b00001101; 
    	 	 	 	 	4'h4: data=8'b10011001; 
     	 	 	4'h5: data=8'b01001001;  	 	4'h6: data=8'b01000001;  	 	4'h7: data=8'b00011111; 
    	 	 	4'h8: data=8'b00000001; 
     	 	4'h9: data=8'b00001001;  	 	4'ha: data=8'b00010001; 
    	 	 	4'hb: data=8'b11000001; 
    	 	 	4'hc: data=8'b01100011; 
    	 	 	4'hd: data=8'b10000101; 
     	 	 	 	 	 	4'he: data=8'b01100001;  	 	 	 	 	 	4'hf: data=8'b01110001;  	 	 	 	 	 	default: data=8'b11111111; 
     	 	 	 	 	endcase  	 	 	 	end 
     	 	 	else if(sel==4'b1011) 
     	 	 	 	begin 
     	 	 	 	 	case(q_a[11:8])  	 	 	 	 	 	4'h0: data=8'b00000011; 
     	 	 	 	 	 	4'h1: data=8'b10011111; 
     	 	 	 	 	 	4'h2: data=8'b00100101; 
     	 	 	 	 	 	4'h3: data=8'b00001101; 
     	 	 	 	 	 	4'h4: data=8'b10011001; 
     	 	 	 	 	 	4'h5: data=8'b01001001; 
     	 	 	 	 	 	4'h6: data=8'b01000001; 
     	 	 	 	 	 	4'h7: data=8'b00011111; 
     	 	 	 	 	 	4'h8: data=8'b00000001; 
     	 	 	 	 	 	4'h9: data=8'b00001001;  	 	 	 	 	 	4'ha: data=8'b00010001;  	 	 	 	 	 	4'hb: data=8'b11000001; 
     	 	 	 	 	 	4'hc: data=8'b01100011; 
     	 	 	 	 	 	4'hd: data=8'b10000101;  	 	 	 	 	 	4'he: data=8'b01100001;  	 	 	 	 	 	4'hf: data=8'b01110001;  	 	 	 	 	 	default: data=8'b11111111; 
     	 	 	 	 	endcase  	 	 	 	end 
     	 	 	else if(sel==4'b1101)  	 	 	 	begin 
     	 	 	 	 	case(q_a[7:4])  	 	 	 	 	 	4'h0: data=8'b00000011; 
     	 	 	 	 	 	4'h1: data=8'b10011111; 
    	 	 	 	 	4'h2: data=8'b00100101; 
    	 	 	 	 	4'h3: data=8'b00001101; 
    	 	 	 	 	4'h4: data=8'b10011001; 
     	 	 	4'h5: data=8'b01001001;  	 	4'h6: data=8'b01000001;  	 	4'h7: data=8'b00011111; 
    	 	 	4'h8: data=8'b00000001; 
     	 	4'h9: data=8'b00001001;  	 	4'ha: data=8'b00010001; 
    	 	 	4'hb: data=8'b11000001; 
    	 	 	4'hc: data=8'b01100011; 
    	 	 	4'hd: data=8'b10000101; 
     	 	 	 	 	 	4'he: data=8'b01100001;  	 	 	 	 	 	4'hf: data=8'b01110001;  	 	 	 	 	 	default: data=8'b11111111; 
     	 	 	 	 	endcase  	 	 	 	end 
     	 	 	else   	 	 	 	begin 
     	 	 	 	 	case(q_a[3:0])  	 	 	 	 	 	4'h0: data=8'b00000011; 
     	 	 	 	 	 	4'h1: data=8'b10011111; 
     	 	 	 	 	 	4'h2: data=8'b00100101; 
     	 	 	 	 	 	4'h3: data=8'b00001101; 
     	 	 	 	 	 	4'h4: data=8'b10011001; 
     	 	 	 	 	 	4'h5: data=8'b01001001; 
     	 	 	 	 	 	4'h6: data=8'b01000001; 
     	 	 	 	 	 	4'h7: data=8'b00011111; 
     	 	 	 	 	 	4'h8: data=8'b00000001; 
     	 	 	 	 	 	4'h9: data=8'b00001001;  	 	 	 	 	 	4'ha: data=8'b00010001;  	 	 	 	 	 	4'hb: data=8'b11000001; 
     	 	 	 	 	 	4'hc: data=8'b01100011; 
     	 	 	 	 	 	4'hd: data=8'b10000101;  	 	 	 	 	 	4'he: data=8'b01100001;  	 	 	 	 	 	4'hf: data=8'b01110001;  	 	 	 	 	 	default: data=8'b11111111; 
     	 	 	 	 	endcase  	 	 	 	end  	 	end endmodule 
    

     

    2) Ucf 文件设置

     

     

    四.实验分析

    1.本实验主要分为三个部分,寄存器文件,数码管的控制,以及加一运算实现这三个模块

    2..寄存器文件本质为一状态机

    3.对于时间上地要求,0.5s 采用统计地方式实现,达到一定地周期数后产生脉冲 

     

    在同一时刻对同一地址进行读写,会有何结果?会将时钟上升沿之前的内容读出,然后将新内容写进覆盖原先内容,因为在reg 模块中可见采用的是非阻塞赋值的方式,读写同时进行不存在先后

     

     

    展开全文
  • FPGA——数码管动态扫描(verilog)

    千次阅读 2020-07-14 20:39:11
    数码管动态扫描原理——FPGA代码1、动态扫描是利用人眼视觉滞留的特点,点亮某一位后,在人眼反应之前,进行下一位的显示,故而出现重影现象。而人的视觉暂留时间大约在1/24秒左右,所以应该保持24帧以上才会保持...

    数码管动态扫描原理——FPGA代码

    1、动态扫描是利用人眼视觉滞留的特点,点亮某一位后,在人眼反应之前,进行下一位的显示,故而出现重影现象。而人的视觉暂留时间大约在1/24秒左右,所以应该保持24帧以上才会保持连续而不会出现闪烁,通俗来讲,应该在一秒内至少扫描24次。也就是每次扫描时间至少小于40ms 。
    2、注意数码管的响应时间,一般为纳秒级,故扫描时间也不能太短。
    3、本例使用四段数码管,七段数码管译码器74LS48作为驱动。50m时钟输入,以下为载板测试后的代码。

    /*
    * Title:    <FPGA数码管动态扫描>
    * description:
    * @author:  fateszs
    * @data:    2017.12.07
    *
    */
    module hex_hum_tem(
    	output [3:0]duan,
    	output [3:0]wei,
    	
    	input reset,
    	input clock_50m,
    	input [15:0]data
    );
    	reg clock_25m;
    	always@(posedge clock_50m , negedge reset)
    	begin
    		if(!reset)
    			clock_25m <= 0;
    		else 
    			clock_25m <= ~clock_25m;
    	end
    	
    	//计数器,约为10ms扫描一次
    	reg [17:0] cnt;
    	always @(posedge clock_25m , negedge reset)
    	begin
    		if(!reset)
    			cnt <=0;
    		else if(cnt == 18'b111111111111111111)  
    			cnt <= 18'b0;
    		else
    			cnt <= cnt+1;
    	end
    	
    	//数码管位选
    	reg [3:0] wei_r,num ;
    	always @(posedge clock_25m , negedge reset)
    	begin
    		if(!reset)
    		begin
    			wei_r <= 4'b1111;
    			num <= 0;
    		end
    		else
    			case(cnt[17:16])
    			2'b00:
    				begin wei_r<=4'b1110; num <= data[3:0]; end
    			2'b01:
    				begin wei_r<=4'b1101; num <= data[7:4]; end
    			2'b10:
    				begin wei_r<=4'b1011; num <= data[11:8]; end
    			2'b11:
    				begin wei_r<=4'b0111; num <= data[15:12]; end
    			default:
    				begin wei_r<=4'b1111; num <= 0; end
    			endcase
    			
    	end
    	assign wei = wei_r;
    	
    	//数码管段选
    	reg [3:0]duan_r ;
    	always@(posedge clock_25m , negedge reset)
    	begin
    		if(!reset)
    			duan_r <= 4'b0000;
    		else
    		case(num)
    			4'd9 : duan_r <= 4'b1001;
    			4'd8 : duan_r <= 4'b1000;
    			4'd7 : duan_r <= 4'b0111;
    			4'd6 : duan_r <= 4'b0110;
    			4'd5 : duan_r <= 4'b0101;
    			4'd4 : duan_r <= 4'b0100;
    			4'd3 : duan_r <= 4'b0011;
    			4'd2 : duan_r <= 4'b0010;
    			4'd1 : duan_r <= 4'b0001;
    			4'd0 : duan_r <= 4'b0000;
    			default : duan_r <= 4'b0000;
    		endcase
    	end
    	assign duan = duan_r;
    endmodule
    	
    
    
    
    展开全文
  • 依据数码管显示原理,实现数码管动态扫描方法 运用Verilog HDL 语言的描述与建模的技巧和方法编程实现了数码管动态扫描
  • 数码管动态扫描显示01234567

    千次阅读 2013-11-24 22:24:57
    原理图:8个数码管它的数据线并联接到JP5, 位控制由8个PNP型三级管驱动后由JP8引出。 相关原理:  数码管是怎样来显示1,2,3,4呢?数码管实际上是由7个发光管组成8字形构成的,加上小数点就是8个。...

      原理图:8个数码管它的数据线并联接到JP5, 位控制由8个PNP型三级管驱动后由JP8引出。

    相关原理:

        数码管是怎样来显示1,2,3,4呢?数码管实际上是由7个发光管组成8字形构成的,加上小数点就是8个。我们分别把他命名为A,B,C,D,E,F,G,H。

         搞懂了这个原理, 我们如果要显示一个数字2, 那么 A,B,G,E,D这5个段的发光管亮就可以了。也就是把B,E,H(小数点)不亮,其余全亮。根据硬件的接法我们编出以下程序。当然在此之前,还必须指定哪一个数码管亮,这里我们就指定最后一个P2.7。
    LOOP:
    CLR P2.7 ;选中最后的数码管
    SETB P0.7 ;B段不亮
    SETB P0.5 ;小数点不亮
    SETB P0.1 ;C段不亮
    CLR P0.2 ;其他都亮
    CLR P0.3
    CLR P0.4
    CLR P0.6
    CLR P0.0
    JMP LOOP ;跳转到开始重新进行
    END
    把这个程序编译后写入单片机,可以看到数码管的最后一位显示了一个数字2。
    也许你会说:显示1个2字就要10多行程序,太麻烦了。
    显示数字2则是C,F,H(小数点)不亮,同时由于接法为共阳接法,那么为0(低电平)是亮
    为1(高电平)是灭。从高往低排列,(p0.7_p0.0)写成二进制为01111110, 把他转化为16进制则为A2H。我们可以根据硬件的接线把数码管显示数字编制成一个表格, 以后直接调用就行了。 

        有了这个表格上面显示一个2的程序则可简化为:
    LOOP:
    CLR P2.7 ;选中左边的数码管
    MOV P0,#0A2H ;送数字2的代码到P0口
    JMP LOOP ;跳转到开始重新进行
    END
         原理图中把所有数码管的8个笔划段a-h同名端连在一起,而每一个显示器的公共极COM是各自独立地受I/O线控制。CPU向字段输出口送出字形码时,所有显示器接收到相同的字形码,由8个PNP的三极管,来控制这8位哪一位工作,例如上面的例子中我们选中的是P2.7.就是最后的一位亮了. 同样的如果要第一位亮, 只需要把程序CLR P2.7改为CLR P2.0即可。
       在这里就有了一个矛盾, 所有数码管的8个笔划段a-h同名端连在一起, 那么在一个屏幕上如何显示0,1,2,3,4,5这样不同的数字呢? 的确, 在这样的接法中,同一个瞬间所有的数码管显示都是相同的, 不能显示不同的数字。在单片机里,首先显示一个数, 然后关掉.然后显示第二个数,又关掉, 那么将看到连续的数字显示,轮流点亮扫描过程中,每位显示器的点亮时间是极为短暂的(约1ms),由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位显示器并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
    例如数码管显示01234567这么8个数,在单片机中实际的工作流程如下:先打开P2.0,送0, 然后关掉P2.0,打开P2.1送1, 再关掉P2.1,打开P2.2 送2 , 依次向下,由于速度足够快, 那么我们将连续的看到01234567这8个数。
    程序运行照片:

    1、接8位数码管的数据线。将数码管部份的数据口 JP5接到CPU部份的P0口JP51.
    2、接8位数码管的显示位线。将数码管部份的显示位口 JP8接到CPU部份的P2口JP52.

    程序流程图:

    汇编语言参考程序:

    ORG 0000H
    AJMP MAIN
    ORG 0080H
    MAIN:
    CLR P2.0 ;选中第一个数码管
    MOV P0,#28H ;显示0
    LCALL DELAY ; 调用延时
    MOV P0,#0FFH ;关显示
    SETB P2.0
    CLR P2.1 ;选中第二个数码管
    MOV P0,#7EH ;显示1
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.1
    CLR P2.2 ;选中第三个数码管
    MOV P0,#0A2H ;显示2
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.2
    CLR P2.3 ;选中第四个数码管
    MOV P0,#62H ;显示3
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.3
    CLR P2.4 ;选中第五个数码管
    MOV P0,#74H ;显示4
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.4
    CLR P2.5 ;选中第六个数码管
    MOV P0,#61H ; 显示5
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.5
    CLR P2.6 ;选中第七个数码管
    MOV P0,#21H ; 显示6
    LCALL DELAY
    MOV P0,#0FFH
    SETB P2.6
    CLR P2.7 ;选中第八个数码管
    MOV P0,#7AH ; 显示7
    LCALL DELAY
    SETB P2.7
    MOV P0,#0FFH
    AJMP MAIN ;重新开始
    DELAY: ;延时子程序
    MOV R7,#2
    D1: MOV R6,#25
    D2: DJNZ R6,D2
    DJNZ R7,D1
    RET
    END
    c语言参考程序:

    #include<reg51.h> //头文件
    #define uchar unsigned char //宏定义,为方便编程
    #define uint unsigned int
    #define DIGI P0 //宏定义,将P1口定义为数码管
    #define SELECT P2 //宏定义,将P2定义为数码管选择口
    uchar digivalue[]={0x28,0x7e,0x0a2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60};
    //显示的数字数组,依次为0,1,..,9
    uchar select[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //选择数码管数组,依次选择1,2,..,8
    void delay() //延迟函数,决定数码管跳变的间隔时间

    uchar ii=200; //若发现数码管闪烁,调节这里即可
    while(ii--);
    }
    char code SST516[3] _at_ 0x003b; //仿真器插入代码
    main() //主函数
    {
    uchar i=0;
    while(1)

    for(i=0;i<8;i++) //8个数码管轮流显示
    {
    SELECT=select[i]; //选择第i个数码管
    DIGI=digivalue[i]; //显示i
    delay();

    }
    }

    展开全文
  • STM32之---数码管动态扫描

    千次阅读 2019-05-22 08:53:34
    如果按照惯例,第一个实验一般是LED流水灯,但是我相信大家的胃口绝不仅仅满足于区区一个流水灯,因此给出了一个稍微复杂一点的实验,这个实验就是通过动态扫描的方式让这8个数码管分别显示0~7这8个数字。...

           如果按照惯例,第一个实验一般是LED流水灯,但是我相信大家的胃口绝不仅仅满足于区区一个流水灯,因此给出了一个稍微复杂一点的实验,这个实验就是通过动态扫描的方式让这8个数码管分别显示0~7这8个数字。在这个实验中,大家将正式迈入STM32的开发大门。

           上图为实验的原理图,8个数码管为共阴极数码管,它们的每一段分别接在一起,分别形成了a、b、c、d、e、f、g和h这8个信号,这8个信号分别由74HC245的管脚B0~B7来控制,而74HC245 是一种三态输出、八路信号收发器,顾名思义,它可以用来发送信号,也可以用来接收信号,当管脚DIR=0时,信号从B0~B7输出到A0~A7,当管脚DIR=1时,信号从A0~A7输出到B0~B7。它的A0~A7这8个管脚分别接到STM32F103C8的PB0~PB7管脚,DIR管脚在这里固定拉高,所以信号从A0~A7输出到B0~B7;它们的位选信号分别由74LS138的Y0~Y8来控制,而74LS138是一颗译码器,输入端三个信号ABC,这三个管脚分别接到STM32F103C8的PA5、PA6和PA7上。74LS138真值表如下:

    编码输入值

    译码输出值

    C

    B

    A

    Y7

    Y6

    Y5

    Y4

    Y3

    Y2

    Y1

    Y0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    1

    0

    0

    1

    0

    0

    0

    0

    0

    0

    1

    0

    0

    1

    0

    0

    0

    0

    0

    0

    1

    0

    0

    0

    1

    1

    0

    0

    0

    0

    1

    0

    0

    0

    1

    0

    0

    0

    0

    0

    1

    0

    0

    0

    0

    1

    0

    1

    0

    0

    1

    0

    0

    0

    0

    0

    1

    1

    0

    0

    1

    0

    0

    0

    0

    0

    0

    1

    1

    1

    1

    0

    0

    0

    0

    0

    0

    0

    1、本次编程要达到的目标:让这8个数码管分别显示1~8这8个数字

    2、原理:这8个数码管的8个段位全部接在了一起,要想分别显示1~8这8个不同的数字,似乎不太可能,但是它们的位选信号是独立的,如果同一时刻只选定一位,并向该位数码管送入特定的数字,按此逐个送出特定的数字,如此一来,8个数码管就可以分别被点亮了,但是这样看到的始终只有一个数码管在亮,而不是所有的数码管同时亮,不用急,提高给每个数码管送数据的频率就可以骗过人的眼睛,让人眼看着这8个数码管都是同时分别显示8个数字。

    3、数码管动态显示的思路:

             ①送清屏段码数据,也就是让数码管不显示数据,否则当前送出去的数据很可能就是乱码,把位选信号一打开就会导致某位数码管显示乱码。

             ②通过位选信号选定特定编号的数码管,由于①步骤的存在,此时该位数码管不显示数据。

             ③将该位数码管要显示的数据送出去

             ④延迟一段时间以保证该位数码管在每轮显示周期中被点亮足够的时间,否则该位数码管最终显示的图样会比较暗。

             ⑤送清屏段码数据,否则进入到⑥的时候,刚刚被被显示的图样会在下一位数码管上被短暂显示。

             ⑥改变位选信号,使得下一位数码管开始显示属于它的数据。

             ⑦进入到③

     4、软件规划:

    ①设置好STM32F103C8的系统时钟和外设时钟。

    由于使用了GPIOA和GPIOB,因此需要将这两个端口的时钟打开,于是才有了如下的语句。

    //开启B端口的时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  

    //开启A端口的时钟       

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  

    另外,由于PB3和PB4的管脚上电复位后默认为JTAG信号脚,而PB0~PB7被用于给数码管送出显示数据,因此必须将这两个管脚复用为普通的GPIO管脚,于是才有了如下的语句:

    //如果不加这条语句程序显示就会出错,即没有打开端口复用功能的时钟配置  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

    ②设置GPIOA和GPIOB的管脚特性。数码管的段选信号和位选信号都设置为通用推挽输出,详情见smg.c的GPIOINIT函数。

    ③编写数码管驱动模块

    下面的位选编码需要参看74LS138解码器,由于编码管脚为PA5/PA6/PA7这三个管脚,//所以,编码值只是这三个脚对应的位的变化,PB[7:5]的值时从000到111这8个数值//的变化,而PB[4:0]=00000,于是才有了下面这个数组的各元素的值。

    smg.h
    
    //宏定义
    #define IS_SMGINDEX_RANGE_IN_MAX(SMGINDEX) ((SMGINDEX==0)|| \
    																					  
                                               (SMGINDEX==1)|| \
    																					  
                                               (SMGINDEX==2)|| \
    																					  
                                               (SMGINDEX==3)|| \
    																					  
                                               (SMGINDEX==4)|| \
    																					  
                                               (SMGINDEX==5)|| \
    																					  
                                               (SMGINDEX==6)|| \
    																					  
                                               (SMGINDEX==7)|| \
    																					  
                                               (SMGINDEX==8))
    																					 
    
    #define SMGDXPORT GPIOB
    #define SMGWXPORT GPIOA
    #define SMGDX GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7
    #define SMGWX GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7																					 
    																					 
    //自定义数据类型
    //定义枚举类型
    //定义结构体类型
    //定义共用体类型
    
    
    
    //函数声明
    extern void ClearSmgScreen(void);
    extern void SelSmg(u8 SmgIndex);
    extern void SendSmgDispData(u8 DispData);
    
    extern void GPIOINIT(void);
    
    
    //----------------------------------------------------------------------//
    smg.c
    
    #include"stm32f10x.h"
    #include"smg.h"
    
    u8 smgduan[]={0x3F/*0*/, 0x06/*1*/, 0x5B/*2*/, 0x4F/*3*/, 0x66/*4*/, 0x6D/*5*/, 
                      0x7D/*6*/, 0x07/*7*/,0x7F/*8*/, 0x6F/*9*/};//段选
    u8 smgwei[8]={0x00,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0}; //位选
    /******************************************/
    /*
    @function:清屏
    @input:NONE
    @output:NONE
    */
    void ClearSmgScreen(void)
    {
    	GPIO_Write(SMGDXPORT,( u16)(0));
    }
    /******************************************/
    /*
    @function:选定某位数码管
    @input:NONE
    @output:NONE
    */
    void SelSmg(u8 SmgIndex)
    {
    	assert_param(IS_SMGINDEX_RANGE_IN_MAX(SmgIndex));
    	GPIO_Write(SMGWXPORT,( u16)(smgwei[SmgIndex]));
    }
    /******************************************/
    /*
    @function:送出具体显示数据
    @input:NONE
    @output:NONE
    */
    void SendSmgDispData(u8 DispData)
    {
    	GPIO_Write(SMGDXPORT,( u16)(smgduan[DispData]));
    }
    
    void GPIOINIT()	  //端口初始化函数
    {
    /*********定义一个GPIO_InitTypeDef 类型的结构体**********/
    	GPIO_InitTypeDef GPIO_InitStructure;
    
    /*********选择要控制的GPIOx的引脚**********/
    	GPIO_InitStructure.GPIO_Pin=SMGDX;
    
    /*********设置引脚模式为通用推完输出**********/
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    
    /*********设置引脚速率为50MHZ**********/
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    
    /*初始化相应的GPIOB的设置*/
    	GPIO_Init(SMGDXPORT,&GPIO_InitStructure);
    	
    	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//把调试设置普通IO口
    
    /*********选择要控制的GPIOx的引脚**********/
    	GPIO_InitStructure.GPIO_Pin=SMGWX;
    
    /*********设置引脚模式为通用推完输出**********/
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    
    /*********设置引脚速率为50MHZ**********/
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    
    /*初始化相应的GPIOA的设置*/
    	GPIO_Init(SMGWXPORT,&GPIO_InitStructure); 	
    }
    

    ④延迟模块

    delay.h
    extern void delayms(u32 i);
    
    //---------------------------------------------------------------//
    delay.c
    #include"stm32f10x.h"
    void delayms(u32 i)
    {
    	u32 temp;
    	SysTick->LOAD=9000*i;	  //设置重装数值, 72MHZ时
    	SysTick->CTRL=0X01;		//使能,减到零是无动作,采用外部时钟源
    	SysTick->VAL=0;			//清零计数器
    	do
    	{
    		temp=SysTick->CTRL;	   //读取当前倒计数值
    	}
    	while((temp&0x01)&&(!(temp&(1<<16))));	//等待时间到达
    	SysTick->CTRL=0;	//关闭计数器
    	SysTick->VAL=0;		//清空计数器
    }

    ⑤主函数模块

    main.c
    
    #include"stm32f10x.h"
    #include"smg.h"
    #include"delay.h"
    
    void RCCINIT() //系统初始化函数
    {
    	SystemInit();
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);		  //开启B端口的时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);		  //开启A端口的时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//如果不加这条语句程序显示就会出错,即没有打开端口复用功能的时钟配置
    }
    
    int main()
    {	
    	u8 i;
    	RCCINIT();
    	GPIOINIT();
    		  
    	while(1)
    	{
    		
    		for(i=0;i<8;i++)			
    		{
    			ClearSmgScreen();
                SelSmg(i);
                SendSmgDispData(i);
    			delayms(2);
    		}
    	}	
    }
    

    5、工程结构

    6、最终显示结果

    OK,大功告成!

    展开全文
  • 数码管动态扫描显示 象棋小子 1048272975 数码管由于发光亮度强,指示效果好,非常适合于电梯楼层等数值显示应用中。对于一位数码管,可以采用静态显示,但实际应用中都是需要显示多位数值,数码管模块也只能动态...
  • I/O输出——实例3:数码管动态扫描显示一、实例目的 通过本实例,我们应: 1. 了解多位数码管的结构及引脚; 2. 了解多位数码管驱动电路; 3.掌握数码管动态扫描程序设计。 本例重点介绍多位数码管的驱动电路...
  • /*Proteus 仿真之8位共阴数码管动态扫描实验*/ 程序: /*Proteus 仿真之8位共阴数码管动态扫描实验*/ #include #define SegPort P0 //定义数码管连接端口 sbit LE_Duan = P2^0; //定义...
  • 数码管是51单片机学习中比较基础的一个模块,为简化电路连接,提高系统可靠性,降低制造成本,多位数码管广泛采用动态扫描的方式进行显示。如果程序编写不当,数码管动态扫描容易出现亮度不均匀、亮度过低、重影等...
  • 四位一体数码管介绍、扫描原理、应用电路和共阳共阴码段编写1、 数码管结构如图 1,一般7段数码管由7段条形发光二极管和一个圆点发光二极管组成,控制ABCDEFG发光二极管的亮灭,可以显示0-F字符以及其他特殊字符,...
  • 数码管动态静态显示原理

    万次阅读 2018-03-07 13:02:32
    例如共阴数码管数字0的字段码为00111111B(3FH) 共阴极:八段发光二极管的阴极端连接在一起,阳极端分开控制,使用时候公共端接地,要使哪个发光二极管亮,则对应的阳极端接高电平; 共阳极:八段发光二极管的阳...
  • 实验五 数码管显示及键盘扫描实验

    千次阅读 2019-01-10 15:42:02
    实验五 数码管显示及键盘扫描实验(2学时)  实验目的: – 掌握数码管动态显示的原理,熟悉用总线方式控制数码管显示的方法。 – 掌握矩阵键盘扫描原理,熟悉矩阵键盘与单片机的接口和编程。  实验内容及要求:...
  • Verilog HDL 之 七段数码管扫描显示

    万次阅读 多人点赞 2012-12-17 08:19:16
      原理:  一般来说,多个数码管的连接并不是把每个数码管都独立的与可编程逻辑器件连接,而是把所有的LED管的输入连在一起。如图1.1所示。... 图1.1 扫描数码管的原理图  这样做的好处有两点:一
  • proteus 数码管动态显示问题解决

    千次阅读 2017-10-30 15:46:00
    本文是解决proteus 数码管动态显示问题,具体表现如下: void display(void) //ÏÔʾ³ÌÐò { P2=table[temp_shi]; //ÏÔʾ°Ùλ A1=0;A2=1;A3=0;A4=0; delay(12); // A1=0;A2=0;A3=0;A4=0...
  • 单片机数码管重影和闪烁

    千次阅读 2016-08-02 00:31:30
    在进行数码管动态扫描时,经常出现相邻LED某些段位微亮的重影。 产生重影的原因: 由于数码管是由发光管组成的,发光管是有反应时间的,太快就会因为发光管没有来的急放电就要显示下一状态,两种状态叠加显示,就...
  • 7段八位数码管显示动态数据

    千次阅读 2018-07-23 13:15:13
    #include&lt;reg51.h&gt; // #define DataPort P2 //定义数据端口 sbit LATCH1=P1^0;//定义锁存使能端口 段锁存 sbit LATCH2=P1^1;// 位锁存 ...unsigned char code Seg_mod[]={0x3f,0x06,0x5b,0x4f,0x66,0x...
  • 好玩的单片机——数码管原理(一)

    万次阅读 多人点赞 2017-03-06 17:44:38
    数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、3位、4位、5位、6位、7位等数码管; 按发光二极管单元连接方式...
  • 8位数码管动态扫描显示变化数据

    千次阅读 2017-02-08 18:29:29
    #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换 sbit LATCH1=P2^2;//定义锁存使能端口 段锁存 ...
  • VERILOG实现四位七段数码管显示

    万次阅读 2016-03-02 09:50:52
    // //filename: dyp.v //author: lyq //Date: 2016.3.2 9:36 ...//4位七段带小数点数码管显示控制模块 // //clk: 50M //d1~d4, d[7]-dp, d[6:0]-ASCII or digit //sel[3:0]: 位选 //seg[7:0]: 段码 a~g, dp
  • 数码管串行扫描显示,有时会出现
1 2 3 4 5 ... 20
收藏数 2,884
精华内容 1,153
关键字:

数码管动态扫描显示