fullmous 发表于 2016-4-15 20:12:43

一个关于16X16点阵屏动画移动汉字的程序

本帖最后由 fullmous 于 2016-4-15 20:14 编辑

本文仅就在Arduino环境下不借助任何附加的逻辑芯片,就用Atmega48,仅凭端口的处理方式操控16X16点阵屏,完成文字移动等动画效果。

水平移动一个汉字
      我们取中国象棋里的“帅”字为例,实现一个字自左至右移动的效果。
16 X 16是能够比较清晰地显示大部分汉字的最小分辨率,也是计算机屏幕上能够显示汉字最早采用的制式。
提取一个汉字的点阵并非难事。画一个16 X 16个格子的表格。将欲显示汉字正楷形式写出,按笔画所占的格子,转换成32个字节即可。

//水平向右移动“帅”字
//数据存贮在flash存储器中
//“帅”字点阵
const unsigned 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
};

unsigned char A_array;                //装点阵的数组

void setup()
{
PORTB = 0x00;    //初始化端口B,C,D功能为输出,端口状态为0
DDRB= 0xFF;
PORTC = 0x00;
DDRC= 0x0F;
PORTD = 0x00;
DDRD= 0xFF;
}
//初始化数组,将数据装入数组
void A_arr_prepare()
{
int i,j;
for (i = 0;i < 16;i++)
{
    j = i * 2;
    A_array = table;   
    A_array = table;
    A_array = 0;
    A_array = 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;
      PORTB = A_array;
      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 & 0x01) == 1)
      m0 = 0x80;
      else
      m0 = 0;
      if ((A_array & 0x01) == 1)
      m1 = 0x80;
      else
      m1 = 0;
      if ((A_array & 0x01) == 1)
      m2 = 0x80;
      else
      m2 = 0;
      if ((A_array & 0x01) == 1)
      m3 = 0x80;
      else
      m3 = 0;

      A_array = A_array >> 1;
      A_array = A_array | m0;

      A_array = A_array >> 1;
      A_array = A_array | m3;

      A_array = A_array >> 1;
      A_array = A_array | m2;

      A_array = A_array >> 1;
      A_array = A_array | m1;

    }
}

}

向上连续移动6个汉字
      前面的例子告诉我们,在16 X 16点阵屏上显示一个汉字,要占用32个字节的存储空间。光靠SRAM是显示不了几个字的,我们可以利用片上的EEPROM。下面的例子是利用EEPROM存储汉字点阵数据,连续显示六个汉字自下向上移动的程序。我们知道Atmega48具有片上256个字节的EEPROM空间,最多可以存储8个汉字的点阵,要想再多,就要换芯片了。

//16X16点阵屏,六字向上移动
//六个汉字点阵字模存在EEPROM中

#include <EEPROM.h>
//六个汉字的数据存贮在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;      //汉字点阵数组
int I;
int J;
int K;
int L;

for (K = 0;K < 32;K++)      //初始化数组
{
    B_port = 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;                                 
      PORTB = B_port;                              
      PORTC = I;
      delay(1);               //行扫间隔
      J = J + 2;
      }
    }

    I = 0;                ////开始移动数组,由后向前
    while (I < 30)
    {
      B_port = B_port;   //例如,数组元素2、3移至0、1
      B_port = B_port;
      I = I + 2;                  //指针递增
    }
    B_port = EEPROM.read(K);//最后,从EEPROM取字节两个,填入数组元素30和31
    K++;
    B_port = EEPROM.read(K);
    K++;
    if (K > 191)
      K = 0;
}
while(1);
}

      请读者注意,Arduino不具备下载程序代码的同时下载EEPROM数据的功能(笔者未能找到),EEPROM数据只有通过其他渠道写入芯片,比如,很好用的一款下载工具:AVR_Fighter。

      以上两个关于16X16点阵屏的例子仅用一片Atmega48就跑起来,充分调动了单片机自己的资源,说明硬件结构对一个系统的影响。可能非常繁琐复杂,也可以很简单。


战戟先锋aa 发表于 2016-4-15 21:20:12

不错,学习一下。

swhl 发表于 2016-4-16 16:47:01

不错,学习了
页: [1]
查看完整版本: 一个关于16X16点阵屏动画移动汉字的程序