首页 > 实用范文 > 其他范文
移动设备课程设计
编辑:梦回江南 识别码:130-757067 其他范文 发布时间: 2023-10-19 06:54:42 来源:网络

武汉轻工大学

数学与计算机学院

移动设备课程设计

设计题目:ARM开发板上通过转换函数实现汉字显示

专 业 计算计科学与技术

班 级 1802

学 号 1801070108

姓 名 毛佳文

指导教师 易逵

2021 年 7 月5 日

一、实验环境

开发板:iTOP-4412

操作系统:Windows 10

虚拟机:VMware Workstation Pro 15 Ubuntu12.04.2_V2.0

数据传输工具:Xshell 7

驱动软件:驱动精灵

二、实验要求

ARM开发板上实现汉字显示

三、实验原理

当前流行的字符编码格式有:US-ASCII、ISO-8859-1、UTF-8、UTF-16BE、UTF-16LE、UTF-16、GBK、GB2312等,其中GBK、GB2312是专门处理中文编码的。而libiconv是一个常用的编码转换库,支持常用的多种编码之间的转换。在Linux下,工具链gcc有专门的libiconv库,所有不用移植,但在arm-linux下就没那么幸运了,需要我们额外移植libiconv库,不过,过程还是比较简单的。

字符编码转换libiconv库介绍

Libiconv是一个常用的编码转换库,支持常用的多种编码之间的转换。

iconv_open是打开一个编码流,类似于打开一个编码管道(通道),出错则返回-1;

iconv用于具体输入的转换,如果出错,则返回-1,否则返回 0;

iconv_close是关闭该管道(通道)。

如果对于大量需要转换的编码,上述函数covert不适合该方式,一是内存的限制不能一次调用,二是若分多次调用会频繁打开一个编码管道(通道),导致资源浪费,最好的办法还是拆开该函数根据情况使用。

存在的问题

开发环境为ubuntu11.10,开发板为ARM开发板,交叉编译器版本为arm-linux-4.4.3.相同的C源程序,在ubuntu11.10上能够正常执行,而在ARM开发板则不能正常执行,调用iconv_open(“utf-8”, “gb2312”)返回失败,错误信息为“Invalid argument”.经过查询资料得知iconv相关函数为libc中的函数,初步分析得出结论为有可能是libc版本中

iconv相关函数的版本不同造成的,因此要更新iconv相关函数。

更新iconv相关函数有两种方法:

第一,更新libc库;

第二,更新libiconv库。

第一种方法更新libc库比较麻烦,因为我们用的是编译好的交叉编译器,这种方法需要重新编译生成交叉编译器,并且也需要使用新编译生成的交叉编译工具重新编译应用程序,因此本方法代价太大,因此我们采用第二种方法。

GBK对汉字的编码

GBK的中文编码是双字节来表示的,英文编码是用ASCII码表示的,既用单字节表示。但GBK编码表中也有英文字符的双字节表示形式,所以英文字母可以有2种GBK表示方式。为区分中文,将其最高位都定成1。英文单字节最高位都为0。当用GBK解码时,若高字节最高位为0,则用ASCII码表解码;若高字节最高位为1,则用GBK编码表解码。

字符有一字节和双字节编码,00–7F范围内是第一个字节,和ASCII保持一致,此范围内严格上说有96个文字和32个控制符号。之后的双字节中,前一字节是双字节的第一位。总体上说第一字节的范围是81–FE(也就是不含80和FF),第二字节的一部分领域在40–7E,其他领域在80–FE。

四、实验步骤

1.搭建实验环境

确保iTop-4412已经搭载了最小Linux子系统。

2.更新libiconv动态链接库

下载最新库文件并且编译安装: libiconv-1.14.tar.gz

tar-vxf libiconv-1.14.tar.gz //解压缩libiconv-1.14.tar.gz

cd jpeg-9d

./configure--host=arm-none-linux-gnueabi //配置交叉编译器

make //编译

make install //安装

将preloadable_libiconv.so 这个动态库安装在开发板的根目录下的 /lib文件夹下:

图1 libiconv编译后的lib库文件

图2 开发板下的 lib库文件

从虚拟机中将文件preloadable_libiconv.so cp iTopeet-4412/lib下

1,编写实验代码

文件结构如下:

图3 代码结构图

其中ascii.h、HZK16均为资源文件,而mode_print_CH_String.c才是最关键的文件(实现了本实验的全部功能:输入一串中文字符就可以在开发板屏幕上显示)

具体代码如下:

(1)ascii.h

图4 ascii.h源码部分截图

其中ascii_bitmaps[]的每16个数据元就存放一个ASCII字符的编码信息(前面有大量无法显示的字符,故为0x00)

(2)mode_print_CH_String.c

#include

#include

#include

#include

#include

#include

#include

#include ”ascii.h“

#include

#include

#include

int *fbmem;//数据帧缓存

unsigned char *hzkmem;汉字字符串缓存

int w, h;

unsigned char *string = ”张多鱼国家排核废水

#define OUTLEN 128

void fb_point(int x, int y, int color)//画点函数

{

fbmem[y * w + x] = color;

}

void fb_hline(int x1, int x2, int y, int color)//画线函数

{

int i;

for(i=x1;i

fb_point(i, y, color);

}

void show_ascii(int x, int y, unsigned char c, int color)

{

/* 得到字符点阵在数组中的起始位置 */

// unsigned char *dots =(unsigned char *)&ascii_bitmaps[c*16];

unsigned char *dots = &ascii_bitmaps[c*16];

int i,j;

unsigned char byte;

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

/* 取出一个字节 */

byte = dots[i];

for(j = 7;j >= 0;j--)

{

if(byte &(1 << j)){

/* 传入参数的值是lcd要显示的起点坐标 这里每个点的坐标每描一个点要移动一次 */

fb_point(x + 7-j, y + i, color);

}

}

}

}

void show_chinese(int x, int y, unsigned char *str,int d,int w,int color)

//d w 分别是放大倍数和点阵密度倍数,两者需保持一致 可放大字体倍数

{

unsigned int area = str[0]-0xa1;

unsigned int where = str[1]-0xa1;

unsigned char *dots = hzkmem +(area * 94 + where)* 32;

unsigned char byte;

// int i,j,k;

int i, j, b,m,n;

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

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

byte = dots[i*2 + j];

for(b = 7;b >=0;b--){

if(byte &(1<

/* show 加粗显示*/

for(m=0;m< d;m++){

for(n=0;n

fb_point((x+(7-b+j*8)*w)+m,(y+i*w)+n, color);

}//for n

}//for m

} //if

}

}

}/

x+=16*w+20;//按照行来显示,中间空20个pixs

y+=0;

}

int main()

{

int i, j, k;

int fd, fd_hzk;

struct fb_var_screeninfo fb_var;

struct stat hzk_stat;

iconv_t cd;

int inbuf_len = strlen(string);

char outbuf[OUTLEN];

char *pin = string;

char *pout = &outbuf[0];//用“pout=&outbuf” 会引发SIGSERV信号,导致段错误

int outbuf_len = OUTLEN;

fd = open(“/dev/fb0”, O_RDWR);//打开缓冲设备

if(fd < 0){

printf(“open errorn”);

return-1;

}

fd_hzk = open(“HZK16”, O_RDONLY);//打开字库文件

if(fd_hzk < 0)

{

printf(“cant open HZK16n”);

return-1;

}

/* 得到这个件的统计信息当然也包含了大小 */

if(fstat(fd_hzk, &hzk_stat))

{

printf(“cant get hzk_stat!n ”);

return-1;

}

if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_var))/* 获得可变信息 */

{

/* 正常获得信息的话 ioctl 会返回0 如果返回值不为0时表示出错 */

printf(“cant get var!n”);

return-1;

}

w = fb_var.xres;

h = fb_var.yres;

k = fb_var.bits_per_pixel;

printf(“framebuffer: %d * %d * %dn”, w, h, k);

fbmem = mmap(0, w*h*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

hzkmem =(unsigned char *)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk, 0);

memset(outbuf, 0, OUTLEN);//清空输出缓存,否则会有意外结果的 printf(“Originial Data:n”);//打印转换前的一些参数和信息,以进行比较

printf(“tpin str: %s, outbuf str:%sn”, pin, outbuf);

printf(“tinbuf_len=%d, outbuf_len=%dn”, inbuf_len, outbuf_len);

printf(“tstrlen(outbuf)= %dn”, strlen(outbuf));

cd = iconv_open(“GB2312”, “UTF-8”);

if(cd == 0)

return EXIT_FAILURE;

int count = iconv(cd, &pin, &inbuf_len, &pout, &outbuf_len);

printf(“iconv count : %dn”, count);//观察iconv返回值,理解不可逆转换含义

iconv_close(cd);

printf(“After Converted Data:n”);//注意发生变化的变量

printf(“tpin str: %s, gb2312 str:%sn”, pin, outbuf);

printf(“tinbuf_len=%d, outbuf_len=%dn”, inbuf_len, outbuf_len);

printf(“tstrlen(outbuf)= %dn”, strlen(outbuf));

for(i = 0;i < strlen(outbuf);i += 2)

{

show_chinese(100+32*i, 300, outbuf+i,2,2, 0xffff00);

//使用HZK16字库显示GB2312编码的中文点阵

}

return 0;

}

对该文件进行交叉编译:

arm-none-linux-gnueabi-gcc mode_print_CH_String.c

2.配置preloadable_libiconv.so的环境变量

在超级终端在输入:

export LD_PRELOAD=/lib/preloadable_libiconv.so

五、实验运行

    挂载

图5 挂载(将带有运行程序的TF卡挂载到/mnt/disk)

    运行程序:

图6 运行程序:./mode_print_CH_String

    运行结果截图

六、实验总结

经过本学期的移动设备开发学习,我了解到嵌入式Linux开发的基本流程,对xshell软件等的使用有了了解,发现自己知识水平有待提高,在今后的学习里,我会更加地努力,提升自我的知识素养。

移动设备课程设计
TOP