led点阵屏怎么设置(玩转1616LED点阵屏)
led点阵屏怎么设置(玩转1616LED点阵屏)0x0F 0xF0 0x30 0x0C 0x44 0x22 0x44 0x22下一个要解决的问题是如何得到一个汉字的点阵信息。图11.1所示是中国象棋中的帅字,我们将一个汉字的显示区域划分成4个8×8的子区,即A区、B区、C区、D区。显而易见,可以用一个字节来代表一个子区中一行的信息,32个字节就能表示4个子区。获取点阵信息的方法也就随之产生了,我们只要按照某种顺序,依次将这些信息存入一个容量为32的数组就可以了。存取的顺序可以有多种,比如A、B、C、D或A、C、B、D等,存取顺序的不同,没有大的区别,只是影响将来的编程思路。以图11.1为例,我们按横向每行(区的顺序是A、B、C、D)的顺序取得的数据如下(C 语言的表示方式):图11.1图11.2 系统原理图当初DOS绝不是随便定下16×16,即16行与16列的标准的。在计算机世界里,8位(bit)组成一个字节(byte),而双字节则构成
在单片机发烧友圈子中,有关用单片机驱动LED、数码管、LCD等的入门文章随处可见,有关驱动LED点阵屏的文章则不多,至于真正能够显示一个国标汉字的16×16点阵屏的则更少。本文向大家介绍一款用ATmega48单片机控制16×16点阵屏显示汉字,并可做出多种动画特效的实验小系统,让你尽显编程技巧,尽情玩转16×16点阵屏这一汉字显示最小单位。
原理说明1.计算机显示汉字的基本原理
计算机显示屏上的汉字实际上是由一组有序排列的像素构成的。如果有笔画的像素不亮,而其周围的像素都是亮的,就能看到一个黑色笔画的汉字。能够清楚地显示一个汉字的最小像素数是16×16=256,这是DOS时代就定下的规矩。现在的Windows有了矢量字体,大大丰富了汉字的显示,能在屏幕上不失真地显示汉字书法的美。
现在回到16×16LED点阵屏,我们的任务是在这块方寸之地显示一个汉字,而且要能上下、左右地滚动,首先要解决的问题就是如何存放这256个汉字笔画像素的信息。
图11.1
图11.2 系统原理图
当初DOS绝不是随便定下16×16,即16行与16列的标准的。在计算机世界里,8位(bit)组成一个字节(byte),而双字节则构成一个字。于是办法有了,用两个字节共16位来代表一行的信息,16行共32个字节,用某位是0还是1来控制点亮还是熄灭对应位置的像素,就能在16×16LED屏上显示汉字,存放汉字笔画信息的问题解决了。
下一个要解决的问题是如何得到一个汉字的点阵信息。图11.1所示是中国象棋中的帅字,我们将一个汉字的显示区域划分成4个8×8的子区,即A区、B区、C区、D区。显而易见,可以用一个字节来代表一个子区中一行的信息,32个字节就能表示4个子区。获取点阵信息的方法也就随之产生了,我们只要按照某种顺序,依次将这些信息存入一个容量为32的数组就可以了。存取的顺序可以有多种,比如A、B、C、D或A、C、B、D等,存取顺序的不同,没有大的区别,只是影响将来的编程思路。以图11.1为例,我们按横向每行(区的顺序是A、B、C、D)的顺序取得的数据如下(C 语言的表示方式):
0x0F 0xF0 0x30 0x0C 0x44 0x22 0x44 0x22
A B A B A B A B
0x95 0xFD 0x95 0x25 0x95 0x25 0x95 0x25
A B A B A B A B
0x95 0x25 0x95 0x25 0x85 0x25 0x89 0x2D
C D C D C D C D
0x50 0x22 0x40 0x22 0x30 0x0C 0x0F 0xF0
C D C D C D C D
图11.3 4个8×8LED模块与单片机端口的寻址关系
2.系统原理
从图11.2的原理图中可以看出,单片机ATmega48的3个端口几乎全部用上。端口D和端口B分别控制纵向左(A区和C区)、右(B区和D区)两组8×8点阵模块的列寻址。端口C则通过一个74HC154译码器将4位地址值转换成15个行控制信号。在硬件设计上,这15个控制信号也被分成两组,分别控制横向的上(A区和B区)、下(C区和D区)两组8×8点阵模块的行寻址。
4个8×8LED模块与单片机端口的寻址关系如图11.3所示。搞清这些关系将是软件设计的基础。
硬件介绍1.单片机主控板
图11.4所示的是AVR单片机最小系统,因为引脚定义完全一致,所以可换插ATmega48/88/168/328系列单片机和ATmega8单片机。这块板子的电路图见图11.5。
图11.4 AVR单片机最小系统
图11.5 AVR单片机最小系统电路图
该板子的一个设计特点是“资源全开放”,因为ATmega48系列单片机具有引脚功能复用的特点,即所有的B端口、D端口和C端口的6个引脚通过插针全部对外开放,使用者负责定义每个引脚的工作模式和状态。例如,在你的程序中使用了串口功能,D端口的PD0 和PD1两个引脚就不能用作I/O。同理,如果系统使用了外部晶体振荡器,则PB7和PB6也不能用作他用。从图4可以看出,端口B和D都将8个引脚通过排针引了出来。而端口C的设计有些独特,不但将引脚引出,还增加了一排VCC插针和一排GND插针,这主要是为了方便接插伺服电机和众多传感器而设计的。大家知道,伺服电机3根引线的排列顺序是信号、VCC、GND,很多传感器也是如此排列3根引脚,而且端口C的引脚从0至5又具有ADC的第二功能。如此一来,需要接插伺服电机和传感器时就方便多了。板子上还提供专门的位置将串口引出。而外部晶体振荡器则通过开关控制其是否接入系统。当然,改变系统振荡源时不要忘记相关标志位的设置。ISP下载部分则是标准的10针插座,可接插多种下载器。
2. 16×16点阵屏模块
这块板子上的主要元件就是4个8×8LED模块和一只74HC154地址译码器,如图11.6所示。本文不准备详述点阵模块这种发光元件的基本原理,爱好者们可以找到很多相关文章,并参照本文前面的说明自行设计搭建。需要强调的是,要搞清模块的引脚排列,不同厂家的产品并不完全相同。另外要搞清模块是共阴的还是共阳的,这主要决定着地址译码器的选择。
图11.6 16×16点阵屏模块
本文中用到的这块板子使用的是共阳模块,就是当某列的引脚为高电位,而某行的引脚为低电位时,处于该行与该列交叉点的LED被点亮。74HC154译码器的输出为低电平有效,因此,当单片机端口B和D的某个引脚输出高电位即1时,此时74HC154译码器的某个引脚有效(输出低电平),则处于交叉点的LED被点亮。
3.系统搭建
图11.7 系统搭建方法
系统搭建非常简单,如图11.7所示。使用两根8线排缆将单片机主控板的D端口和B端口分别与16×16点阵屏的对应端口插接,用一组4线杜邦头的跳线将单片机主控板C端口的0~3 与16×16点阵屏的4位地址线接插,另用一根电源引线通过单片机主控板C端口任意一组VCC、GND插针引出接入16×16点阵屏,即可完成系统搭建。
程序所谓程序就是数据 算法。首先设计一个有效的数据结构,再根据硬件电路的寻址方式,有序地将数据送达正确的点位(算法),我们要求的图案就显示出来了。
笔者选取了几个例子与爱好者朋友分享,作为抛砖引玉,相信朋友们会设计出更丰富多彩的程序。
一个汉字垂直向上移动例程序
#include
#include
#include
#pragma data:EEPROM
//中国象棋中的帅字点阵,存储在EEPROM中
char table[]={
0x0F 0xF0 0x30 0x0C 0x44 0x22 0x44 0x22 0x95 0xFD 0x95 0x25 0x95 0x25 0x95 0x25 0x95 0x25 0x95 0x25 0x85 0x25 0x89 0x2D 0x50 0x22 0x40 0x22 0x30 0x0C 0x0F 0xF0};
#pragma data:data
//一个粗略的延时子程
void delay_1ms(void)
{
unsigned int i;
for (i=1;i < 1000;i ) ;
}
//端口初始化函数
void port_init(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x0F;
PORTD=0x00;
DDRD=0xFF;
}
void main(void)
{
char i K L;
char B_port[32];
port_init();//数据准备
for (i=0;i <32;i )
{//从EEPROM 读出数据,初始化数组B_port。
EEPROM_READ(i B_port[i]);
}
K=0;//初始化计数变量K
while(1)//无限循环
{
for(L=0;L<10;L )//滚屏速度控制
{
for(i=0;i<16;i )//点阵屏刷新
{
PORTD=B_port[i*2];//送端口D
PORTB=B_port[i*2 1];//送端口B
PORTC=i;//行寻址
delay_1ms();
}
}
//将数组中的数据都顺序向前移动一排
for (i=0;i < 29;i =2)
{
B_port[i]=B_port[i 2];
B_port[i 1]=B_port[i 3];
}
//从EEPROM中取出两个字节,填充到数组最后两个单元中
EEPROM_READ(K B_port[30]);
K ;
EEPROM_READ(K B_port[31]);
K ;
if (K >=32)//行更新计数
K=0;
}
}
1.数据准备
从本文前述关于16×16点阵汉字信息的提取,结合实例中的硬件寻址方式,大家不难想象,只要将这32个字节顺序存入一个数组,然后每两个字节为一组送往D端口和B端口形成列地址,再通过C端口给出行地址,对应行的LED将被选中,位于D、B端口字节中高电位的LED被点亮,其他的不亮,该行的点阵就形成了。如此动作16次,将32个字节依次送出,一帧(16×16点阵)的图案就显示出来了。我们只要以小于1ms的时间间隔循环做这组动作,一个汉字(或图案)就能稳定地显示在点阵屏上。
2.文字上下滚动
让汉字在16×16点阵屏上、下滚动(垂直移动)是最为简单的动作。
向右水平移动汉字例程序
#include
#include
//中国象棋中的帅字点阵,以数组形式存储在RAM中
char table[]={
0x0F 0xF0 0x30 0x0C 0x44 0x22 0x44 0x 22
0x95 0xFD 0x95 0x25 0x95 0x25 0x95 0x 25
0x95 0x25 0x95 0x25 0x85 0x25 0x89 0x 2D
0x50 0x22 0x40 0x22 0x30 0x0C 0x0F 0x F0};
//工作数组
char A_array[16][4];
//一个粗略的延时子程
void delay_1ms(void)
{
unsigned int i;
for (i=1;i < 1000;i ) ;
}
//端口初始化函数
void port_init(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x0F;
PORTD=0x00;
DDRD=0xFF;
}
//数据准备函数
void A_arr_prepare(void)
{
char i j;
for (i=0;i < 16;i )
{
j=i*2;
A_array[i][3]=table[j];
A_array[i][2]=table[j 1];
A_array[i][1]=0;
A_array[i][0]=0;
}
}
void main(void)
{
char i L;
char m0 m1 m2 m3;
//用于存储移出位的变量
port_init();
//数据准备
A_arr_prepare();
while(1)
{
for(L=0;L < 10;L )//滚屏速度控制
{
for(i=0;i<16;i )//点阵屏刷新
{
PORTD=A_array[i][1];
PORTB=A_array[i][0];
PORTC=i;
delay_1ms();
}
}
//整屏数据右移一列
for (i=0;i < 16;i )
{
if (A_array[i][0] & 0x01==1)
//保留移出位
m0=0x80;//如果是1,保留在高位。
else
m0=0;
if (A_array[i][1] & 0x01==1)
m1=0x80;
else
m1=0;
if (A_array[i][2] & 0x01==1)
m2=0x80;
else
m2=0;
if (A_array[i][3] & 0x01==1)
m3=0x80;
else
m3=0;
A_array[i][3]=A_array[i][3]>>1;//字节右移一位
A_array[i][3]=A_array[i][3] | m0;//将前一字节的高位移入
A_array[i][2]=A_array[i][2]>>1;
A_array[i][2]=A_array[i][2] | m3;
A_array[i][1]=A_array[i][1]>>1;
A_array[i][1]=A_array[i][1] | m2;
A_array[i][0]=A_array[i][0]>>1;
A_array[i][0]=A_array[i][0] | m1;
}
}
}
向上滚动时的流程图如图11.8所示,其实现程序在ICC 7平台调试通过。这个小例程使用EEPROM存储汉字点阵信息,主要是作为练习,爱好者也可以使用RAM中的数组省去EEPROM的读动作。
3. 文字左右移动
左右移动(水平横向移动)稍微复杂一些,因为要进行数据位的循环移动。在下面的例子中,我们使用一个二维数组A_array[16][4],目的是在汉字水平移动时有一个字的空格,当然你也可以试着只留半个空格或不留空格。此例程没有使用EEPROM,而是在RAM中建立一个存放点阵数据的数组table[ ]。在数据准备阶段,将数组table[ ]中的数据导入数组A_array[16][4]的后两列,即A_array[16][3]和A_array[16][2]。显示完一帧后,再对这16组4个字节向右移位,实现整帧的右移。数组A_array[16][4]的移动动作顺序如图11.9所示,该例程的流程图如图11.10所示。
图11.8 文字向上滚动的流程图
图11.9 数组A_array[16][4]的移动动作顺序
图11.10 文字向右移动的流程图
拓展练习本文仅对16×16点阵屏做一浅显介绍,相信单片机爱好者可以借助这个小平台玩出许多花样,例如对角移动、中心开花、中心会聚、对称分开或合拢,以及多字连续移动等。文中例程序是用C语言写的,也可以使用BASIC语言,里面的一些函数可以改成汇编语言的,将会显著提高效率。现在,很多爱好者玩起了Arduino,同样可以驱动这个16×16点阵屏,只是由于Arduino端口开放得不全,所以要加锁存器,并分步传送数据,程序会稍微复杂些,但基本思路是相似的。