文件浏览器及数据相框,添加华语字库

by admin on 2019年1月31日

要求:原操作系统代码里只是协理了波兰语突显,须要做的是达成对这些系统的汉字全角辅助。

FrameBuffer的原理     FrameBuffer
是出新在 2.2.xx 根本当中的一种驱动程序接口。

2017/07/02
更新,以前随手复制的外人的,只打算自己存档,所以格式没怎么管,不过看到500+阅读量觉得挺对不起以前点开的心上人的,而且终于打算好好经营这一个号了,所以能够收拾了一下。

在C51中,HZK16汉字库的采纳(mydows’s Blog转发)

hzk16的牵线以及简单的运用办法

   
Linux是工作在爱惜形式下,所以用户态进度是无力回天象DOS那样采取显卡BIOS里提供的中断调用来落成直接写屏,Linux抽象出
FrameBuffer这么些设备来供用户态进度达成直接写屏。Framebuffer机制模仿显卡的成效,将显卡硬件结构抽象掉,可以透过
Framebuffer的读写间接对显存举行操作。用户可以将Framebuffer看成是显示内存的一个影象,将其映射到进程地址空间之后,就足以一贯开展读写操作,而写操作可以立刻反应在显示屏上。那种操作是画个饼来解除饥饿的,统一的。用户无需关切物理显存的职位、换页机制等等具体细节。那几个都是由
Framebuffer设备驱动来形成的。

【转自 自己读书用 侵删】

概念如下:
unsigned char str[]=”我”
在运行时str被起先化为2个字节长度,内容为“我”的GBK码,为:0xCE(区码),0xD2(位码)。
选择如下换算公式得到“我”在HZK16文本中的地址,从该职位上马的依次32字节为“我”的字样。
    ADD=【(区码-0xa1)×0x5e + (位码-0xa1)】×0x20
安份守己上边的持筹握算办法,“我”的字样地址:0x216E0 。他的C语言字模为:0x04,0x80,0x0E,0xA0,0x78,0x90,0x08,
0x90,0x08,0x84,0xFF,0xFE,0x08,0x80,
0x08,0x90,0x0A,0x90,0x0C,0x60,0x18,
0x40,0x68,0xA0,0x09,0x20,0x0A,0x14,
0x28,0x14,0x10,0x0C

HZK16字库是相符GB2312标准的16×16点阵字库,HZK16的GB2312-80支撑的汉字有6763个,符号682个。其中顶级汉字有3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。大家在部分选择场面根本用不到这么多汉字字模,所以在应用时就可以只领到部分字体作为己用。

   
但Framebuffer本身不具有任何运算数据的力量,就只好比是一个临时存放水的水池.CPU将运算后的结果放到这几个水池,水池再将结果流到显示屏.
中间不会对数码做处理.
应用程序也得以平素读写这些水池的内容.在那种体制下,即使Framebuffer须要真正的显卡驱动的支撑,但具备突显义务都有CPU完毕,由此CPU
负担很重

HZK16字库是适合GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中超级汉字有
3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。

        
HZK16字库是契合GB2312标准的16×16点阵字库,HZK16的GB2312-80支撑的汉字有6763个,符号682个。其中顶级汉字有3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。大家在一些利用场馆根本用不到那般多汉字字模,所以在运用时就足以只领到部分字体作为己用。

HZK16字库里的16×16汉字一共需求256个点来显示,也就是说要求32个字节才能达到展现一个惯常汉字的目标。

framebuffer的装备文件一般是
/dev/fb0、/dev/fb1 等等。

咱俩在一部分应用场地根本用不到这么多汉字字模,所以在动用时就可以只领到部分字体作为己用。

HZK16字库里的16×16中国字一共须要256个点来突显,也就是说要求32个字节才能达到呈现一个惯常汉字的目标。

文件浏览器及数据相框,添加华语字库。我们明白一个GB2312汉字是由七个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符(注意:那只是编码的特许范围,不肯定都有字型对应,比如符号区就有很多编码空白区域)。上边以汉字“我”为例,介绍怎么着在HZK16文书中找到它对应的32个字节的字样数据。

可以用命令: #dd if=/dev/zero of=/dev/fb
清空显示器. 假若突显情势是 1024×768-8 位色,

HZK16字库里的16×16中国字一共必要256个点来突显,也就是说需求32个字节才能达到显示一个普通汉字的目标。

我们清楚一个GB2312汉字是由五个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符(注意:那只是编码的认可范围,不必然都有字型对应,比如符号区就有无数编码空白区域)。上边以汉字“我”为例,介绍如何在HZK16文件中找到它对应的32个字节的字样数据。

眼前说到一个汉字占七个字节,那多少个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的地点。所以要找到“我”在hzk16库中的地点就不可能不取得它的区码和位码。(为了分歧使用了区码和区号,其实是一个事物,别被自己误导了)

用命令:$ dd if=/dev/zero of=/dev/fb0
bs=1024 count=768 清空显示器;

咱俩知晓一个GB2312汉字是由多少个字节编码的,范围为0xA1A1~0xFEFE。A1-A9为符号区,B0-F7为汉字区。每一个区有94个字符(注意:那只是编码的认可范围,不必然都有字型对应,比如符号区就有比比皆是编码空白区域)。

前方说到一个中国字占五个字节,那七个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的地方。所以要找到“我”在hzk16库中的地点就务须取得它的区码和位码。(为了分裂使用了区码和区号,其实是一个事物,别被自己误导了)

区码:区号(汉字的率先个字节)-0xa0
(因为汉字编码是从0xa0区始发的,所以文件最前头就是从0xa0区初步,要算出相对区码)

用命令: #dd if=/dev/fb of=fbfile 
可以将fb中的内容保留下去;

上边以汉字”我”为例,介绍怎么样在HZK16文书中找到它对应的32个字节的字样数据。后面说到一个中国字占五个字节,那八个中前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的地点。所以要找到”我”在hzk16库中的地点就务须得到它的区码和位码。

区码:区号(汉字的首先个字节)-0xa0   
(因为汉字编码是从0xa0区启幕的,所以文件最前头就是从0xa0区初叶,要算出相对区码)

位码:位号(汉字的第三个字节)-0xa0

可以另行写回屏幕: #dd if=fbfile
of=/dev/fb;

区码:汉字的率先个字节-0xA0(因为汉字编码是从0xA0区启幕的,
所以文件最前边就是从0xA0区开端, 要算出相对区码)

位码:位号(汉字的第一个字节)-0xa0

那样我们就可以收获汉字在HZK16中的绝对偏移地方:

在应用Framebuffer时,Linux是将显卡置于图形形式下的.

位码:文件浏览器及数据相框,添加华语字库。汉字的其次个字节-0xA0

这么我们就足以获取汉字在HZK16中的相对偏移地点:

offset=(94*(区码-1)+(位码-1))*32

 

诸如此类我们就可以取得汉字在HZK16中的相对偏移地点:

offset=(94*(区码-1)+(位码-1))*32

诠释:1、区码减1是因为数组是以0为始发而区号位号是以1为始发的

    在应用程序中,一般通过将 FrameBuffer
设备映射到进度地址空间的点子利用,比如上面的程序就开辟 /dev/fb0
设备,

offset=(94*(区码-1)+(位码-1))*32

注脚:1、区码减1是因为数组是以0为开首而区号位号是以1为开首的

2、(94*(区号-1)+位号-1)是一个中国字字模占用的字节数

并通过 mmap 系统调用进行地址映射,随后用
memset 将显示器清空(那里假若显示形式是 1024×768-8
位色方式,线性内存形式):

注解:

            2、(94*(区号-1)+位号-1)是一个中国字字模占用的字节数

3、最后乘以32是因为汉字库文应从该义务起的32字节新闻记录该字的字样新闻(前边提到一个中国字要有32个字节突显)

int fb;

区码减1是因为数组是以0为开始而区号位号是以1为开始的

           3、最后乘以32是因为汉字库文应从该地点起的32字节音讯记录该字的字样信息(后面提到一个汉字要有32个字节显示)

 有了舞狮地址就可以从HZK16中读取汉字编码了

unsigned char* fb_mem;

(94*(区号-1)+位号-1)是一个中国字字模占用的字节数

有了摇头地址就足以从HZK16中读取汉字编码了,剩下的就是文件操作了,就不说了,要看代码(汉字)就是上面的:“hzk16汉字库的简短读写程序 ”,是一个最简便的c语言程序。

兑现思路:

fb = open (“/dev/fb0”, O_RDWR);

最终乘以32是因为汉字库文应从该岗位起的32字节音讯记录该字的字样音讯(前边提到一个中国字要有32个字节显示)

                                                 hzk16汉字库的简要读写程序

  1. 询问HZK编码,领会一下适合GB2312标准的中文点阵字库文件HZK16;
  2. 下载普通话GB2312的二进制点阵文件;
  3. 将HZK16.fnt文件放入nihongo文件夹中;
  4. 修改主makefile文件和app_make.txt文件,将原先装载nihongo.fnt的口舌替换成装载HZK16.fnt即可;
  5. 修改bootpack.c文件,将事先分配的装载阿拉伯语字体的内存扩充,载入字库的公文名;
  6. 在haribote/graphic.c中加上帮忙汉字的代码,增添一个函数用于体现汉字;
  7. 修改putfonts8_asc函数里if (task->langmode == 3)语句块;
  8. 测试程序。
  9. 专注:日文的编码是分为左半片段和右半部分,而大家运用的HZK16是分为上半部分和下半部分的。

fb_mem = mmap (NULL, 1024*768,
PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

自家画的图示:

hzk汉字点阵   
    
   int    i,j,k;   
   unsigned    char    incode[3]=”我”;    //    要读出的汉字   
   unsigned    char    qh,wh;   
   unsigned    long    offset;   
   //    占四个字节,    取其区位号   
   qh    =    incode[0]    –    0xa0;/ /获得区码            
   wh    =    incode[1]    –    0xa0;   / /得到位码               
   offset    =    (94*(qh-1)+(wh-1))*32;          /   
*赢得偏移地点*    /   
      
   FILE    *HZK;   
   char    mat[32];   
   if((HZK=fopen(“hzk16”,    “rb”))    ==    NULL)   
   {   
   printf(“Can’t    Open    hzk16\n”);   
   exit(0);   
   }   
   fseek(HZK,    offset,    SEEK_SET);   
   fread(mat,    32,    1,    HZK);

此处其他的地方相比较弄,第5步将大小修改一下,我的是nihongo = (unsigned
char *) memman_alloc_4k(memman, 55*94*32);

memset (fb_mem, 0, 1024*768);
//那些命令应该唯有在root可以举行

所以,’我’在HZK16 16*16点阵字库的寄放的行列为:

//显示

第6步,要专注,HZK16是上下两片段,分裂于日文的左右两部分的社团。

 

(一行一行地保留,共16行,每行2个字节, 共32个字节)

for(j=0;j<16;j++)
        for(i=0;i<2;i++)
            for(k=0;k<8;k++)
               
if(mat[j][i]&(0x80>>k)) /*测试为1的位则显得*/
                    {

代码如下:

效仿写一个

04 80 0E A0 78 90 08 90 08 84 FF FE 08 80 08 90

0A 90 0C 60 18 40 68 A0 09 20 0A 14 28 14 10 0C

                            printf(“%s”,’#’);

void putfont32(char *vram, int xsize, int x, int y, char c, char *font1, char *font2)
{
    int i,k,j,f;
    char *p, d ;
    j=0;
    p=vram+(y+j)*xsize+x;
    j++;
    //上半部分
    for(i=0;i<16;i++)
    {
        for(k=0;k<8;k++)
        {
            if(font1[i]&(0x80>>k))
            {
                p[k+(i%2)*8]=c;
            }
        }
        if(i%2==0){
            for(k=0;k<4;k++){
                f=p[k];
                p[k]=p[7-k];
                p[7-k]=f;
            }
        }else{
            for(k=0;k<4;k++){
                f=p[k+8];
                p[k+8]=p[15-k];
                p[15-k]=f;
            }
        }
       /* for(k=0;k<8/2;k++)
        {
            f=p[k+(i%2)*8];
            p[k+(i%2)*8]=p[8-1-k+(i%2)*8];
            p[8-1-k+(i%2)*8]=f;
        }*/
        if(i%2)
        {
            p=vram+(y+j)*xsize+x;
            j++;
        }
    }
    //下半部分
    for(i=0;i<16;i++)
    {
        for(k=0;k<8;k++)
        {
            if(font2[i]&(0x80>>k))
            {
                p[k+(i%2)*8]=c;
            }
        }
        if(i%2==0){
            for(k=0;k<4;k++){
                f=p[k];
                p[k]=p[7-k];
                p[7-k]=f;
            }
        }else{
            for(k=0;k<4;k++){
                f=p[k+8];
                p[k+8]=p[15-k];
                p[15-k]=f;
            }
        }
        /*for(k=0;k<8/2;k++)
        {
            f=p[k+(i%2)*8];
            p[k+(i%2)*8]=p[8-1-k+(i%2)*8];
            p[8-1-k+(i%2)*8]=f;
        }*/
        if(i%2)
        {
            p=vram+(y+j)*xsize+x;
            j++;
        }
    }
    return;
}

 

似乎下边那样:

                         }else{   printf(“%s”,’-‘);

 

1     fd_fb = open("/dev/fb0",O_RDWR);
 2     if(fd_fb < 0)
 3     {
 4         printf("can't open /dev/fb0 \n");
 5         return -1;
 6     }
 7     if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))            //取出可变信息
 8     {
 9         printf("can't get var \n");
10         return -1;    
11     }
12     if(ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))            //取出固定信息
13     {
14         printf("can't get fix \n");
15         return -1;    
16     }
17     screen_size = var.xres * var.yres * var.bits_per_pixel / 8;    //占内存大小 单位字节
18     line_width = var.xres *  var.bits_per_pixel / 8;         //一行像素大小
19     pixel_width =  var.bits_per_pixel / 8;               //一点像素大小
20     
21     fb_mem = (unsigned char *)mmap(NULL, screen_size, \       //mmap 系统调用进行地址映射
22         PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
23     if(fb_mem == (unsigned char *) -1)
24     {                                      
25         printf("can't mmap \n");
26         return -1;
27     }
28     memset(fb_mem, 0, screen_size);                   //清屏,黑色

以下是本身要好写的示范程序, 能够友善修改成其它的数目格式.(很简短,
所以没写注释)。

                              }

运行结果,大家在euc.txt中参预一些中国字。

 

示例源代码

    fclose(HZK);
     fclose(fp);

home88一必发 1

字符点阵显示

版本1

                               图形LCD模块ACM19264ASB的方块字突显

参考资料:

8*16像素的字符点阵

int main(void)

1引言

1. 30天操作系统扶助汉语。

一个字节8位来代表一行的8个像素是还是不是被入选点亮

{

在根据单片机的智能体系中,汉字突显模块是很关键的一个组成部分,它采纳广泛、操作简单、调试简便。

每个字符由16个字节表示

FILE* fphzk = NULL;

而是,在单片机上突显汉字也设有多少个难题。首先,单片机资源有限,我们不可能为了显得汉字占用太多的资源;其次,汉字存储读取相比麻烦,使用不便利;第三,汉字是经过点阵展现出来的,往往与LCD写入措施不平等,那就得进行转移和调整。

仅须求用asii码值乘以16就足以固定到当下字符的点阵地方

int i, j, k, offset;

值得注意的是,基于单片机的汉字显示不可以在字符LCD上落到实处。使用图形LCD有好多优点,不仅能显得汉字,而且可以完毕汉字动态移动和左右滚屏,完毕汉字与图片的鱼目混珠突显,同时功耗低。

 

int flag;

2依照单片机的汉字突显原理

1 static const unsigned char fontdata_8x16[FONTDATAMAX] = {
 2 
 3     /* 0 0x00 '^@' */
 4     0x00, /* 00000000 */
 5     0x00, /* 00000000 */
 6     0x00, /* 00000000 */
 7     0x00, /* 00000000 */
 8     0x00, /* 00000000 */
 9     0x00, /* 00000000 */
10     0x00, /* 00000000 */
11     0x00, /* 00000000 */
12     0x00, /* 00000000 */
13     0x00, /* 00000000 */
14     0x00, /* 00000000 */
15     0x00, /* 00000000 */
16     0x00, /* 00000000 */
17     0x00, /* 00000000 */
18     0x00, /* 00000000 */
19     0x00, /* 00000000 */
20 
21     /* 1 0x01 '^A' */
22     0x00, /* 00000000 */
23     0x00, /* 00000000 */
24     0x7e, /* 01111110 */
25     0x81, /* 10000001 */
26     0xa5, /* 10100101 */
27     0x81, /* 10000001 */
28     0x81, /* 10000001 */
29     0xbd, /* 10111101 */
30     0x99, /* 10011001 */
31     0x81, /* 10000001 */
32     0x81, /* 10000001 */
33     0x7e, /* 01111110 */
34     0x00, /* 00000000 */
35     0x00, /* 00000000 */
36     0x00, /* 00000000 */
37     0x00, /* 00000000 */
38 
39         /*****
40     ****
41     ****
42     ****
43     ****
44     ****
45     ****
46     ****
47     *****/
48 
49     /* 255 0xff '' */
50     0x00, /* 00000000 */
51     0x00, /* 00000000 */
52     0x00, /* 00000000 */
53     0x00, /* 00000000 */
54     0x00, /* 00000000 */
55     0x00, /* 00000000 */
56     0x00, /* 00000000 */
57     0x00, /* 00000000 */
58     0x00, /* 00000000 */
59     0x00, /* 00000000 */
60     0x00, /* 00000000 */
61     0x00, /* 00000000 */
62     0x00, /* 00000000 */
63     0x00, /* 00000000 */
64     0x00, /* 00000000 */
65     0x00, /* 00000000 */
66 
67 };

unsigned char buffer[32];

2.1汉字字模

 

unsigned char word[3] = “我”;

汉字相似是以点阵式存储的,如16×16,24×24点阵(即汉字的字样),每个汉字由32字节(16点阵)或72字节(24点阵)描述。按照汉字的不等字体,也可分为草书字模、黑体字模、石籀文字模等等。

刷写8*16字符点阵

unsigned char key[8] = {

汉字的字样其实是汉字字形的图形化。对于16点阵字模,就是把汉字写在一个16×16的网格内,汉字的笔画能过某网格时该网格就对应1,否则该网格对应0,这样每一网格均对应1或0,把对应1的网格连起来看,就是这么些汉字。汉字就是这样经过字节表示点阵存储在字库中的。

 

0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01

为了方便寻找所需汉字的点阵,每个汉字都与一个双字节的内码一一对应。通过汉字的内码能够测算出它的点阵先导字节。现以16点阵为例表达。

1 lcd_put_ascii(int x, int y, unsigned char c )
 2 {
 3     unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
 4     int i, b;
 5     unsigned char byte;
 6     
 7     for(i = 0; i < 16; i++)
 8     {
 9         byte = dots[i];
10         
11         for(b = 7; b >= 0; b --)
12         {
13             if(byte & (1<<b))
14             {
15                 /* 显示 */
16                 lcd_put_pixel(x + 7 - b, y + i, 0xffffff);//白
17             }
18             else
19             {
20                         /* 不显示 */
21                 lcd_put_pixel(x + 7 - b, y + i, 0);//黑
22             
23             }
24         }
25     }
26     

};

先由内码总括出它在汉字库中的区位码,计算公式为:

 

fphzk = fopen(“hzk16”, “rb”);

区码=内码第一字节-160

拔取HZK16
字库,将它拷贝到内存中,使用时间接用数组指向某个汉字所在地点

home88一必发,if(fphzk == NULL){

位码=内码第二字节-160

 使用#include <sys/stat.h>中的fstat()函数来总计HZK16文件音信

fprintf(stderr, “error hzk16\n”);

再由区位码可以博得它在汉字库中字模第三个字节的职位:

 

return 1;

(区码×94+位码)×32
于是,可以向后连连读出由32个字节组成的该字的点阵数据。

    fd_hzk16 =  open("HZK16",O_RDWR);
    if(fd_hzk16 < 0)
    {
        printf("can't open HZK16 \n");
        return -1;
    }

    if(fstat(fd_hzk16, &hzk_stat))    //得到文件统计信息
    {
        printf("can't get fstat\n");
        return -1;

    }
    hzk_mem = (unsigned char *)mmap(NULL, hzk_stat.st_size, \
        PROT_READ, MAP_SHARED, fd_hzk16, 0);
    if(hzk_mem == (unsigned char *) -1)
    {
        printf("can't mmap hzk_mem\n");
        return -1;
    }

}

2.2汉字彰显

 

offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32;

汉字占用资源太多(如16点阵,每个汉字就需32字节),因而寻常把汉字库放在EEPROM里,必要彰显某个汉字时,先算出它的区位码,再求出点阵早先地方,从EEPROM中各类调出该字的点阵数据,存在缓冲区里,最终依次送往LCD呈现,描出该字。需求注明的是汉字存储格局与LCD突显格局有肯定距离。

 

fseek(fphzk, offset, SEEK_SET);

正文使用另一种突显格局,即事先将先后用到的汉字、符号和数码(为了节省彰显空间,可以将数据压成8×16点阵),编成一个文书文件,用一段小程序做出相应小的汉字库,这些小字库的汉字点阵数据取自于一般汉字库。再经过转换和调整,得到新的汉字库,最终把新字库固化在EEPROM中。单片机只需按序号读出点阵字节,送往LCD即可显示所需汉字。减轻了单片机的负责,去除了繁琐的物色内码、求先导地方、转换、调整等工作,进步了系统可信性。

HZK16
字库是顺应GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中超级汉字有3755个,按
声序排列,二级汉字有3008个,按偏旁部首排列。我们在一些用参与合根本用不到那样多汉字字模,所以在运用时就足以只领到部分字体作为己用。

fread(buffer, 1, 32, fphzk);

表116点阵汉字字库存储方式

 

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

3自定义小字库的打造

HZK16字库里的16×16中国字一共须求256个点来展现,也就是说需求32个字节才能达成呈现一个经常汉字的目标。

printf(“%02X “, buffer[k]);

一流的汉字库可接纳UCDOS下的字库,如16点阵字库HZK16。需要256K空间,用了较大的EEPROM,又不便宜读取,而事实上行使中须要的汉字又相当少,因此我们得以自己制作小的汉字库,在那么些小字库里只包括系统必要的汉字。这样,一方面节省读取时间,另一方面大大地节约了资源。

我们知晓一个GB2312汉字是由多少个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符(注意:那只是编码的许可限制,不肯定都有字型对应,比如符号区就有不计其数编码空白区域)。下边以汉字“我”为例,介绍怎么着在HZK16文本中找到它对应的32个字节的字样数据。

}

平抑篇幅,那里唯有给出流程图(假定事先将所需汉字写到了一个文本文件),如图1所示。

 

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

眼前说到一个中国字占八个字节,那五个中前一个字节为该汉字的区号,后一个字节为该字的
位号。其中,每个区记录94个汉字,位号为该字在该区中的地方。所以要找到“我”在hzk16库中的地方就不可能不得到它的区码和位码。(为了不一致使用了区码
和区号,其实是一个东西,别被自己误导了)

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

将一切汉字字库存放在EPROM或E2PROM内,程序根据要呈现汉字的机内码来调用汉字字模。

 

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

一些高端单片机,如一加的M68300连串32位单片机,寻址范围可达8M,液晶展现常用的16×16汉字库二进制数据文件为两百多k,将汉字字库存入大容量的E2PROM,通过地点线可寻址到汉字库中的每一个汉字。

区码:区号(汉字的第一个字节)-0xa0   
(因为汉字编码是从0xa0区伊始的,所以文件最前方就是从0xa0区早先,要算出相对区码)

flag = buffer[k*2+j]&key[i];

在处理器中对汉字的分辨是通过机内码来兑现的,汉字标准机内码为两字节代码。汉字在汉字库中是规行矩步区位来排列的,每一区中有94个汉字,每个汉字都对应唯一的区号和在本区的位号,汉字输入法中就有区位码方法,实际上,汉字机内码和区位码有正规的对应关系,某个汉字在字库中的区号加上0xa0等于其机内码的高字节,位号加上0xa0等于其机内码的低字节,由此很不难通进度序计算出要展现的方块字在汉字库中的区位号,即得到了其在汉字库中的偏移地址。

位码:位号(汉字的第三个字节)-0xa0

printf(“%s”, flag?”●”:”○”);

由于E2PROM中储存了全副汉字库,只须在硬件上设定存放汉字库的存储器片选地址,直接将汉字作为字符数组付给汉字展现函数,通过机内码总括出区号和位号,即可方便地对汉字字模进行调用了。与前三种办法相比较,无须事先提取字模和设定其地方用于程序调用,由此在展开程序升级,涉及到汉字彰显时,不用更改汉字字模数据。

那般大家就能够赢得汉字在HZK16中的相对偏移地点:

}

                                  汉字的字样与显示–汉字的代码连串
目 录
  1.1 汉字机内码
  1.2 汉字地址码
  1.3 汉字沟通码
  1.4 汉字字型码

offset=(94*(区码-1)+(位码-1))*32

}


 

printf(“\n”);

  在汉字新闻处理系统中留存着冒尖汉字编码。一般的话,在系统的不比地位,可按照其条件给汉字定以相应的编码,因为在汉字消息处理系统中留存着数种汉字编码。那几个编码构成了一个中国字的代码连串。

诠释:1、区码减1是因为数组是以0为始发而区号位号是以1为开始的

}

1.1、汉字机内码
  汉字机内码(亦称汉字内码)是系统里面处理和存储汉字而利用的代码。众所周知,西文字符的机内码多选取一个字节来代表的ASCII码,有的系统则利用EBCDIC码。一般只行使7位来表示128个字符,而把高位用作奇偶校验(或者不用)。我国的国标GB2312-80规定,一个汉字用多少个字节表示,近日确定每个字节也只用七位,其高位未作定义。
  为了有限协理系统的中西文包容,意味着系统的机内码中务必维持ASCII(IBM-PC选取该码作为西文字符的机内码)的选择,同时又要允许汉字机内码的施用,并且使两者之间没有争执。即使用GB2312-80中的国标码作为机内码,则在系统中并且存在ASCII码和国标码时,将会生出二义性。例如,机内有四个字节的内容分别为30H和21H,它们既可以代表汉字“啊”的国标码,又可以表示字符“0”和“!”的ASCII码。所以,一清二楚地利用国标码作为汉字机内码是格外的,必须求加以合适的更换。
  一般境况下是将国标码的每个字节的高职位成1,作为汉字机内码,那种编码称作为变形国标码。那样作既缓解了西文机内码与汉字机内码的二义性,又保证汉字机内码与国标码之间有极简单的相应关系。其团伙如下:

     2、(94*(区号-1)+位号-1)是一个汉字字模占用的字节数

fclose(fphzk);

内码 ch1 ch2
   不 不
1字节 1字节

   3、最后乘以32是因为汉字库文应从该职位起的32字节音信记录该字的字样音信(前边提到一个汉字要有32个字节显示)

fphzk = NULL;

  依据CGB2312-80中的汉字、图形符号,根据其地方分为94个“区”,每个区包涵94个汉字,每个汉字字符又称为“位”。其中“区”的序号,由01到94,“位”的序号,也是从01到94。若以横向表示“位”号,纵向表示“区”号,则“区”和“位”构成一个二维坐标。给定一个“区”值和“位”值就可以规定一个唯一的方块字或图形符号。所以4位数字就足以唯一确定一个汉字或标志,上面给出汉字的区内和内码对应关系表。

 

return 0;

区位码(10进制) 内码(16进制)
区号 位号 高字节 低字节
1—9 1—94 A1—A9 A1—FE
10—12 1—94 AA—AC A1—FE
13—15 1—94 AD—AF A1—FE
16—87 1—94 B0—F7 A1—FE

 1 void lcd_put_chinese(int x, int y, unsigned char *str)
 2 {
 3     unsigned int area = str[0] - 0xa1;
 4     unsigned int where = str[1] - 0xa1;
 5     unsigned char *dots = hzk_mem + (area * 94 + where) * 32;
 6     unsigned char byte;
 7     int i,j,b;
 8 
 9     for(i=0; i < 16; i++)
10         for(j=0; j < 2; j++)
11         {
12             byte = dots[i*2 + j];
13             for(b=7; b >=0; b--)
14             {
15                 if(byte & (1<<b))
16                 {
17                     /* 显示 */
18                     lcd_put_pixel(x + j * 8 + 7 - b, y + i, 0xffffff);//白
19                 }
20                 else
21                 {
22                             /* 不显示 */
23                     lcd_put_pixel(x + j * 8 + 7 - b, y + i, 0);//黑
24                 
25                 }
26             }
27         }
28 
29 }

}

1.2、汉字地址码
  汉字地址码是指汉字字模库(那里主要指整字形的点阵字模库)中贮存各汉字字形音信的逻辑地址码。中文系统中的汉字字模库有二种,它们分别存放在RAM(或EPROM)中和磁盘上。故汉语系统中的汉字地址码有二种,一种拔取内存地址数来代表(对应RAM和EPROM中的字库),其余一种采用盘地址来代表(对应于磁盘中的字库)。由于中文系统的汉字字模库中汉字字形音讯排列的条条框框,使得粤语系统的汉字字模库中的汉字字形新闻排列连串的规则,使得中文系统的汉字地址码与汉字机内码之间存在着一个大致的函数关系。

 

版本2

1.3、汉字调换码
  汉字沟通码是一种用于汉字音信处理系统之间,或者与报导系统之间开展新闻互换的汉字代码。汉字互换码位于一台机器的言语和另一台机械(包涵输出设备与记录设备)的入口之间。为了要达到系统装备之间或记录介质之间新闻互换的目标,汉字交流码必须利用联合的情势。近来境内统计机种类所选取的正统音信处理沟通码,是依照国家标准制定的,即GB1988

《新闻处理交流使用的七位编码字符集》;还制定了对应的代码扩展标准,即GB2311

《音信处理沟通使用的七位编码字符集的扩展方法》。因为汉字交流码应与GB1988包容,并根据GB2311所确定的形式开展编制。由于汉字数量远远超越七位编码所能表示的六千三个常用汉字制定了互换码的国家标准,即GB2312

《音信沟通用汉字编码字符基本集》,其中每个汉字用对应于GB1988的四个七位码来表示。

 

int main(void)

1.4、汉字字型码
  由于近年来汉字新闻处理系统中暴发汉字字形的办法大多是数字式的,即以点阵的点子形成汉字,过汉字字形码是指确定一个汉字字形码也就不一致。

对像素举行瞄颜色

{

                                                      汉字库的接纳 

 

FILE* fphzk = NULL;

UCDOS软件中的文件HZK16为16×16的国标汉字点阵文件,以二进制格式存储。在文书HZK16中,按汉字区位码从小到大依次存有国标区位码表中的兼具汉字,每个汉字占用32个字节,每个区为94个汉字。

 1 void lcd_put_pixel(int x, int y, unsigned int color)
 2 {
 3     unsigned char *pen_8 = fb_mem + y * line_width + x * pixel_width;     //当前像素对应内存位置
 4     unsigned short *pen_16;
 5     unsigned int *pen_32;
 6 
 7     unsigned int red, blue, green;
 8     
 9     pen_16 = (unsigned short *)pen_8;
10     pen_32 = (unsigned int *)pen_8;
11     
12     switch(var.bits_per_pixel)
13     {
14         case 8:
15         {
16             *pen_8 = color;            //对应调色板颜色
17             
18             break;
19         }
20         case 16:
21         {
22             /* 5*6*5 */
23             red   = (color >> 16) & 0xff;
24             green = (color >> 8) & 0xff;
25             blue  = (color >> 0) & 0xff;
26 
27             color = ((red >> 3 ) << 11) | ((green >> 2) << 5) | ( blue >> 3);
28             
29             /* 颜色数据为高位 */
30             *pen_16 = color;
31             
32             break;
33         }
34         case 32:
35         {
36             *pen_32 = color;
37             break;
38         }
39         
40     }
41 
42 }

int i, j, k, offset;

在PC机的文件文件中,汉字是以机内码的花样储存的,每个汉字占用七个字节:首个字节为区码,为了与ASCII码差别,范围从十六进制的0A1H发端(小于80H的为ASCII码字符),对应区位码中区码的第一区;第三个字节为位码,范围也是从0A1H开头,对应某区中的首个位码。那样,将汉字机内码减去0A0AH就得该汉字的区位码。

 

int flag;

比如汉字“房”的机内码为十六进制的“B7BF”,其中“B7”表示区码,“BF”表示位码。所以“房”的区位码为0B7BFH-0A0A0H=171FH。将区码和位码分别转换为十进制得汉字“房”的区位码为“2331”,即“房”的点阵位于第23区的第31个字的职位,约等于在文书HZK16中的地方为第32×[(23-1)
×94+(31-1)]=67136B将来的32个字节为“房”的显得点阵。

    lcd_put_ascii(var.xres / 2, var.yres / 2, 'a');
    printf("中: chinese code: %02x %02x\n", str[0], str[1]);
    lcd_put_chinese(var.xres / 2 + 32, var.yres / 2, str);

unsigned char buffer[32];

上边给出一个基于汉字机内码(两字节)在汉字库中搜索汉字的字样的主次。字库文件分成四部分,分别设有四片27512(并行EPROM)中。读出的字样存入hz_buffer[32]数组中。

 

unsigned char word[5];

int8
hz_buffer[32];//定义32字节数组,用于存储点阵字模,该字模为横排字模。

显示屏输出‘a’,“中”

unsigned char key[8] = {

#define int8 unsigned char

 

0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01

#define int16 unsigned int

};

#define int32 unsigned long

fphzk = fopen(“hzk16”, “rb”);

/*

if(fphzk == NULL){

函数void read_hz(int16
hz)的参数hz为两字节的机内码,调用方法:read_hz(‘汉’);

fprintf(stderr, “error hzk16\n”);

对ASCII字符,则read_hz(‘A’+0xa380);读取

return 1;

*/

}

void   read_hz(int16 hz){

while(1){

void   *void_p;//定义一个空类型指针

printf(“输入要生成字模的汉字(七个):”);

int8   *int8_p;//定义一个unsigned char 指针

for(;;){

int8    i;   //定义一个循环变量

fgets((char*)word, 3, stdin);

int16 area_l,area_h;//定义三个整型变量,用于存储区码和位码

if(*word == ‘\n’)

int32 pos;  //定义一个long型变量,用于存储总计所得字模在字库的职位,

break;

int8   chip;  //字模所在的芯片,可用74HC138等等的芯片译码。

offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32;

int16 addr;  //在某一芯片64K字节空间内的地方

fseek(fphzk, offset, SEEK_SET);

   

fread(buffer, 1, 32, fphzk);

void_p=&hz;    //空指针指向机内码的低字节

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

int8_p=void_p;    //char类型指针指向空指针,即机内码的低字节

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

area_l=*int8_p-0xa0; //机内码低字节减去0xa0得到区码

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

area_h=*(int8_p+1)-0xa0; //机内码高字节减去0xa0得到位码

flag = buffer[k*2+j]&key[i];

pos=32*((int32)((area_h-1)*94)+area_l-1);
//计算在一个整机的字库中的地点(256K)

printf(“%s”, flag?”●”:”○”);

//pos=116672;        
//那是“请”字在HZK16文本中的地方,单位为字节。用于测试

}

if(pos<64*1024)   //在率先片27512芯片

}

    {

printf(“\n”);

       chip=0;addr=(int16)pos;

}

    }

printf(“uchar code key[32] = {“);

else if((pos>=64*1024)&&(pos<128*1024)) //在其次片27512芯片

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

    {

printf(“0x%02X,”, buffer[k]);

       chip=1;

}

       addr=(int16)pos;  

printf(“0x%02X};\n”, buffer[31]);

    }

printf(“\n”);

else if((pos>=128*1024)&&(pos<192*1024)) //在第三片27512芯片

}

    {

}

       chip=2;

fclose(fphzk);

       addr=(int16)pos;

fphzk = NULL;

    }   

return 0;

else if((pos>=192*1024)&&(pos<256*1024)) //在第四片27512芯片

}

    {

       chip=3;

       addr=(int16)pos;         

    }

select_chip(chip);   //选择第chip片27512芯片

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

    {

      hz_buffer[i]=read_data(addr+i); //读取一字节的多寡

    }

}

   
 在实际上中,由于现很少使用EPROM芯片,可以用并口、SPI,I2C接口的大容量Flash、EEPROM芯片。但I2C接口速度较慢,突显汉字的进程将会很慢,能够在部分相比较少字场馆使用;而SPI接口的存储芯片速度较快,接口不难,对于一般的行使场面依然得以满意的;对于大气施用的场地,可以使用并行接口,它具储存空间大,读取速度快的特征,如使用AT29多级的Flash存储器,单片容量可以达标256K之上,就不必要分开储存,但其急需较多的IO口,接口复杂。所以应依据实际来抉择存储器。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图