特色专栏 > 机械控制
+

在ARM实验板LCD上显示汉字

2020/5/7    作者:未知    来源:网络文摘    阅读:327

一、实验目的

1.编写能够在ARM实验板LCD上显示汉字的程序;

2.在Ubuntu系统中建立交叉编译环境,编译上述程序生成.o文件;

3.制作root文件系统,下载到开发板中验证。


二、实验原理

16*16点阵字库HZK16的使用


三、实验步骤

1.Ubuntu系统上编写验证程序

Ubuntu系统上编写的验证程序如下,为了验证是否能够正确从HZK16字库中读取出某个字。

#include   

#include   

void getHZCode(unsigned char incode[], unsigned char hzCode[]);  

int main()  

{  

    unsigned char incode[2] = {0xce,0xd2};//要显示的汉字  

    //unsigned char incode[2] = "我";//要显示的汉字  

    unsigned char hzCode[32];  

    int i;  

    int j = 0;  

    getHZCode(incode, hzCode);  

    for(i=0; i<32; i++){  

        for(j=0; j<8; j++){  

            if(hzCode[i] << j & 0x80)  

                printf("●");  

            else  

                printf("○");  

        }  

        if((i+1) % 2 == 0)  

            printf("n");  

    }  

    return 0;  

}  


void getHZCode(unsigned char incode[], unsigned char hzCode[]){  

    long offset;//相对于字库起始位置的偏移字节数  

    int quCode = incode[0] - 0xa0;//区码:该汉字的区号  

    int weiCode = incode[1] - 0xa0;//位码:该汉字的位号  

    offset = (94 * (quCode - 1) + (weiCode - 1)) * 32;//32为一个汉字需要32字节(16*16=256个点,256/8=32)  

    FILE *HZK;  

    HZK = fopen("HZK16", "rb");  

    if(HZK == NULL)//rb:打开二进制文件  

    {  

        printf("Can’t Open HZK16n");  

        exit(0);  

    }  

    //fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置  

    //如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0  

    //偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END)  

    fseek(HZK, offset, SEEK_SET);  

    //size_t fread ( void *buffer, size_t size, size_t count, FILE *stream)  

    //从一个文件流中读数据,最多读取count个项,每个项size个字节,如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0  

    //buffer:用于接收数据的内存地址  

    //size:要读的每个数据项的字节数,单位是字节  

    //count:要读count个数据项,每个数据项size个字节.  

    //stream:输入流  

    fread(hzCode, 1, 32, HZK);//读取表示此汉字的32字节数到hzCode中  

}  



在Ubuntu中使用如下命令编译:gcc HZK16.cpp -o HZK16.exe

使用./HZK16执行程序,执行结果如下图所示:

在ARM实验板LCD上显示汉字

注意:在win7中可以直接将“我”字赋值给incode[2]:incode[2] = "我",而在Ubuntu中需要将表示该汉字的2字节赋值给incode[2]:incode[2] = {0xce, 0xd2},不然用gcc编译时会报错。


2.Ubuntu系统上编写能够在板子上执行的程序

要在LCD上显示“北京邮电大学”,首先打开FrameBuffer驱动:fd_fb = open("/dev/fb0", O_RDWR),之后使用函数mmap映射显示存储器,最后调用函数PrintLCD显示字体,代码如下:

#include  

#include

#include

#include

#include  

#include

#include

#define FONT_COLOR 0xf100 //红色

int k;

unsigned char hzCode[16][2];

unsigned short *fb = 0;

 

 

void getHZCode(unsigned char incode[], unsigned char hzCode[16][2])

{

long offset;//相对于字库起始位置的偏移字节数  

int quCode = incode[0] - 0xa0;//区码:该汉字的区号       

int weiCode = incode[1] - 0xa0;//位码:该汉字的位号

offset = (94 * (quCode - 1) + (weiCode - 1)) * 32;//32:一个汉字需要32字节(16*16=256个点,256/8=32)     

FILE *HZK;

HZK = fopen("HZK16", "rb");

if (HZK == NULL)  

{

printf("Can't Open HZK16n");

exit(0);

}

    //fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置    

    //如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0    

    //偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END)  

fseek(HZK, offset, SEEK_SET);

  //size_t fread ( void *buffer, size_t size, size_t count, FILE *stream)    

    //从一个文件流中读数据,最多读取count个项,每个项size个字节,如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0    

    //buffer:用于接收数据的内存地址    

    //size:要读的每个数据项的字节数,单位是字节    

    //count:要读count个数据项,每个数据项size个字节    

    //stream:输入流    

fread(hzCode, 32, 1, HZK);//读取表示此汉字的32字节数到hzCode中    

}

 

 

void PrintLCD(int top, int left) {

int i, j, k;

for (j = 0; j < 16; j++) {

for (i = 0; i < 2; i++) {

for (k = 0; k < 8; k++) {

if (hzCode[j][i] & (0x80 >> k))

*(fb + (j + top) * 240 + left + i * 8 + k) = FONT_COLOR;

}

}

}

 

 

}

 

 

int main()

{

int i,j;

int fd_fb = 0;

unsigned char incode[2];//存储区码和位码

int strLength = 0;//字符串长度

char testStr[] = {0xB1, 0xB1,

0xBE, 0xA9,

0xD3, 0xCA,

0xB5, 0xE7,

0xB4, 0xF3,

0xD1, 0xA7

};

strLength = strlen(testStr);

fd_fb = open("/dev/fb0", O_RDWR);//打开FrameBuffer驱动

fb = (unsigned short *)mmap(0, 240 * 320 * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);//映射显示存储器,2:2Bytes

memset(fb,0,240 * 320 * 2); //清屏  

for (k = 0; k < strLength; k += 2) {

incode[0] = testStr[k];//区码

incode[1] = testStr[k++];//位码

getHZCode(incode, hzCode);

PrintLCD(90, (k / 2) * (16 + 5));//显示点阵

}

}

3.Ubuntu系统上搭建交叉编译环境

Ubuntu系统下arm-linux-gcc交叉编译环境搭建过程

4.Ubuntu系统上生成文件系统

(1)生成目标文件:

arm-linux-gcc –o HZK16LastOutFile HZK16Last.cpp

(2)将 root文件系统镜像Mount(挂载)到一个空目录mountDisk:

 mount –t cramfs –o loop root.cramfs mountDisk

(3)将 mountDisk目录内的整个 root 文件系统复制到一个新文件夹mountDiskNew中:

cp mountDisk mountDiskNew/

(4)确定完整无误地复制了root文件系统后,Unmount(卸载)disk 内的文件系统,使用命令如下:

umount disk

(5)然后切换到mountDiskNew/mountDisk/home/guest文件夹(哪个文件夹都可以)下,将经过交叉编译的目标文件和字库HZK16复制到其中;

(6)使用如下命令生成一个新的 root 文件系统镜像:

mkcramfs mountDisk newroot.cramfs

(7)将生成的root文件系统下载到实验板上,步骤如下:

将超级终端配置成:端口为COM1,波特率为115200,数据位为8bit,校验位为无,停止位为1,流控为无。

将启动模式调成ON-OFF-ON-ON-ON-ON

给ADS板上电

在系统启动过程中立即敲击以进入启动菜单

选择选项 ‘2’烧写根文件系统镜像

当超级终端上显示“USB drive ready for transfer”时,将USB先插入PC上

当一个可移动磁盘出现在Windows中后,将要烧写的镜像文件复制到该可移动磁盘中

文件复制完后,在可移动磁盘的盘符上点击鼠标右键选择弹出选项

此时在超级终端上会显示“Press any key to start program…”,只需要任意键入一个键就可以开始烧写了。

烧写完成后重启板子进入系统,切换目录:cd home/guest/

运行程序:./ HZK16LastOutFile,LCD上显示“北京邮电大学”


四、过程中遇到的问题

1.Ubuntu下的汉字是用UTF-8的编码表示的,也就是说一个汉字需要3个字节。但是HZK16是一个符合GB2312标准的库,也就是说每个汉字只需要2个字节来表示。所以在Ubuntu下直接给出ASCII码,如“北京邮电大学”对应的ASCII码为:0xb1,0xb1,0xbe,0xa9,0xd3,0xca,0xb5,0xe7,0xb4,0xf3,0xd1,0xa7;


2.起初使用的交叉编译器版本太高,造成在板子中执行./ HZK16LastOutFile语句时提示找不到文件,所以使用版本低的交叉编译器重新搭建交叉编译环境,问题得以解决。

  • 相关文章
  • 热门文章
免责申明:天天CAD教程网旨在相互学习交流,是一个完全免费的网站,部分原创作品,欢迎转载,部分内容来自互联网,如果侵犯了您的权利请尽快通知我们!邮箱:qm198794@gmail.com天天CAD教程网湘ICP备17006802号
【回到顶部】