字符编码

来源:互联网 发布:淘宝发货单打印软件 编辑:程序博客网 时间:2024/06/13 21:50

    在利用单片机进行开发时,应该如何通过串口显示汉字呢?

    众所周之,显示单个字符是,只需要将字符的ASCII值表示即可。如果要显示在上位机的串口中时,只需要串口按照ASCII的编码方式解析这些以ASCII表示的字符即可;如果要显示在不带字库的液晶屏上,则要根据显示的内容对每个像素点进行操作;如果要显示在带字库的液晶屏上,则要通过给液晶屏控制器相应的编码予以显示。

    一般在嵌入式(单片机)的字符集中,使用的是GBK汉字编码方式,在用串口调试的时候,一个串口发送汉字,另一个串口用十六进制显示,比如:一个串口发送“汉”,另一个串口则显示“BA BA(机内码)”,从http://bianma.supfree.net/sos.asp?id=6597可以查到,此时采用的就是GBK编码(这里GBK编码为已经换算为16进制的机内码0xBABA,区位码(GB2312)2626是十进制的,首先得换算为16进制,然后各位都加20H和80H就可以换算为十六进制的机内码)。为什么在嵌入式行业采用的是GBK编码呢?主要是可以减少字库容量从而可以减少成本。

    下面学习一下常用的一些字符编码方式:

    ANSI : 这是美国国家标准协会制定的编码格式,例如"A汉" 在这种编码方式下的内存值为 41 BA BA ,'A'占用一个字节,"汉"用两个字节,而且 BA BA 正是 GBK内码的值, 那让我们先认识GBK编码.

    GB2312,GBK,GB18030:都是中国人自己发明的(中国之外并不使用的), 他们出现的时间顺序是GB2312 -> GBK -> GB18030 ,他们是包含关系,GB我猜是 "国标" 的意思 "k" 可能是 "扩展", 这些编码都是书面协议,要在计算机内部表示所以GB2312的内存值须在原来的每个字节值(区位码)上加0x80得到机内码,加上0x80是为了使得每个字节的最高位为1,这样就可以在内存中区分汉字和ASCII了[因为ASCII的最高位都为0]. 但是后来要在GB2312上扩展(得到GBK,GB18030),就需要更多的编码空间,所以GBK,GB18030就没有要求第二个字节的的最高位为1了,而是通过第一个字节来判断这是一个字节的ASCII还是两个字节的GBK.另外需要说明一点GB2312,GBK,GB18030是向下兼容的,例如 "汉" 在GB2312,GBK,GB18030中都是“BA BA”。

   另外,GB2312,GBK并没有因为GB18030的出现退出市场,在一些嵌入式设备中还是应用广泛的,因为减少字库容量可以大大减少成本.

   回到之前的ANSI, 我们大概知道了GBK(不知道人们为什么喜欢用GBK而不是GB18030,姑且认为是GBK只有3个字母,书写方便吧!),那么ANSI又是怎么回事呢? ANSI就像一个指针,本身没有内容,如果指向"中国的编码",那么它就是GBK,如果指向"印度的编码",他就是x??x.也就是说在中国ANSI是GBK,在日本ANSI是XXX,在印度ANSI是???,但是他们在windows的记事本中都只能看到ANSI.但是ANSI也做了一些小的变动,就像刚才一样,'A'在内存中只占用了一个字节,也就是说ANSI = ASCII + 本地编码,单片机里面就是这样定义的,主要由ASCII和GBK编码的。

   Unicode:但是,我们怎么在一个汉语资料中书写日文符号呢?这时,Unicode出现了,Unicode把世界上的所有文字符号都包含进来了,不仅解决了刚才说的问题,而且程序员用Unicode写的程序可以在全世界的电脑上运行.C语言中用wchar_t表示。所以在编写可以在世界范围流通的程序时最好采用Unicode编码格式。Unicode码是一种国际标准编码,采用二个字节编码,与ANSI码不兼容。目前,在网络、Windows系统和很多大型软件中得到应用。

   UCS:据说UCS是和Unicode一样的工程,最后两个工程达成共识,所以编码完全兼容.所以我就把UCS看做Unicode.这里的UCS-2就是常说的UCS,只使用了两个字节保存一个字符,而UCS-4则是使用4个字节保存一个字符.

   UTF-8:(ucs transformation format),为什么要创造UTF-8呢?其中一个原因是:0x00在C语言及操作系统文件名(等..)中有特殊意义(如字符串结尾),然而按照Unicode编码的话,很可能这个字符的第一个字节(高字节)为非零数值,而低字节为零,这样C语言就会误认为这是字符串的结尾.所以UTF-8的一个功能是保证Unicode编码表中不出现0x00(当然正常的0x00是可以的)。网络一般采用的是这种编码,不如在浏览器中输入包含中文字符的网络地址,浏览器会自动转换编码。

   汉字系统中的过程包括区位码、国标码和机内码,其中的转换关系如下:
      1.区位码(十进制)转换成区位码(十六进制)。 这里要把前两个位换成十六进制,然后后两位换成十六进制。 例如,”汉“字的区位码是2626,这样把26转换为16进制数1AH,得到十六进制数1A1AH。
      2.国标码=区位码(十六进制)+2020H 例如,1A1AH+2020H=3A3AH 得到国标码GB2312或GBK
      3.汉字机内码=国标码+8080H 机内码就是3A3AH+8080H=BABAH,ASCII码是八位的一个字节 最高位为0,这样可以区分和汉字编码的区别。

例如:
                     区位码                国标(GBK、GB2312)         内码
      "汉"    2626D=1A1AH                   3A3AH                BABAH
      国标 = 区位码 + 0x20 (每个字节)
      内码 = 国标(GBK) + 0x80 (每个字节)

      区位码:按照先区后位的方法对汉字进行的数字编码,以“汉”字为例,“汉”按照GB2312-80处于第26区(行)的第26位(列)个字,它的区位码就是0d2626,使用区位输入法,用2626就可以输入“汉”。这个2626也就是区位输入法下“汉”字的外码,若是使用拼音输入法,那么汉字的外码则是 han 。(所有的汉字键盘输入法都是外码方案)

      机内码:汉字在传输的数据包中是机内码。区位码(外码)仅仅是输入码,不在计算机当中,保存在计算机中时,要转换为机内码。

      注意:一般在使用中,查询到的GBK编码为已经转换为机内码的汉字编码,无需再次转换,因为没有人使用区位输入法。在使用带字库的液晶屏时,只需要输出机内码就行了!!!