文章目录

  • 1.初识点阵LED
    • 1.1.什么是点阵LED
    • 1.2.点亮LED点阵
    • 1.3.点阵显示图案
  • 2.点阵的动画显示
    • 2.1.点阵的纵向移动
    • 2.2.点阵的横向移动

1.初识点阵LED

1.1.什么是点阵LED

LED点阵屏通过LED(发光二极管)组成,以灯珠亮灭来显示文字、图片、动画、视频等,是各部分组件都模块化的显示器件,通常由显示模块、控制系统及电源系统组成。LED点阵显示屏制作简单,安装方便,被广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。

点阵LED显示屏作为一种现代电子媒体设备,具有灵活的的显示面积(可任意的分割和拼装)、高亮度、长寿命、数字化、实时性等特点,应用非常广泛。前边学了LED小灯和LED数码管后,学习LED点阵就要轻松多了。一个数码管是由 8 个LED组成,同理,一个 8X8 的点阵就是由 64 个LED组成。如下图:

其内部结构原理图,如下图:

1.2.点亮LED点阵

从上图可知,每一行的LED的阳极(阴极)连接在一起由左侧的 8 个引脚控制(例如:第一行的LED的阳极由第 9 号引脚控制),每一列的LED的阴极(阳极)连接在一起由上侧的 8 个引脚控制。

那么如果我们把 9 号引脚置高电平、13 号引脚置低电平的话,左上角的那个LED小灯就会被点亮。我们先在proteus中建立仿真图:

#include<reg52.h>void main()
{P0 = 0 ;P2 = 0 ;while(1){P0 = ~0x01 ;P2 = 0x01 ;}
}

仿真结果如下:

我们可以看到,左上脚的LED被点亮了。从这里我们可以逐步发现点阵的控制原理了。我们前面讲了一个数码管就是 8 个 LED 小灯,一个点阵是 64 个 LED 小灯。同样的道理,我们还可以把一个点阵理解成是 8 个数码管。经过前面的学习已经掌握了 6 个数码管同时显示的方法,那 8 个数码管也应该轻轻松松了。

1.3.点阵显示图案

独立的 LED 小灯可以实现流水灯,数码管可以显示多位数字,那点阵 LED 就得来显示一点花样了。

我们要显示花样的时候,往往要先做出来一些小图形,这些小图形的数据要转换到我们的程序当中去,这个时候就需要取模软件。给大家介绍一款简单的取模软件,这种取模软件在网上都可以下载到,大家来了解一下如何使用,先看一下操作界面。

鼠标点一下“新建图形”,根据我们板子上的点阵,把宽度和高度分别改成 8,然后点确定。


点击左侧的“模拟动画”菜单,再点击“放大格点”选项,一直放大到最大,那我们就可以在我们的 8X8 的点阵图形中用鼠标填充黑点,就可以画图形了。

取模软件是把黑色取为 1,白色取为 0

大家可以看到 P0 口控制的是一行,所以用“横向取模”,如果控制的是一列,就要选“纵向取模”。选中“字节倒序”这个选项,是因为左边是低位 DB0,右边是高位 DB7,所以是字节倒序,其它两个选项大家自己了解,点确定后,选择“取模方式”这个菜单,点一下“C51 格式”后,在“点阵生成区”自动产生了 8 个字节的数据,这 8 个字节的数据就是取出来的“模”。

大家注意,虽然我们用了软件来取模,但是也得知道其原理是什么,在这个图片里,黑色的一个格子表示一位二进制的 1,白色的一个格子表示一位二进制的 0。第一个字节是 0x00,其实就是这个 8X8 图形的第一行,全黑就是 0xFF;第二个字节是 0x66,低位在左边,高位在右边,大家注意看,黑色的表示 1,白色的表示 0,就组成了 0x66 这个数值。同理其它的数据大家也就知道怎么来的了。

那么下面我们就用程序把这些数据依次送到点阵上去,看看运行效果如何。

#include<reg52.h>unsigned char i = 0;
unsigned char image[] = {0x00,0x66,0x99,0x81,0x81,0x42,0x24,0x18
};void display()
{switch(i){case 0 : P0 = 0xfe ; P2 = image[i] ;   i ++ ; break ;case 1 : P0 = 0xfd ; P2 = image[i] ;  i ++ ; break ;case 2 :    P0 = 0xfb ; P2 = image[i] ;   i ++ ; break ;case 3 : P0 = 0xf7 ; P2 = image[i] ;  i ++ ; break ;case 4 :    P0 = 0xef ; P2 = image[i] ;   i ++ ; break ;case 5 : P0 = 0xdf ; P2 = image[i] ;  i ++ ; break ;case 6 :    P0 = 0xbf ; P2 = image[i] ;   i ++ ; break ;case 7 : P0 = 0x7f ; P2 = image[i] ;  i = 0 ; break ;}
}void main()
{EA = 1 ;TMOD = 0x01; //设置 T0 为模式 1TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1msTL0 = 0x67;ET0 = 1; //使能 T0 中断TR0 = 1; //启动 T0while(1);
}void InterruptTimer0() interrupt 1
{ TH0 = 0xFC; //重新加载初值TL0 = 0x67;display();
}

对于 8X8 的点阵来说,我们可以显示一些简单的图形,字符等。但大部分汉字通常来说要用到 16X16 个点,而 8X8 的点阵只能显示一些简单笔画的汉字,大家可以自己取模做出来试试看。使用大屏显示汉字的方法和小屏的方法是类似的,所需要做的只是按照相同的原理来扩展行数和列数而已。

2.点阵的动画显示

点阵的动画显示,说到底就是对多张图片分别进行取模,使用程序算法巧妙的切换图片,多张图片组合起来就成了一段动画了,我们所看到的动画片、游戏等等,它们的基本原理也都是这样的。

2.1.点阵的纵向移动

上一节我们学了如何在点阵上画一个❤形,有时候我们希望这些显示是动起来的,而不是静止的。对于点阵本身已经没有多少的知识点可以介绍了,主要就是编程算法来解决问题了。比如我们现在要让点阵显示一个 I ❤ U 的动画,首先我们要把这个图形用取模软件画出来看一下。

这张图片共有 24 行,每 8 行组成一张点阵图片,并且每向上移动一行就出现了一张新图片,一共组成了 16 张图片。

用一个变量 index 来代表每张图片的起始位置,每次从 index 起始向下数 8 行代表了当前的图片,250ms 改变一张图片,然后不停的动态刷新,这样图片就变成动画了。首先我们要对显示的图片进行横向取模,虽然这是 16 张图片,由于我们每一张图片都是和下一行连续的,所以实际的取模值只需要 24 个字节就可以完成,我们来看看程序。

#include<reg52.h>unsigned char index = 0 , tmr = 0 ;
unsigned char i = 0;
unsigned char image[] = {0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x66,0x99,0x81,0x81,0x42,0x24,0x18,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00
};void display()
{switch(i){case 0 : P0 = 0xfe ; P2 = image[i + index] ;  i ++ ; break ;case 1 : P0 = 0xfd ; P2 = image[i + index] ; i ++ ; break ;case 2 :    P0 = 0xfb ; P2 = image[i + index] ;  i ++ ; break ;case 3 : P0 = 0xf7 ; P2 = image[i + index] ; i ++ ; break ;case 4 :    P0 = 0xef ; P2 = image[i + index] ;  i ++ ; break ;case 5 : P0 = 0xdf ; P2 = image[i + index] ; i ++ ; break ;case 6 :    P0 = 0xbf ; P2 = image[i + index] ;  i ++ ; break ;case 7 : P0 = 0x7f ; P2 = image[i + index] ; i = 0 ; break ;}
}void main()
{EA = 1 ;TMOD = 0x01; //设置 T0 为模式 1TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1msTL0 = 0x67;ET0 = 1; //使能 T0 中断TR0 = 1; //启动 T0while(1);
}void InterruptTimer0() interrupt 1
{ TH0 = 0xFC; //重新加载初值TL0 = 0x67;display();tmr ++ ;if(tmr >= 125){tmr = 0 ;index ++ ;if(index == 16)index = 0 ;}
}


大家把这个程序下载到单片机上看看效果,一个 I ❤ U 一直往上走动的动画就出现了,现在还有哪位敢说我们工科同学不懂浪漫的?还需要用什么玫瑰花取悦女朋友吗?一点技术含量都没有,要玩就玩点高科技,呵呵。

2.2.点阵的横向移动

上下移动我们会了,那我们还想左右移动该如何操作呢?

方法一:最简单,就是把板子侧过来放,纵向取模就可以完成。

这里大家是不是有种头顶冒汗的感觉?我们要做好技术,但是不能沉溺于技术。技术是我们的工具,我们在做开发的时候除了用好这个工具外,也得多拓展自己解决问题的思路,要慢慢培养自己的多角度思维方式。

那把板子正过来,左右移动就完不成了吗?当然不是。大家慢慢的学多了就会培养了一种感觉,就是一旦硬件设计好了,我们要完成一种功能,大脑就可以直接思考出来能否完成这个功能,这个在我们进行电路设计的时候最为重要。我们在开发产品的时候,首先是设计电路,设计电路的时候,工程师就要在大脑中通过思维来验证板子硬件和程序能否完成我们想要的功能,一旦硬件做好了,做好板子回来剩下的就是靠编程来完成了。只要是硬件逻辑上没问题,功能上软件肯定可以实现。

当然了,我们在进行硬件电路设计的时候,也得充分考虑软件编程的方便性。因为我们的程序是用 P0 来控制点阵的整行,所以对于我们这样的电路设计,上下移动程序是比较好编写的。那如果我们设计电路的时候知道我们的图形要左右移动,那我们设计电路画板子的时候就要尽可能的把点阵横过来放,有利于我们编程方便,减少软件工作量。

方法二:和纵向取模一样,将横向的共阴数码管看成是纵向的共阳数码管。

我们先设计如图的图案。

#include<reg52.h>unsigned char index = 0 , tmr = 0 ;
unsigned char i = 0;
unsigned char image[] = {0x81,0x81,0xFF,0xFF,0x81,0x81,0x00,0x70,0x88,0x84,0x82,0x41,0x41,0x82,0x84,0x88,0x70,0x00,0xFE,0xFF,0x03,0x03,0xFF,0xFE,
};void display()
{switch(i){case 0 : P2 = ~0xfe ; P0 = ~image[i + index] ;    i ++ ; break ;case 1 : P2 = ~0xfd ; P0 = ~image[i + index] ;   i ++ ; break ;case 2 :    P2 = ~0xfb ; P0 = ~image[i + index] ;    i ++ ; break ;case 3 : P2 = ~0xf7 ; P0 = ~image[i + index] ;   i ++ ; break ;case 4 :    P2 = ~0xef ; P0 = ~image[i + index] ;    i ++ ; break ;case 5 : P2 = ~0xdf ; P0 = ~image[i + index] ;   i ++ ; break ;case 6 :    P2 = ~0xbf ; P0 = ~image[i + index] ;    i ++ ; break ;case 7 : P2 = ~0x7f ; P0 = ~image[i + index] ;   i = 0 ; break ;}
}void main()
{EA = 1 ;TMOD = 0x01; //设置 T0 为模式 1TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1msTL0 = 0x67;ET0 = 1; //使能 T0 中断TR0 = 1; //启动 T0while(1);
}void InterruptTimer0() interrupt 1
{ TH0 = 0xFC; //重新加载初值TL0 = 0x67;display();tmr ++ ;if(tmr >= 125){tmr = 0 ;index ++ ;if(index == 16)index = 0 ;}
}


方法三:利用二维数组来实现,算法基本上和上下移动相似。

那么下面我们要进行横向做 I ❤ U 的动画了,先把我们需要的图片画出来,再逐一取模,和上一张图片类似的是,我们这个图形共有 30 张图片,通过程序每 125ms 改变一张图片,就可以做出来动画效果了。但是不同的是,我们这个是要横向移动,横向移动的图片切换时的字模数据不是连续的,所以这次我们要对 30 张图片分别取模。
最上面的图形是横向连在一起的效果,而实际上我们要把它分解为 30 个帧,
每帧图片单独取模,取出来都是 8 个字节的数据,一共就是 30X8 个数据,我们用一个二维数组来存储它们。

#include<reg52.h>unsigned char index = 0 , tmr = 0 ;
unsigned char i = 0;
unsigned char code image[30][8] = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //动画帧 1{0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F}, //动画帧 2{0xFF,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F}, //动画帧 3{0xFF,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F}, //动画帧 4{0xFF,0x0F,0x9F,0x9F,0x9F,0x9F,0x9F,0x0F}, //动画帧 5{0xFF,0x87,0xCF,0xCF,0xCF,0xCF,0xCF,0x87}, //动画帧 6{0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3}, //动画帧 7{0xFF,0xE1,0x73,0x73,0x73,0xF3,0xF3,0xE1}, //动画帧 8{0xFF,0x70,0x39,0x39,0x39,0x79,0xF9,0xF0}, //动画帧 9{0xFF,0x38,0x1C,0x1C,0x1C,0x3C,0x7C,0xF8}, //动画帧 10{0xFF,0x9C,0x0E,0x0E,0x0E,0x1E,0x3E,0x7C}, //动画帧 11{0xFF,0xCE,0x07,0x07,0x07,0x0F,0x1F,0x3E}, //动画帧 12{0xFF,0x67,0x03,0x03,0x03,0x07,0x0F,0x9F}, //动画帧 13{0xFF,0x33,0x01,0x01,0x01,0x03,0x87,0xCF}, //动画帧 14{0xFF,0x99,0x00,0x00,0x00,0x81,0xC3,0xE7}, //动画帧 15{0xFF,0xCC,0x80,0x80,0x80,0xC0,0xE1,0xF3}, //动画帧 16{0xFF,0xE6,0xC0,0xC0,0xC0,0xE0,0xF0,0xF9}, //动画帧 17{0xFF,0x73,0x60,0x60,0x60,0x70,0x78,0xFC}, //动画帧 18{0xFF,0x39,0x30,0x30,0x30,0x38,0x3C,0x7E}, //动画帧 19{0xFF,0x9C,0x98,0x98,0x98,0x9C,0x1E,0x3F}, //动画帧 20{0xFF,0xCE,0xCC,0xCC,0xCC,0xCE,0x0F,0x1F}, //动画帧 21{0xFF,0x67,0x66,0x66,0x66,0x67,0x07,0x0F}, //动画帧 22{0xFF,0x33,0x33,0x33,0x33,0x33,0x03,0x87}, //动画帧 23{0xFF,0x99,0x99,0x99,0x99,0x99,0x81,0xC3}, //动画帧 24{0xFF,0xCC,0xCC,0xCC,0xCC,0xCC,0xC0,0xE1}, //动画帧 25{0xFF,0xE6,0xE6,0xE6,0xE6,0xE6,0xE0,0xF0}, //动画帧 26{0xFF,0xF3,0xF3,0xF3,0xF3,0xF3,0xF0,0xF8}, //动画帧 27{0xFF,0xF9,0xF9,0xF9,0xF9,0xF9,0xF8,0xFC}, //动画帧 28{0xFF,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFE}, //动画帧 29{0xFF,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF} //动画帧 30
};void display()
{switch(i){case 0:  P0 = 0xfe ; i++; P2=image[index][0]; break;case 1:  P0 = 0xfd ; i++; P2=image[index][1]; break;case 2:  P0 = 0xfb ; i++; P2=image[index][2]; break;case 3:  P0 = 0xf7 ; i++; P2=image[index][3]; break;case 4:  P2 = 0xef ; i++; P2=image[index][4]; break;case 5:  P2 = 0xdf ; i++; P2=image[index][5]; break;case 6:  P2 = 0xbf ; i++; P2=image[index][6]; break;case 7:  P2 = 0x7f ; i=0; P2=image[index][7]; break;default: break;}
}void main()
{EA = 1 ;TMOD = 0x01; //设置 T0 为模式 1TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1msTL0 = 0x67;ET0 = 1; //使能 T0 中断TR0 = 1; //启动 T0while(1);
}void InterruptTimer0() interrupt 1
{ TH0 = 0xFC; //重新加载初值TL0 = 0x67;display();tmr ++ ;if(tmr >= 125){tmr = 0 ;index ++ ;if(index == 30)index = 0 ;}
}

下载进到板子上瞧瞧,是不是有一种帅到掉渣的感觉呢。技术这东西,外行人看的是很神秘的,其实我们做出来会发现,也就是那么回事而已,每 125ms 更改一张图片,每 1ms在定时器中断里刷新单张图片的某一行。

不管是上下移动还是左右移动,大家要建立一种概念,就是我们是对一帧帧的图片的切换,这种切换带给我们的视觉效果就是一种动态的了。比如我们的 DV 拍摄动画,实际上就是快速的拍摄了一帧帧的图片,然后对这些图片的快速回放,把动画效果给显示了出来。因为我们硬件设计的缘故,所以在写上下移动程序的时候,数组定义的元素比较少,但是实际上大家也得理解成是 30 张图片的切换显示,而并非是真正的“移动”。

51单片机入门——8X8点阵LED相关推荐

  1. 51单片机入门 第一篇:LED灯

    文章目录 前言 一.LED原理图 二.创建keil5工程 三.代码的编写 四.程序的烧录 总结 前言 本篇文章讲正式带大家开始学习51单片机,希望这些文章能够很好的帮助到大家学习51单片机. 一.LE ...

  2. 51单片机入门学习篇-led灯、按键、数码管、中断

    文章目录 前言 一.Proteus仿真 二.Keil代码编写 1.流水灯 2.来回点灯 3.按键操作 4.中断操作 5.数码管 6 动态数码管 三. 练习题 总结 前言 本文用来记录博主学习单片机的过 ...

  3. 51单片机(使用8x8点阵)

    2018/3/21 51单片机 1.说在前面 今天初步学会了怎样使用面包板,感觉挺好玩的,学硬件的路渐行渐远吧 2.74hc595模块(8位移位寄存器和一个存储器,三态输出功能) 1.将三位串行输入变 ...

  4. 51单片机_9-2 8x8点阵动画显示

    文章目录 要求 效果 资源 main函数 要求 1.动态显示字符串"Hello!" 效果 资源 工程文件压缩包 链接:https://pan.baidu.com/s/1FP58oM ...

  5. 51单片机入门教程(1)——点亮一个LED灯

    51单片机入门教程(1)--点亮一个LED灯 一.什么是单片机 单片机(Microcontrollers)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU.随机存储器 ...

  6. 【51单片机入门】点亮多个LED流水灯

    [51单片机&入门]点亮多个LED流水灯 实验环境 功能实现 PCB原理图 代码 要点 仿真 代码 实验环境 Keil C51 Proteus 8.9 功能实现 LED流水灯依次从右向左亮起, ...

  7. 51单片机入门:LED灯闪烁(原理图+仿真+程序)

    目录 硬件电路设计 仿真电路设计 程序设计 仿真实现 在用51单片机点亮一个LED小灯的基础上,下面尝试将一个LED灯闪烁起来. 硬件电路设计 结合51单片机最小系统的知识,利用AD19画好最小系统电 ...

  8. 51单片机入门:LED灯实现不同频率闪烁(原理图+程序+仿真)

    目录 硬件电路设计 仿真电路设计 程序设计 在上一篇文章中,我们用51单片机实现了单个LED灯的闪烁,但闪烁频率固定的.下面我们实现LED灯不同频率的闪烁! 硬件电路设计 结合51单片机最小系统的知识 ...

  9. 51单片机入门教程(5)——定时器中断

    51单片机入门教程(5)--定时器中断 一.中断的概念 二.定时器中断 2.1 软件延时的不足 2.2 中断寄存器 2.2.1 中断允许控制寄存器 IE 2.2.2 定时器工作方式寄存器 TMOD 2 ...

  10. 51单片机入门学习小结(流水灯与数码管)

    51单片机入门学习小结(流水灯与数码管) 对原理图的分析 以下是我所用单片机的原理图 这块51单片机一共有4个I/O口(意思为input/output),也代表着如果我们后续都要用到这四个的话那么功能 ...

最新文章

  1. SAP UI5库对浏览器类型检测的实现
  2. java ac自动机_如何使用Java实现AC自动机全文检索实例
  3. 回字有四样写法之引号编码
  4. tab+easyui datagrid无法正常显示
  5. 计算机本地磁盘包括,电脑中系统文件夹和本地磁盘各是什么意思?又有什么不同?...
  6. 计算机 行列式,行列式计算器
  7. nand flash 读写测试
  8. 【Spring源码学习篇(一)】☀️Spring5本地环境编译,超级实用!!✨
  9. 从技术起源看TD-SCDMA的演进
  10. 前端学习笔记之HTML body内常用标签
  11. 《视觉SLAM十四讲》笔记(1-3)
  12. 计算机文档里的圆圈,请问在WORD文档里怎样插入数字上的圆点?
  13. cocos2dx在Android studio运行 以及在 Android 平台上使用 JavaScript 直接调用 Java 方法
  14. Mybatis反射实现装载Mapper
  15. 【“BattenSnakexjp4.1”数据结构课程设计报告】
  16. 微软开放技术云浪生:微软开源.NET是民心之所向
  17. 计算机专业第五轮学科评估排名,第五轮学科评估排行榜-第二轮双一流淘汰名单预测...
  18. redis主从保证数据一致性
  19. ricky java_恕我直言你可能真的不会java第8篇-函数式接口
  20. 设备巡检管理系统的作用

热门文章

  1. 固高运动控制卡常规返回值
  2. android 微积分计算器,不到1M的良心之作 连微积分都能算的计算器APP
  3. http权威指南(一)-Http概述
  4. SQL数据库基础知识复习
  5. VB.net:VB.net编程语言学习之基于VB.net语言控制VS软件中的窗体(各种控件及其属性代码说明)的简介、案例应用(GUI界面设计代码案例)之详细攻略
  6. 单片机开发需要的工具以及软件有哪些
  7. Ubuntu+CUDA+OpenCV+Caffee安装
  8. 声道测试音频_一音成佛的尺八音色,电吹管的单声道和双声道录音对比(2)
  9. 计算机基础知识ppt操作题,计算机一级ppt操作题
  10. javascript 实现简单计算器