水平移动一个汉字
我们取中国象棋里的“帅”字为例,实现一个字自左至右移动的效果。
16 X 16是能够比较清晰地显示大部分汉字的最小分辨率,也是计算机屏幕上能够显示汉字最早采用的制式。
提取一个汉字的点阵并非难事。画一个16 X 16个格子的表格。将欲显示汉字正楷形式写出,按笔画所占的格子,转换成32个字节即可。
//水平向右移动“帅”字
//数据存贮在flash存储器中
//“帅”字点阵
const unsignedchar 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
};
unsigned charA_array[16][4]; //装点阵的数组
void setup()
{
PORTB = 0x00; //初始化端口B,C,D功能为输出,端口状态为0
DDRB =0xFF;
PORTC = 0x00;
DDRC =0x0F;
PORTD = 0x00;
DDRD =0xFF;
}
//初始化数组,将数据装入数组
voidA_arr_prepare()
{
int i,j;
for (i = 0;i < 16;i++)
{
j = i * 2;
A_array[3] = table[j];
A_array[2] = table[j+1];
A_array[1] = 0;
A_array[0] = 0;
}
}
void loop()
{
int i,L;
char m0,m1,m2,m3;
A_arr_prepare(); //初始化数组
while(1)
{
for (L = 0;L < 10;L++) //滚屏速度控制
{
for (i = 0;i < 16;i++) //显示一屏
{
PORTD = A_array[1];
PORTB = A_array[0];
PORTC = i;
delay(1); //行扫间隔
}
}
//数组A是一个16X4共64字节的结构,可以将数组想象成四列、十六行。
//我们将这四列以0,1,2,3标注,其中1,2两列直接对应点阵屏上的左右两列8X8 LED模块
//其中每个字节里的每位,即每个bit对应点阵的一个LED,即一个光点
//要想造成向右移动的效果,就将最左侧字节数组列即标注为0的那一列的最低位移入第1列的字节的最高位
//再将第1列的最低位移入第2列的最高位,而第2列的最低位移入第0列的最高位
//依次将16行都移动,就完成了整屏向右移动一列的效果,连续起来,
//就造成整屏右移的效果。
for (i = 0;i < 16;i++) //右移一列
{
if ((A_array[0] & 0x01) == 1)
m0 = 0x80;
else
m0 = 0;
if ((A_array[1] & 0x01) == 1)
m1 = 0x80;
else
m1 = 0;
if ((A_array[2] & 0x01) == 1)
m2 = 0x80;
else
m2 = 0;
if ((A_array[3] & 0x01) == 1)
m3 = 0x80;
else
m3 = 0;
A_array[3] = A_array[3] >> 1;
A_array[3] = A_array[3] | m0;
A_array[2] = A_array[2] >> 1;
A_array[2] = A_array[2] | m3;
A_array[1] = A_array[1] >> 1;
A_array[1] = A_array[1] | m2;
A_array[0] = A_array[0] >> 1;
A_array[0] = A_array[0] | m1;
}
}
}
向上连续移动6个汉字
前面的例子告诉我们,在16X 16点阵屏上显示一个汉字,要占用32个字节的存储空间。光靠SRAM是显示不了几个字的,我们可以利用片上的EEPROM。下面的例子是利用EEPROM存储汉字点阵数据,连续显示六个汉字自下向上移动的程序。我们知道Atmega48具有片上256个字节的EEPROM空间,最多可以存储8个汉字的点阵,要想再多,就要换芯片了。
//16X16点阵屏,六字向上移动
//六个汉字点阵字模存在EEPROM中
#include
//六个汉字的数据存贮在EEPROM存储器中
//Arduino不具备向FLASH下载程序代码的同时写入EEPROM数据的功能,
//本程序所用EEPROM数据要借助其他工具写入。
void setup()
{
PORTB = 0x00; //初始化端口B,C,D功能为输出,端口状态为0
DDRB =0xFF;
PORTC = 0x00;
DDRC =0x0F;
PORTD = 0x00;
DDRD =0xFF;
}
void loop()
{
unsigned char B_port[32]; //汉字点阵数组
int I;
int J;
int K;
int L;
for (K = 0;K < 32;K++) //初始化数组
{
B_port[K] = EEPROM.read(K); //从EEPROM中读出第一个字的点阵
}
K = 0; //EEPROM地址计数指针从0开始,六个字连续计数
do
{
for (L = 0;L < 10;L++) //刷屏移动速度,也就是每帧画面保留的时间
{
J = 0;
for (I = 0;I < 16;I++)
{
PORTD = B_port[J];
PORTB = B_port[J+1];
PORTC = I;
delay(1); //行扫间隔
J = J + 2;
}
}
I = 0; ////开始移动数组,由后向前
while (I < 30)
{
B_port[I] = B_port[I + 2]; //例如,数组元素2、3移至0、1
B_port[I + 1] = B_port[I + 3];
I = I + 2; //指针递增
}
B_port[30] = EEPROM.read(K); //最后,从EEPROM取字节两个,填入数组元素30和31
K++;
B_port[31] = EEPROM.read(K);
K++;
if (K > 191)
K = 0;
}
while(1);
}
请读者注意,Arduino不具备下载程序代码的同时下载EEPROM数据的功能(笔者未能找到),EEPROM数据只有通过其他渠道写入芯片,比如,很好用的一款下载工具:AVR_Fighter。
以上两个关于16X16点阵屏的例子仅用一片Atmega48就跑起来,充分调动了单片机自己的资源,说明硬件结构对一个系统的影响。可能非常繁琐复杂,也可以很简单。