热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【连载】【FPGA黑金开发板】NIOSII那些事儿LCD中英文字符显示(二十三)

声明:本文为原创作品,版权归本博文作者所有,如需转载,请注明出处http:www.cnblogs.comkingst这一节&

声明:本文为原创作品,版权归本博文作者所有,如需转载,请注明出处http://www.cnblogs.com/kingst/

3

      这一节,我们在上一节的基础上,来研究英文变宽字体以及中文的字体显示的解决方案。

      在LCD上显示字符,不管是英文还是中文,都需要有字库支持。在有些LCD模块中,已经将字库文件烧写到了芯片当中,这样的字库有优点也有缺点。优点是操作简单,而缺点就是不灵活,显示的效果不够好,而且性价比也不高。FPGA黑金开发板选用的COG液晶是本身不带字库文件的液晶,我们在这里将研究一种通用的中英文字符显示方法,让大家充分了解如何利用外部字库文件实现字符显示,让我们的液晶显示更漂亮的字体。

      英文字库

      我们首先来研究英文字库的结构。英文字库使用的是ASCII码,起码值是0到127,其寻址公式为:

英文点阵数据在英文点阵字库中的偏移 = 英文的ASCII码 * 一个英文字模占用的字节数

我们使用的字库是tahoma字体,高度为16位,而字体的宽度是变宽的。在下表的tahoma_font_offset[]中,注释部分与偏移量是一一对应的,比如!,它的地址偏移量为7,它的宽度为11-7=4个,也就是说

字符宽度 = 它的下一个字符的偏移量 - 它本身的偏移量

#ifndef TAHOMA_H_
#define TAHOMA_H_
//字符的相对偏移量
unsigned int tahoma_font_offset[]&#61;{// ! " # $ % & &#39; (0 ,3 ,7 ,11 ,19 ,25 ,36 ,43 ,45 ,49 ,// ) * &#43; , - . / 0 1 253 ,59 ,67 ,71 ,75 ,79 ,83 ,89 ,95 ,101,// 3 4 5 6 7 8 9 : ; <107,113,119,125,131,137,143,147,152,159,// &#61; > ? &#64; A B C D E F168,175,180,190,197,203,210,217,223,229,// G H I J K L M N O P236,243,247,252,258,263,271,278,286,292,// Q R S T U V W X Y Z300,307,313,319,326,332,342,348,354,360,// [ \ ] ^ _ &#96; a b c d364,368,372,380,387,392,398,404,409,415,// e f g h i j k l m n421,425,431,437,439,442,447,449,457,463,// o p q r s t u v w x469,475,481,485,490,494,500,506,514,520,// y z { | } ~526,531,536,540,545,553
};const char font_tahoma_8[]&#61;{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0xF0,0x00,0x00,0x00,0x00,0x00,0x38,
0x00,0x00,0x00,0x38,0x00,0x00,0x02,0x00,0x0E,0x40,0x03,0xC0,0x0E,0x70,0x03,0xC0,
0x02,0x70,0x00,0x40,0x00,0x00,0x08,0xC0,0x09,0x20,0x3F,0xF8,0x09,0x20,0x06,0x20,
0x00,0x00,0x00,0x60,0x00,0x90,0x00,0x90,0x0C,0x60,0x03,0x00,0x00,0xC0,0x06,0x30,
0x09,0x00,0x09,0x00,0x06,0x00,0x00,0x00,0x07,0x60,0x08,0x90,0x08,0x90,0x09,0x60,
0x06,0x00,0x05,0x80,0x08,0x00,0x00,0x38,0x00,0x00,0x07,0xC0,0x18,0x30,0x20,0x08,
0x00,0x00,0x20,0x08,0x18,0x30,0x07,0xC0,0x00,0x00,0x02,0x80,0x01,0x00,0x07,0xC0,
0x01,0x00,0x02,0x80,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x0F,0xE0,0x01,0x00,
0x01,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
0x01,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,
0x07,0xC0,0x00,0x38,0x00,0x00,0x07,0xE0,0x08,0x10,0x08,0x10,0x08,0x10,0x07,0xE0,
0x00,0x00,0x00,0x00,0x08,0x20,0x0F,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x0C,0x20,
0x0A,0x10,0x09,0x10,0x08,0x90,0x08,0x60,0x00,0x00,0x04,0x20,0x08,0x10,0x08,0x90,
0x08,0x90,0x07,0x60,0x00,0x00,0x01,0x80,0x01,0x40,0x01,0x20,0x0F,0xF0,0x01,0x00,
0x00,0x00,0x04,0xF0,0x08,0x90,0x08,0x90,0x08,0x90,0x07,0x10,0x00,0x00,0x07,0xC0,
0x08,0xA0,0x08,0x90,0x08,0x90,0x07,0x00,0x00,0x00,0x00,0x10,0x0C,0x10,0x03,0x10,
0x00,0xD0,0x00,0x30,0x00,0x00,0x07,0x60,0x08,0x90,0x08,0x90,0x08,0x90,0x07,0x60,
0x00,0x00,0x00,0xE0,0x09,0x10,0x09,0x10,0x05,0x10,0x03,0xE0,0x00,0x00,0x00,0x00,
0x0C,0xC0,0x00,0x00,0x00,0x00,0x20,0x00,0x1C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x00,0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x00,0x00,0x02,0x80,
0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x00,0x00,0x00,0x00,
0x08,0x20,0x04,0x40,0x04,0x40,0x02,0x80,0x02,0x80,0x01,0x00,0x00,0x00,0x00,0x10,
0x0B,0x10,0x00,0x90,0x00,0x60,0x00,0x00,0x07,0xC0,0x08,0x20,0x13,0x90,0x14,0x50,
0x14,0x50,0x17,0xD0,0x04,0x10,0x04,0x20,0x03,0xC0,0x00,0x00,0x0E,0x00,0x03,0xC0,
0x02,0x30,0x02,0x30,0x03,0xC0,0x0E,0x00,0x00,0x00,0x0F,0xF0,0x08,0x90,0x08,0x90,
0x08,0x90,0x07,0x60,0x00,0x00,0x03,0xC0,0x04,0x20,0x08,0x10,0x08,0x10,0x08,0x10,
0x08,0x10,0x00,0x00,0x0F,0xF0,0x08,0x10,0x08,0x10,0x08,0x10,0x04,0x20,0x03,0xC0,
0x00,0x00,0x0F,0xF0,0x08,0x90,0x08,0x90,0x08,0x90,0x08,0x10,0x00,0x00,0x0F,0xF0,
0x00,0x90,0x00,0x90,0x00,0x90,0x00,0x90,0x00,0x00,0x03,0xC0,0x04,0x20,0x08,0x10,
0x09,0x10,0x09,0x10,0x0F,0x10,0x00,0x00,0x0F,0xF0,0x00,0x80,0x00,0x80,0x00,0x80,
0x00,0x80,0x0F,0xF0,0x00,0x00,0x08,0x10,0x0F,0xF0,0x08,0x10,0x00,0x00,0x08,0x00,
0x08,0x10,0x08,0x10,0x07,0xF0,0x00,0x00,0x0F,0xF0,0x01,0x80,0x02,0x40,0x04,0x20,
0x08,0x10,0x00,0x00,0x0F,0xF0,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x0F,0xF0,
0x00,0x30,0x00,0xC0,0x03,0x00,0x00,0xC0,0x00,0x30,0x0F,0xF0,0x00,0x00,0x0F,0xF0,
0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x0F,0xF0,0x00,0x00,0x03,0xC0,0x04,0x20,
0x08,0x10,0x08,0x10,0x08,0x10,0x04,0x20,0x03,0xC0,0x00,0x00,0x0F,0xF0,0x01,0x10,
0x01,0x10,0x01,0x10,0x00,0xE0,0x00,0x00,0x03,0xC0,0x04,0x20,0x08,0x10,0x08,0x10,
0x18,0x10,0x24,0x20,0x23,0xC0,0x00,0x00,0x0F,0xF0,0x01,0x10,0x01,0x10,0x03,0x10,
0x04,0xE0,0x08,0x00,0x00,0x00,0x08,0x60,0x08,0x90,0x08,0x90,0x08,0x90,0x07,0x10,
0x00,0x00,0x00,0x10,0x00,0x10,0x0F,0xF0,0x00,0x10,0x00,0x10,0x00,0x00,0x07,0xF0,
0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0xF0,0x00,0x00,0x00,0x70,0x03,0x80,
0x0C,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x00,0x70,0x03,0x80,0x0C,0x00,0x03,0x80,
0x00,0x70,0x03,0x80,0x0C,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x0C,0x30,0x02,0x40,
0x01,0x80,0x02,0x40,0x0C,0x30,0x00,0x00,0x00,0x30,0x00,0xC0,0x0F,0x00,0x00,0xC0,
0x00,0x30,0x00,0x00,0x0C,0x10,0x0A,0x10,0x09,0x90,0x08,0x50,0x08,0x30,0x00,0x00,
0x3F,0xF8,0x20,0x08,0x20,0x08,0x00,0x00,0x00,0x38,0x07,0xC0,0x38,0x00,0x00,0x00,
0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x10,
0x00,0x20,0x00,0x40,0x00,0x80,0x00,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,
0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x06,0x00,0x09,0x40,0x09,0x40,0x09,0x40,0x0F,0x80,0x00,0x00,0x0F,0xF8,0x08,0x40,
0x08,0x40,0x08,0x40,0x07,0x80,0x00,0x00,0x07,0x80,0x08,0x40,0x08,0x40,0x08,0x40,
0x00,0x00,0x07,0x80,0x08,0x40,0x08,0x40,0x08,0x40,0x0F,0xF8,0x00,0x00,0x07,0x80,
0x09,0x40,0x09,0x40,0x09,0x40,0x05,0x80,0x00,0x00,0x0F,0xF0,0x00,0x48,0x00,0x48,
0x00,0x00,0x07,0x80,0x28,0x40,0x28,0x40,0x28,0x40,0x1F,0xC0,0x00,0x00,0x0F,0xF8,
0x00,0x40,0x00,0x40,0x00,0x40,0x0F,0x80,0x00,0x00,0x0F,0xD0,0x00,0x00,0x20,0x40,
0x1F,0xD0,0x00,0x00,0x0F,0xF8,0x01,0x00,0x02,0x80,0x04,0x40,0x08,0x00,0x0F,0xF8,
0x00,0x00,0x0F,0xC0,0x00,0x40,0x00,0x40,0x0F,0x80,0x00,0x40,0x00,0x40,0x0F,0x80,
0x00,0x00,0x0F,0xC0,0x00,0x40,0x00,0x40,0x00,0x40,0x0F,0x80,0x00,0x00,0x07,0x80,
0x08,0x40,0x08,0x40,0x08,0x40,0x07,0x80,0x00,0x00,0x3F,0xC0,0x08,0x40,0x08,0x40,
0x08,0x40,0x07,0x80,0x00,0x00,0x07,0x80,0x08,0x40,0x08,0x40,0x08,0x40,0x3F,0xC0,
0x00,0x00,0x0F,0xC0,0x00,0x80,0x00,0x40,0x00,0x00,0x09,0x80,0x09,0x40,0x0A,0x40,
0x06,0x40,0x00,0x00,0x07,0xF0,0x08,0x40,0x08,0x40,0x00,0x00,0x07,0xC0,0x08,0x00,
0x08,0x00,0x08,0x00,0x0F,0xC0,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x03,0x00,
0x00,0xC0,0x00,0x00,0x03,0xC0,0x0C,0x00,0x03,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,
0x03,0xC0,0x00,0x00,0x08,0x40,0x04,0x80,0x03,0x00,0x04,0x80,0x08,0x40,0x00,0x00,
0x00,0xC0,0x33,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x0C,0x40,0x0A,0x40,
0x09,0x40,0x08,0xC0,0x00,0x00,0x01,0x00,0x01,0x00,0x1E,0xF0,0x20,0x08,0x00,0x00,
0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x00,0x20,0x08,0x1E,0xF0,0x01,0x00,0x01,0x00,
0x00,0x00,0x03,0x00,0x00,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x02,0x00,0x01,0x80,
0x00,0x00};#endif /*TAHOMA_H_*/

      中文字库

      相对于英文字库&#xff0c;中文字库就要复杂一些&#xff0c;为了让大家更明白&#xff0c;我们先了解一下汉字点阵字库的原理。

  • 汉字编码

      区位码在孤寂GD2312-80中规定&#xff0c;所有的国际汉字及符号分配在一个94行、94列的方阵中&#xff0c;方阵的每一行称为一个“区”&#xff0c;编号为01区到94区&#xff0c;每一列为一个“位”&#xff0c;比那好为01位到94位&#xff0c;方阵中的每一个汉字和符号所在的区号和位号组成在一起形成的四个阿拉伯数字就是他们的“区位码”。区位码的前两位是他的区号&#xff0c;后两位是它的位号。用区位码就可以唯一的确定一个汉字或字符&#xff0c;反过来说&#xff0c;任何一个汉字或字符也都对应着一个唯一的区位码。例如&#xff0c;汉字“母”字的区位码是3624&#xff0c;表明它在方阵的36区24位&#xff0c;问好“&#xff1f;”的区位码为0331&#xff0c;则它在03区31位。

  • 机内码

      汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述&#xff0c;汉字区位码的区码和位码的取值均在1-94之间&#xff0c;如直接用区位码作为机内码&#xff0c;就会与基本的ASCII码混淆。为了避免机内码与基本ASCII码的冲突&#xff0c;需要避开基本ASCII码中的控制码&#xff08;00H-1FH&#xff09;&#xff0c;还需要与基本ASCII码中的字符相区别。为了实现这两点&#xff0c;可以先在区码和位码分别加上20H&#xff0c;在此基础上再加80H&#xff08;此处“H”表示前两位数字为十六进制&#xff09;。经过这些处理&#xff0c;用机内码表示一个汉字需要占两个字节&#xff0c;分别称为高位字节和地位字节&#xff0c;这两位字节的机内码按如下规则表示&#xff1a;高位字节 &#61; 区码 &#43; 20H &#43;80H&#xff08;或区码&#43;A0H&#xff09;低位码&#61;位码&#43;20H&#43;80H&#xff08;或位码&#43;A0H&#xff09;由于汉字的区码与位码的取值范围的十六进制数均为01H-5EH&#xff08;即十进制的01-94&#xff09;&#xff0c;所以汉字的高位字节与低位字节的取值范围则为A1H-FEH&#xff08;即十进制的161-254&#xff09;。例如&#xff0c;汉字“啊”的区位码为1601&#xff0c;区码和位码分别用十六进制表示即为1001H&#xff0c;它的机内码的高位字节为B0H&#xff0c;低位字节为A1H&#xff0c;机内码就是B0A1H。

      有了上面的基础后&#xff0c;我们来看看我们点阵字库的结构。

      点阵字库存储在汉字的点阵字库中&#xff0c;每个字节的每个位代表一个汉字的一个点&#xff0c;每个汉字都是由一个矩形的点阵组成&#xff0c;0代表没有&#xff0c;1代表有点&#xff0c;将0和1用不同的颜色画出&#xff0c;就形成了汉字&#xff0c;常用的点阵矩阵有12*12&#xff0c;14*14&#xff0c;16*16三种字库。我们常用的字库文件来自UCDOC中&#xff0c;DOC前辈们经过将制作好的字模放到一个个标准的苦衷&#xff0c;这就是点阵字库文件。一般我们使用的是16*16的点阵宋体字库&#xff0c;所谓16*16&#xff0c;是每一个汉字在纵、横各16点的区域内显示的。现在又有了HZK12,HZK24,HZK32和HZK48字库及黑体、楷体和隶书字库。虽然汉字库种类繁多&#xff0c;但都是按照区位的顺序排列的。前一个字节为该汉字的区号&#xff0c;后一个字节为该字的位号。每一个区记录94个汉字&#xff0c;位号则为该字在该区中的位置。因此&#xff0c;汉字在汉字库中的具体位置采用机内码的计算公式为&#xff1a;

94*&#xff08;区号-0XA0-1&#xff09;&#43;&#xff08;位号-0XA0-1&#xff09;

      减1是因为数组是以0开始而区号位号是以1开始的。这仅为汉字为单位该汉字在汉字库中的位置&#xff0c;如果想得到以字节为单位&#xff0c;该汉字所在汉字库中的位置&#xff0c;那么只需要乘以一个汉字字模占用的字节数即可&#xff0c;即&#xff1a;

&#xff08;94*&#xff08;区号-0XA1&#xff09;&#43;(位号-0XA1)&#xff09;* 一个汉字字模占用字节数

      正常来说&#xff0c;一个汉字字模占用的字节数为横纵点数/8&#xff0c;以16*16点阵为例&#xff0c;它的一个汉字字模占用的字节数就为16*16/8&#61;32。不过也有例外&#xff0c;在下面将会有所提及。

我们所使用的字库是HZK12,它是12*12的点阵字库&#xff0c;字库设计者为了使用方便&#xff0c;字模每一行的位数均补齐为8的整数倍&#xff0c;有的设计者也将列补齐为8的整数倍。我们使用的HZK12即为这种&#xff0c;于是实际该字库的为长度是16*16&#xff0c;多余的4为都是0&#xff08;不显示&#xff09;&#xff0c;在显示效果上不受影响。

      下面&#xff0c;我们就来研究一下程序是如何实现的。

      首先&#xff0c;我们在工程目录中inc下建立gui.h文件&#xff0c;内容如下表所示

/** &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Filename: gui.h* Description: * Version: 1.0.0* Created: 2010.4.16* Revision: none* Compiler: Nios II 9.0 IDE* Author: (AVIC)* Email: avic633&#64;gmail.com * &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
#ifndef GUI_H_
#define GUI_H_typedef struct{unsigned char x;unsigned char y;unsigned char * matrix; unsigned char wide;unsigned char reverse;
}X_16_T;typedef struct{unsigned char x;unsigned char y;unsigned char * str;unsigned char reverse;
}CHARACTER_STRING;typedef struct{unsigned char x;unsigned char y;unsigned char reverse;
}STRING_T;extern unsigned char printf_string(STRING_T * p, char * fmt, ...);#define BUFFER_SIZE 200#endif /*GUI_H_*/

然后&#xff0c;我们在工程目录的drvier下建立gui.c文件&#xff0c;内容如下表所示

/** &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Filename: gui.c* Description: * Version: 1.0.0* Created: 2010.4.16* Revision: none* Compiler: Nios II 9.0 IDE* Author: (AVIC)* Email: avic633&#64;gmail.com * &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
#include "../inc/gui.h"
#include "../inc/lcd.h"
#include "../inc/tahoma.h"
#include "../inc/hzk12.h"
#include
#include static int _gui_x_16(X_16_T *p);
static int _print_tahoma(CHARACTER_STRING *p);
static int _tahoma_string_length(char * p);
unsigned char printf_string(STRING_T * p, char * fmt, ...);
static int h_to_v( unsigned char *dest, unsigned char *source);
int _print_simsun(CHARACTER_STRING *p);/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: _gui_x_16* Description: 这个函数是根据字库的结构&#xff0c;将字库中的点打印到LCD屏幕上&#xff0c;结构体
* X_16_T在gui.h中定义&#xff0c;可以通过参数确定点的位置&#xff0c;字库的宽度&#xff0c;
* 是否反色&#xff0c;以及字库文件的指针。* &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
int _gui_x_16(X_16_T *p)
{unsigned char i;if(p &#61;&#61; NULL)return -1;if(p->x > 128)return -1;if(p->y > 8)return -1 ;if(p->matrix &#61;&#61; NULL)return -1;if(p->reverse > 1)return -1;lcd.set_x(p->x);lcd.set_y(p->y);for(i&#61;0;iwide;i&#43;&#43;){lcd.write_data(p->reverse?p->matrix[2*i&#43;1]^0xfe:p->matrix[2*i&#43;1]);}lcd.set_x(p->x);lcd.set_y(p->y&#43;1);for(i&#61;0;iwide;i&#43;&#43;){lcd.write_data(p->reverse?~p->matrix[2*i]:p->matrix[2*i]);}return 0;}
/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: _print_tahoma* Description: 这个函数是英文字库的处理函数&#xff0c;使用的字库为定义在tomato.h中&#xff0c;
* CHARACTER_STRING结构体在gui.h当中定义&#xff0c;可以通过参数确定点
* 的位置&#xff0c;是否反色&#xff0c;以及字库文件的指针。* &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
int _print_tahoma(CHARACTER_STRING *p)
{unsigned char l,i&#61;0;unsigned int wide;X_16_T tmp;if(p &#61;&#61; NULL)return 0;if(p->x > 128)return 0;if(p->y > 8)return 0;if(p->str &#61;&#61; NULL)return 0;if(p->reverse > 1)return 0;l&#61;strlen((const char *)p->str);for(i&#61;0;istr[i]-&#39; &#39;&#43;1];wide-&#61;tahoma_font_offset[p->str[i]-&#39; &#39;]; tmp.x&#61;p->x;tmp.y&#61;p->y;tmp.matrix&#61;(unsigned char *)font_tahoma_8&#43;tahoma_font_offset[p->str[i]-&#39; &#39;]*2;//*2是因为字模高为16位&#xff0c;两个字节tmp.reverse&#61;p->reverse;tmp.wide&#61;wide;_gui_x_16(&tmp);p->x&#43;&#61;wide;}return 0;
}
/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: _tahoma_string_length* Description: 这个函数求英文字模的宽度* &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
int _tahoma_string_length(char * p)
{int temp&#61;0;while(*p !&#61;&#39;\0&#39;){temp&#43;&#61;tahoma_font_offset[*p-&#39; &#39;&#43;1];temp-&#61;tahoma_font_offset[*p-&#39; &#39;];p&#43;&#43;;}return temp;
}
/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: printf_string* Description: 这个函数是实现中英文字体自动切换显示的&#xff0c;利用它可以显示中英文混合
* 字体的字符串。里面还涉及到了变参的使用* &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
unsigned char printf_string(STRING_T * p, char * fmt, ...)
{unsigned char buf1[BUFFER_SIZE];CHARACTER_STRING tmp;unsigned int i&#61;0,offset,c&#61;0;va_list arg_ptr;unsigned char buf[BUFFER_SIZE];if(p &#61;&#61; NULL)return 0;if(p->x > 191)return 0;if(p->y > 6)return 0 ;memset(buf,&#39;\0&#39;,sizeof(buf));//这部分就是C语言中变参的使用方法va_start(arg_ptr,fmt);vsprintf(buf,fmt,arg_ptr);va_end(arg_ptr);offset&#61;p->x;while(buf[c]!&#61;&#39;\0&#39;){//通过判断来决定字符是英文还是中文if(buf[c] <0x7f && buf[c]!&#61;&#39;\n&#39;){i&#61;0;memset(buf1,&#39;\0&#39;,sizeof(buf1));while(buf[c]<0x7f && buf[c]!&#61;&#39;\0&#39; &&buf[c]!&#61;&#39;\n&#39;){buf1[i&#43;&#43;]&#61;buf[c&#43;&#43;];}tmp.x&#61;offset;offset&#43;&#61;_tahoma_string_length(buf1);tmp.y&#61;p->y;tmp.str&#61;buf1;tmp.reverse&#61;p->reverse;if(_print_tahoma(&tmp)&#61;&#61;-1)return 0;}if(buf[c] > 0x7f){i&#61;0;memset(buf1,&#39;\0&#39;,sizeof(buf1));while(buf[c] >0x7f){buf1[i&#43;&#43;]&#61;buf[c&#43;&#43;];buf1[i&#43;&#43;]&#61;buf[c&#43;&#43;];}tmp.x&#61;offset;offset&#43;&#61;i*6;tmp.y&#61;p->y;tmp.str&#61;buf1;tmp.reverse&#61;p->reverse;if(_print_simsun(&tmp)&#61;&#61;-1)return 0;}//new line symbolif(buf[c] &#61;&#61;&#39;\n&#39;){p->y&#43;&#61;2;offset&#61;p->x;c&#43;&#43;;}}p->x&#61;tmp.x;return 0;
}
/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: h_to_v* Description: 将汉字字模有横向转换为纵向&#xff0c;字库中的字模是横着放的&#xff0c;如果不经过转
* 化&#xff0c;显示出来的就是倒着的字。* &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
static int h_to_v( unsigned char *dest, unsigned char *source)
{int i,j;for(j&#61;0;j<8;j&#43;&#43;){for(i&#61;0;i<8;i&#43;&#43;)if(source[30-i*2]&(0x80>>j))dest[j*2]|&#61;(0x80>>i);for(i&#61;0;i<8;i&#43;&#43;)if(source[14-i*2]&(0x80>>j))dest[j*2&#43;1]|&#61;(0x80>>i); }for(j&#61;0;j<4;j&#43;&#43;){for(i&#61;0;i<8;i&#43;&#43;)if(source[31-i*2]&(0x80>>j))dest[j*2&#43;16]|&#61;(0x80>>i);for(i&#61;0;i<8;i&#43;&#43;)if(source[15-i*2]&(0x80>>j))dest[j*2&#43;17]|&#61;(0x80>>i); }return 1;
}
/* * &#61;&#61;&#61; FUNCTION &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Name: _print_simsun* Description: 这个函数是打印中文宋体汉字&#xff0c; * &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
int _print_simsun(CHARACTER_STRING *p)
{unsigned char l,i;X_16_T tmp;unsigned int offset&#61;0;unsigned char bua[32],bub[32]; if(p &#61;&#61; NULL)return 0;if(p->x > 128)return 0;if(p->y > 64)return 0 ;if(p->str &#61;&#61; NULL)return 0;if(p->reverse > 1)return 0;l&#61;strlen(p->str);l/&#61;2;for(i&#61;0;istr[2*i];offset-&#61;0xa1;offset*&#61;94;offset&#43;&#61;p->str[2*i&#43;1];offset-&#61;0xa1;offset*&#61;32;memcpy(bua,achzk12&#43;offset,32);//achzk12是存放汉字字库的数组memset(bub,0,32);h_to_v(bub,bua); tmp.x&#61;p->x;tmp.y&#61;p->y;tmp.reverse&#61;p->reverse;tmp.matrix&#61;bub;tmp.wide&#61;12; _gui_x_16(&tmp);p->x&#43;&#61;12;}return 0;
}

      在上面涉及到了achzk12&#xff0c;它是存放中文字库的数组。对于中文字库&#xff0c;有两种解决方案&#xff0c;一种是将字库文件&#xff08;bin格式&#xff09;烧写到flash中&#xff0c;每次用的时候先从flash读出来&#xff1b;另一种是将字库文件&#xff08;将bin格式文件转化为c格式&#xff09;数组的形式放到程序中。这两种方案根据硬件系统来选取。在这里&#xff0c;我们选用了第二种&#xff0c;因为我们的外部sdram很大&#xff0c;将字库文件放到程序中&#xff0c;每次上电都会将字库文件导入到sdram中&#xff0c;这样调用的时候速度就会很快&#xff0c;那么大的sdram不用也是浪费。而第一种方案一般是在ram比较小的情况下使用的&#xff0c;这样可以节省ram的空间。由于ackzk12文件比较大&#xff0c;在这里就不放出来了。

      最后&#xff0c;我们来测试一下&#xff0c;写个测试程序吧。

/** &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;* Filename: main.c* Description: * Version: 1.0.0* Created: 2010.4.16* Revision: none* Compiler: Nios II 9.0 IDE* Author: 马瑞 (AVIC)* Email: avic633&#64;gmail.com * &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;*/
#include
#include
#include
#include
#include "../inc/lcd.h"
#include "../inc/gui.h"
#include "../inc/ds1302.h"#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_timer_regs.h"
#include "alt_types.h"
#include "sys/alt_irq.h"unsigned char time[7] &#61; {0x00,0x19,0x14,0x17,0x03,0x03,0x10};//格式为: 秒 分 时 日 月 星期 年
alt_u8 segtab[10]&#61;{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0~9
unsigned char led_buffer[8]&#61;{0};
unsigned char bittab[6]&#61;{0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
static unsigned char cnt&#61;0;
unsigned char ti[][7]&#61;{"一","二","三","四","五","六","日"}; /***********************************************/
static void timer_init(void); //初始化中断/***********************************************/
int main(void)
{ unsigned char i&#61;0;unsigned char buf[20];unsigned char en_str[]&#61;"Hello! What&#39;s your name?";unsigned char cn_str[] &#61; "你好&#xff01;你叫什么名字&#xff1f;";unsigned char str[] &#61; " O(∩_∩)O~";STRING_T *string_t;timer_init(); ds1302.set_time(time);lcd.initialize();lcd.clear();string_t->x &#61; 0;string_t->y &#61; 0;string_t->reverse &#61; 0;printf_string(string_t,"%s",en_str);string_t->x &#61; 0;string_t->y &#61; 2;string_t->reverse &#61; 0;printf_string(string_t,"%s",cn_str);string_t->x &#61; 0;string_t->y &#61; 4;string_t->reverse &#61; 0;printf_string(string_t,"%s",str);
while(1){//我们将实时时钟加入进来&#xff0c;这样就可以在LCD上显示时间了ds1302.get_time(time); //采集时string_t->x &#61; 0;string_t->y &#61; 6;string_t->reverse &#61; 1;printf_string(string_t,"%02d-%02d-%02d %02d:%02d:%02d 星期%s\n",time[6],time[4],time[3],time[2],time[1],time[0],ti[time[5]-1]);}return 0;
}

      写好以后&#xff0c;我们就可以编译了。编译通过以后运行&#xff0c;我们来看看效果如何&#xff0c;上张效果图吧。

LSFJP6R9L{AWN&#96;3PI)SU5FW

      还不错吧&#xff0c;中文是宋体&#xff0c;英文是变宽的&#xff0c;显示效果很不错&#xff0c;连笑脸都可以打印出来&#xff0c;看来这个字库还是很全的&#xff0c;在此谢谢前辈们为我们做出的努力和贡献&#xff0c;我们将没齿难忘。

     这一节内容就结束了&#xff0c;谢谢大家的支持&#xff01;



推荐阅读
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了一个程序,可以输出1000内能被3整除且个位数为6的所有整数。程序使用了循环和条件判断语句来筛选符合条件的整数,并将其输出。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
author-avatar
萤之光
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有