一:静态显示
LED阵列显示有些类似于数码管显示,都是扫描显示。这里略讲讲原理:在我们看到的LED阵列显示一个画面或是一行字,其实在硬件显示的时候,应该是一行一行或是一列一列来显示。例如8*8led阵列,在我使用过程中,显示方式是一列一列的显示,也就是先点亮第一列led,其他列都不亮,然后点亮第二列led,其他列都不亮,依次到第八列,然后又回来点亮第一列,以此循环。这样就能实现led阵列的静态显示。
二:左移或右移显示
led滚动显示是一个不容易理解的显示方式。实际使用中,可以看到,led阵列都是一行字缓慢的向左或是向右移动。
显示方法:一列一列显示。(如果是上下移动,则选择一行一行显示)
思考的方向:单独考虑每一列数值的改变,先考虑第一列在滚动显示过程中数值有哪些。
举例说明:
就像上图我们要滚动显示一个字母T,从最上面图1一直右移到最后一个图,然后又回到了图1,这就是典型的滚动循环显示。
按照上面的思考方法来做,假定最左边为第一列,最右边为第八列。首先考虑在滚动显示中第一列的数据变化:
8'h00, 8'h00, 8'h00, 8'h40, 8'h40, 8'h7e, 8'h40, 8'h40
第二列数据变化:
8'h40, 8'h00, 8'h00, 8'h00, 8'h40, 8'h40, 8'h7e, 8'h40
对比第一列数据和第二列数据,会发现第一列第一张图的数据8'h00,是第二列第二张图的数据8'h00.
由此可知:对于右移滚动循环显示,所有列的数据都是同样的,也就是,如果把列出现的所有数据存在一个数组或是库里面,所有列的数据都可以在该数组或是库取。这就诞生了网上很多字模软件,我们只要知道第一张图上面所有列的数据,然后存在一个数组里面,显示的时候只需要每一列取不同的值即可。
具体代码没有保存,故不贴出来。
三:最外围顺时针滚动显示
之所以特别说说这个显示,是因为上周末,和朋友逛校园。走到体育馆,她指着体育馆门口的led,跟我讲,最外围的那一圈一直在顺时针旋转怎么做到的。当时觉得很少见,琢磨难道是横着的设置为左右移动,竖着的设置为上下移动。接着就想,那么怎么在同一个显示中,既使用上下移动模式,又使用左右移动模式,想了很久。昨晚自己在纸上乱画了一下,发现方法还是和上面一样。
其实在旋转过程中,每一列的数据还是周期发生变化,
拿第一列(最左边一列)举例:变化的值为:8'h99, 8'h33,8'h66,8'hCC.这样就可以将问题转换到第二种显示,所以在led阵列显示中,如果是一列一列的显示,需要着重考虑每一列的数据的变化;如果是一行一行的显示,需要着重考虑的是每一行的数据变化。
verilog代码为:(其中中行为1,列为0则led亮)
//pro : 8*8 led show
//data: 2014-04-23 qs336
//info: this is a pro exe that play the show of 8*8 led
module led88(
input clk,
output reg [7:0] R,//this is row
output reg [7:0] L
);
integer cnt1,cnt2,cnt3;
reg clk_lk,clk_h;
reg [2:0] p;
reg [1:0] i;
reg [7:0] char0[3:0];
reg [7:0] char1[3:0];
reg [7:0] char2[3:0];
reg [7:0] char3[3:0];
reg [7:0] char4[3:0];
reg [7:0] char5[3:0];
reg [7:0] char6[3:0];
reg [7:0] char7[3:0];
always@(posedge clk )
begin
char0[0] <= 8'b1001_1001; char0[1] <= 8'b0011_0011; char0[2] <= 8'b0110_0110; char0[3]<= 8'b1100_1100;
char1[0] <= 8'b1000_0001; char1[1] <= 8'b1000_0000; char1[2] <= 8'b0000_0000; char1[3] <= 8'b0000_0001;
char2[0] <= 8'b0000_0000; char2[1] <= 8'b1000_0000; char2[2] <= 8'b1000_0001; char2[3] <= 8'b0000_0001;
char3[0] <= 8'b0000_0000; char3[1] <= 8'b0000_0001; char3[2] <= 8'b1000_0001; char3[3] <= 8'b1000_0000;
char4[0] <= 8'b1000_0001; char4[1] <= 8'b0000_0001; char4[2] <= 8'b0000_0000; char4[3] <= 8'b1000_0000;
char5[0] <= 8'b1000_0001; char5[1] <= 8'b1000_0000; char5[2] <= 8'b0000_0000; char5[3] <= 8'b0000_0001;
char6[0] <= 8'b0000_0000; char6[1] <= 8'b1000_0000; char6[2] <= 8'b1000_0001; char6[3] <= 8'b0000_0001;
char7[0] <= 8'b0110_0110; char7[1] <= 8'b0011_0011; char7[2] <= 8'b1001_1001; char7[3] <= 8'b1100_1100;
if(cnt1==8'd124)
begin
cnt1 <= 0;
if(cnt2==8'd199)
begin
clk_lk <= ~clk_lk;
cnt2 <= 0;
end
else cnt2 <= cnt2+1;
end
elsecnt1 <= cnt1+1;
end
always@(posedge clk_lk)
begin
if(cnt3==8'd70)
begin
cnt3 <= 0;
clk_h <= ~clk_h;
end
elsecnt3 <= cnt3+1;
if(p==3'b111) p <= 0;
else p <= p+1;
end
always@(p)
case(p)
3'b000:begin
L <= 8'b1111_1110;
R[7:0] <= char0[i];
end
3'b001:begin
L <= 8'b1111_1101;
R[7:0] <= char1[i];
end
3'b010:begin
L <= 8'b1111_1011;
R[7:0] <= char2[i];
end
3'b011:begin
L <= 8'b1111_0111;
R[7:0] <= char3[i];
end
3'b100:begin
L <= 8'b1110_1111;
R[7:0] <= char4[i];
end
3'b101:begin
L <= 8'b1101_1111;
R[7:0] <= char5[i];
end
3'b110:begin
L <= 8'b1011_1111;
R[7:0] <= char6[i];
end
3'b111:begin
L <= 8'b0111_1111;
R[7:0] <= char7[i];
end
endcase
always@(posedge clk_h)
begin
i <= i+1;
end
endmodule
其实led阵列显示有很多种方法,上面介绍的是一个很容易理解的方法,可以以此为基本来灵活改变显示方法。