数组的基本定义
1:具有相同的数据类型。
2:具有相同的名字。
3:在存储器中是被连续存放的
数组的初始化
数据类型 数组名[数组长度] = [初值列表]
举例:unsigned char LedChar[8] ={0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF,}
1:初值列表里的数据之间要用逗号隔开,最后一个逗号可以取消
2:初值列表里的初值数量必须等于或者小于数组长度,当小于数组长度时,数组的后面没有赋值的元素由系统自动赋值为0.
3:若给数组的所有元素都赋初值,可以省略数组的长度
上例可写成unsigned char LedChar[] ={0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF};
4:系统为数组分配连续的存储单元的时候,数组元素的相对次序由下标来决定,就是LedChar[0]
LedChar[1]......LedChar[7],按照顺序依次排下来的,注意第1位下标是从0开始的最后一位的下标是数组长度减1,如上述最后一位数0xFF的定位是 LedChar[7]
对于数组LedChar[],如果没加code关键字,这个数组里的数据是既可读也可写的,即
它可以是a = LedChar[0]这是把数组的第一个元素赋值给a这个变量,也可以写成 LedChar[0] = a;
把a这个变量的值送给数组中的第一个元素,即数组现在的值是
LedChar[] = {a,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF,};
即可读可写,如果加上code关键字
unsigned char code LedChar[] ={0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF} ;这个数组就只能读取不能写入了。
二维数组的声明方式是:
数组类型 数组名[数组长度1][数组长度2] ;
与一维数组类似,数据类型是全体元素的数据类型,数组名是标识符,数组长度1和数组长度2分别代表数组具有的行数和列数,数组元素的下表一律从0开始。例如
unsigned char LedChar[2][4] 声明一个2行4列的无符号字符型的二维数组。
则unsigned char LedChar[2][4] = { {0xF7,0xF6,0xB6,0xB6 },
{0xB6,0xB6,0x80,0xFF}
};
二维数组的元素总个数是两个长度的乘积,二维数组在内存中存储的时候,采用行优先的方式来存储,即在内存中先存放第0行的元素,再存放第一行的元素......,同一行中再按照顺序存放。
物理存储结构;LedChar[0][0] LedChar[0][1] LedChar[0][2] LedChar[0][3 LedChar[1][0] LedChar[1][1] LedChar[1][2] LedChar[1][3]
变量的作用域
所谓的作用域就是指变量起作用的范围,也是变量的有效范围,变量按照作用域可以分为局部变量和全局变量
1:局部变量是在一个函数内声明的变量。它只在本函数内有效,在本函数外不起作用。
2; 全局变量是在函数外声明的变量,一个源程序文件可以包含一个或者多个函数,全局变量的作用范围是从它开始声明的位置一直到程序结束。
1:全局变量可以被作用域内所有的函数直接引用
2:全局变量的应用会降低函数的通用性,函数在执行的时候过多依赖全局变量不利于函数的重复利用
3:过多的使用全局变量会降低程序的清晰度,使程序的可读性下降,在各个函数执行的时候都有可能改变全局变量的值,往往难以清楚的判断出每个时刻各个全局变量的值
4:定义全局变量会永久占用单片机的内存单元,而局部变量只有进入定义局部变量的函数时才会占用内存空间,函数退出后会自动释放所占用的内存。
变量的储存类别分别为自动,静态,寄存器和外部4种
函数中的局部变量如果不加static这个关键字来修饰都属于自动变量,也叫动态储存变量。动态变量的关键字是auto,但是这个关键字是可以省略的,所有平时都不写。
与动态变量对应的就是静态变量。首先,全局变量均是静态变量。此外还有一种特殊的局部变量也是静态变量。即在定义局部变量时在前边加上static这个关键字,加上这个关键字的变量就称之为静态局部变量。
它的特点,在整个生存中只赋一次初值,在第一次执行函数时,它的值就是给定的初值,而之后在该函数所有的执行次数中,它的值都是上一次函数执行结束后的值,即它可以保持前次的执行结果。 通俗的将就是类似语句static unsigned char i = 0;不管多少次进入函数该句只执行一次,下次进入函数,该句就不在执行了,即不会再把0赋值给i。
点阵的认识
该图是本案使用的8x8点阵LED。
一个数码管是8个LED组成,同理,1个8x8的点阵就是由64个LED小灯组成的。
图示1
图示2
图示3
图示4
图示是本案的原理图
首先点亮点阵LED左上角的LED。如图从原理图上来看 若想实现该现象,我们需要图示1的 DB0输出低电平 LEDC0也为低电平,从原理图上看点阵LED的限流电阻是图4所示的330R电阻,通过双向缓冲器74HC25和单片机相连。这里不直接接到单片机是因为51单片机的IO口承受电流不能超过50ma,单个IO口的电流不要超过6ma。
通过电路图计算一下IO的电流,供电电压是5V,途径过三极管Q10的CE端和点阵LED本身的压降,Q10工作在饱和状态几乎没有压降,点阵LED的压降在1.8-2.2V作用,假设限流电压R18两端的压降是3V则电流是9ma,8个IO口则是72ma。超出了单片机IO能承受的范围。因此接入一个双向缓冲器74HC25让电流流入缓冲器而不是单片机,看图示4,DIR1脚是高电平,OE19脚是低电平,通过数据手册
可以看出B端的输出电压由A端控制,A端连着单片机P0口,P0口的输出电压则和74Hc25的B端的电压一致。因此 使P0^0 = 0;可使LED阴极接低电平。
若使图1 LEDC0输出低电平其他位为高电平,则需要图2 U4第15脚Y0输出低电平,Y1-Y7输出高电平。这边原理图有点小瑕疵,看图原理图上ADDR0-ADDR3和p1.0-p1.3端口它们没有标识是连在一起的。
,事实上ADDR0和端口P1.0 ,ADDR1和P1.1,ADDR2和p1.2,ADDR3和P1.3是相连的。可以看出ENLED是p1.4端口。
由74Hc18的数据手册可知
U4 A=A0=ADDR0=p1.0 B=A1=ADDR1=p1.1 C=A2=ADDR2=p1.2 G1 =E3接5V电压高电平
G2A=E1=ADDR3=p1.3 G2B=E2=ENLED=p1.4 G2A、G2B接低电平使能。
如果要想使U4工作并且使Y0输出低电平其他输出高电平则需要,
ADDR0 = 0;ADDR1 = 0; ADDR2 = 0;ADDR3 = 0;ENLED = 0;
则程序为
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
void main()
{
ENLED = 0;
ADDR3 = 0;
ADDR2 = 0;
ADDR1 = 0;
ADDR0 = 0;
LED = 0;
while(1);
}
现象为成功点亮左上角的电压。
如果要点亮第一排的电压的话则只需要把P0端口的电压都置为低电平即可。
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
void main()
{
ENLED = 0;
ADDR3 = 0;
ADDR2 = 0;
ADDR1 = 0;
ADDR0 = 0;
P0 = 0x00;
while(1);
}
。
假使点亮左起第一行1.3.5.7LED如何操作
因为低电平有效若实现目标则必须使点阵相应LED的位置的电压为 01010101,从原理图上来看8个LED从左到右是DB0-DB7分是按照循序依次排列的,但是二进制左边是高位,上述01010101高位0是P0.0口因此这个二进制要反一下是10101010=0xAA才符合我们的电路。看程序
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
void main()
{
ENLED = 0;
ADDR3 = 0;
ADDR2 = 0;
ADDR1 = 0;
ADDR0 = 0;
P0 = 0xAA;
while(1);
}
如果我们要在点阵LED上画一些复杂的图片则需要字模软件的帮忙。
针对本案原理图图字模软件的设置是
从上述的例子可以看出要把字节倒序打上勾,然后是横向取模。因为只有横向的8个位置可以被一个值(P0的值)表示。纵向的涉及38译码器无法设置一个值就能控制纵向的通断。
实现1个山字的显示
通过取模软件取一个不标准的山字0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF,
本案是横向取模可以看到要想第1行显示正确,加上是低电平有效因此它的值是11101111取反11110111=0xF7,为数组的第一个元素,可见确实是符合本电路的取值。
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code image[] = {
0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF,
};
void main()
{
EA = 1;
ENLED = 0;
ADDR3 = 0;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
while(1);
}
void InterruptTimer0() interrupt 1
{
static unsigned char i = 0;
TH0 = 0xFC;
TL0 = 0x67;
P0 = 0xFF;
switch(i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=image[0];break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=image[1];break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=image[2];break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=image[3];break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=image[4];break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=image[5];break;
case 6: ADDR2=1; ADDR1=1; ADDR0=0; i++; P0=image[6];break;
case 7: ADDR2=1; ADDR1=1; ADDR0=1; i=0; P0=image[7];break;
default: break;
}
}
显示一个山字
实现山字上下翻转
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
unsigned char code image[] = {0xF7,0xF6,0xB6,0xB6,0xB6,0xB6,0x80,0xFF,
};
void main()
{
EA = 1; //中断使能(启动中断)
ENLED = 0; //38译码器U4使能
ADDR3 = 0; //38译码器U4使能
TMOD = 0x01; //定时器工作在模式1
TH0 = 0xFC; //定时器0赋值 定时1ms
TL0 = 0x67;
ET0 = 1; //定时器0中断使能(启动T0中断)
TR0 = 1; // 定时器0使能(启动T0)
while(1);
}
void TtrTimer0 () interrupt 1
{
static unsigned char i = 0;
TH0 = 0xFC; //定时器0重新赋值
TL0 = 0x67;
P0 = 0xFF; //消除鬼影
switch(i)
{
case 7: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; i = 0; P0 = image[7]; break; //上下扫描
case 6: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[6]; break;
case 5: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[5]; break;
case 4: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[4]; break;
case 3: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; i++; P0 = image[3]; break;
case 2: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[2]; break;
case 1: ADDR2 = 1; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[1]; break;
case 0: ADDR2 = 1; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[0]; break;
default: break;
}
}
通过改变switch语句的扫描方式 数码管从左起第一行开始扫描变成开始从左起最后一行开始扫描
实现山字左右翻转
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
unsigned char code image[] = {0xEF,0x6F,0x6D,0x6D,0x6D,0x6D,0x01,0xFF,
};
void main()
{
EA = 1; //中断使能(启动中断)
ENLED = 0; //38译码器U4使能
ADDR3 = 0; //38译码器U4使能
TMOD = 0x01; //定时器工作在模式1
TH0 = 0xFC; //定时器0赋值 定时1ms
TL0 = 0x67;
ET0 = 1; //定时器0中断使能(启动T0中断)
TR0 = 1; // 定时器0使能(启动T0)
while(1);
}
void TtrTimer0 () interrupt 1
{
static unsigned char i = 0;
TH0 = 0xFC; //定时器0重新赋值
TL0 = 0x67;
P0 = 0xFF; //消除鬼影
switch(i)
{
case 7: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; i = 0; P0 = image[7]; break; //上下扫描
case 6: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[6]; break;
case 5: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[5]; break;
case 4: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[4]; break;
case 3: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; i++; P0 = image[3]; break;
case 2: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[2]; break;
case 1: ADDR2 = 1; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[1]; break;
case 0: ADDR2 = 1; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[0]; break;
default: break;
}
}
0xEF,0x6F,0x6D,0x6D,0x6D,0x6D,0x01,0xFF,
取消选择‘字节倒序’功能,然后重新取值。放入数组
如何实现点阵图片动起来。
1:向上移动的我爱你
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF,0x99,0x99,0x99,0x99,0x99,0x81,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code image[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,
0xFF,0x99,0x99,0x99,0x99,0x99,0x81,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
void main()
{
EA = 1;
ENLED = 0;
ADDR3 = 0;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
while(1);
}
void InterruptTimer0() interrupt 1
{
static unsigned char i = 0;
static unsigned char index = 0;
static unsigned char tmr = 0;
TH0 = 0xFC;
TL0 = 0x67;
P0 = 0xFF;
switch(i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=image[index + 0];break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=image[index + 1];break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=image[index + 2];break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=image[index + 3];break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=image[index + 4];break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=image[index + 5];break;
case 6: ADDR2=1; ADDR1=1; ADDR0=0; i++; P0=image[index + 6];break;
case 7: ADDR2=1; ADDR1=1; ADDR0=1; i=0; P0=image[index + 7];break;
default: break;
}
tmr++;
if(tmr >= 250)
{
tmr = 0;
index++;
if(index >= 32)
{
index = 0;
}
}
}
2:向下移动的我爱你
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xE7,0xC3,0x81,0x00,0x00,0x00,0x99,0xFF,0xC3,0x81,0x99,0x99,0x99,0x99,0x99,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
方式是按照前文山字上下翻转的方式,但是取模的图片需要重新画。,上图上下翻转一下的话是
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
unsigned char code image[] =
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xE7,0xC3,0x81,0x00,0x00,0x00,0x99,
0xFF,0xC3,0x81,0x99,0x99,0x99,0x99,0x99,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
void main()
{
EA = 1; //中断使能(启动中断)
ENLED = 0; //38译码器U4使能
ADDR3 = 0; //38译码器U4使能
TMOD = 0x01; //定时器工作在模式1
TH0 = 0xFC; //定时器0赋值 定时1ms
TL0 = 0x67;
ET0 = 1; //定时器0中断使能(启动T0中断)
TR0 = 1; // 定时器0使能(启动T0)
while(1);
}
void TtrTimer0 () interrupt 1
{
static unsigned char i = 0;
static unsigned char index = 0;
static unsigned char tmr = 0;
TH0 = 0xFC; //定时器0重新赋值
TL0 = 0x67;
P0 = 0xFF; //消除鬼影
switch(i)
{
case 7: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; i = 0; P0 = image[index+7]; break; //上下扫描
case 6: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[index+6]; break;
case 5: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[index+5]; break;
case 4: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[index+4]; break;
case 3: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; i++; P0 = image[index+3]; break;
case 2: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[index+2]; break;
case 1: ADDR2 = 1; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[index+1]; break;
case 0: ADDR2 = 1; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[index+0]; break;
default: break;
}
tmr++;
if(tmr >= 250)
{
tmr = 0;
index++;
if(index >= 32)
{
index = 0;
}
}
}
3向下移动的我爱你第二种方式
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x99,0x99,0x99,0x99,0x81,0xC3,0xFF,
0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF,0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit LED = P0^0;
unsigned char code image[] =
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x99,0x99,0x99,0x99,0x99,0x81,0xC3,0xFF,
0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF,
0xC3,0xE7,0xE7,0xE7,0xE7,0xE7,0xE7,0xC3,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
void main()
{
EA = 1; //中断使能(启动中断)
ENLED = 0; //38译码器U4使能
ADDR3 = 0; //38译码器U4使能
TMOD = 0x01; //定时器工作在模式1
TH0 = 0xFC; //定时器0赋值 定时1ms
TL0 = 0x67;
ET0 = 1; //定时器0中断使能(启动T0中断)
TR0 = 1; // 定时器0使能(启动T0)
while(1);
}
void TtrTimer0 () interrupt 1
{
static unsigned char i = 0;
static unsigned char index = 39;
static unsigned char tmr = 0;
TH0 = 0xFC; //定时器0重新赋值
TL0 = 0x67;
P0 = 0xFF; //消除鬼影
switch(i)
{
case 7: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; i = 0; P0 = image[index-7]; break; //上下扫描
case 6: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[index-6]; break;
case 5: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[index-5]; break;
case 4: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[index-4]; break;
case 3: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; i++; P0 = image[index-3]; break;
case 2: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; i++; P0 = image[index-2]; break;
case 1: ADDR2 = 1; ADDR1 = 1; ADDR0 = 0; i++; P0 = image[index-1]; break;
case 0: ADDR2 = 1; ADDR1 = 1; ADDR0 = 1; i++; P0 = image[index-0]; break;
default: break;
}
tmr++;
if(tmr >= 250)
{
tmr = 0;
index--;
if(index <= 8)
{
index = 39;
}
}
}
从逻辑上更好理解就是往下移动。
4:左移的我爱你
左移的我爱你实现起来会比较麻烦,硬件电路设计的结果更方便上下移动。左移的我爱你在实方面更直观的表现出类似动画片一样一帧一帧的移动。而且使用了二维数组
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
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 main()
{
EA = 1;
ENLED = 0;
ADDR3 = 0;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
while(1);
}
void InterruptTimer0() interrupt 1
{
static unsigned char i = 0;
static unsigned char tmr = 0;
static unsigned char index = 0;
TH0 = 0xFC;
TL0 = 0x67;
P0 = 0xFF;
switch(i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=image[index][0]; break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=image[index][1]; break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=image[index][2]; break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=image[index][3]; break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=image[index][4]; break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=image[index][5]; break;
case 6: ADDR2=1; ADDR1=1; ADDR0=0; i++; P0=image[index][6]; break;
case 7: ADDR2=1; ADDR1=1; ADDR0=1; i=0; P0=image[index][7]; break;
default: break;
}
tmr++;
if(tmr >= 250)
{
tmr = 0;
index++;
if(index >= 30)
{
index = 0;
}
}
}
5:横向的我爱你
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code image[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x7D,0x01,0x01,0x7D,0xFF,0xFF,0xE3,0xC1,
0x81,0x03,0x03,0x81,0xC1,0xE3,0xFF,0xFF,
0x81,0x01,0x3F,0x3F,0x3F,0x01,0x81,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
void main()
{
EA = 1;
ENLED = 0;
ADDR3 = 0;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
while(1);
}
void InterruptTimer0() interrupt 1
{
static unsigned char i = 0;
static unsigned char index = 0;
static unsigned char tmr = 0;
TH0 = 0xFC;
TL0 = 0x67;
P0 = 0xFF;
switch(i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=image[index + 0];break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=image[index + 1];break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=image[index + 2];break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=image[index + 3];break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=image[index + 4];break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=image[index + 5];break;
case 6: ADDR2=1; ADDR1=1; ADDR0=0; i++; P0=image[index + 6];break;
case 7: ADDR2=1; ADDR1=1; ADDR0=1; i=0; P0=image[index + 7];break;
default: break;
}
tmr++;
if(tmr >= 250)
{
tmr = 0;
index++;
if(index >= 32)
{
index = 0;
}
}
}
相比用二维数组的方式更倾向在硬件电路上改动,让点阵转个90度放置实现左右移动。