LED阵列已经普遍使用在我们生活中,出去逛逛随处可见。不太清楚业内是使用什么来控制显示的,估计用单片机,毕竟便宜多了。作为一个搞电子的,一定要了解LED阵列显示。我的理解:LED阵列显示主要有两种:静态显示,滚动显示。
一:静态显示
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
else cnt1 <= cnt1+1;
end
always@(posedge clk_lk)
begin
if(cnt3==8'd70)
begin
cnt3 <= 0;
clk_h <= ~clk_h;
end
else cnt3 <= 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