基本显示原理:一个字符是由 16*16 、 16*24 等方形点阵构成的,而每个像素点又可以由 1 、 2 、 4 等个位来显示,一个像素的位越多,它的色彩就越逼真。要显示的点为 1 发光,而为 0 的不发光。
1、 字符显示
1) 自定义 ASCII ,可以由一个二维数组来表示。显示例如“ 1 ” 在数组中可以定义为:
{
________,
________,
___WW___,
__WWWW__,
__WWWW__,
__WWWW__,
___WW___,
___WW___,
___WW___,
________,
___WW___,
___WW___,
________,
________,
________,
________}
并在宏定义中将每行的符号变为二进制例如
#define ________ 0x0
#define _______W 0x1
#define ______W_ 0x2
#define ______WW 0x3
#define _____W__ 0x4
#define _____W_W 0x5
#define _____WW_ 0x6
#define _____WWW 0x7
#define ____W___ 0x8
#define ____W__W 0x9
#define ____W_W_ 0xa
这样就把一个数字的点阵表示为了二进制文件。在 LCD 显示源代码中,最重要的调用是下面的三个,来完成一串二进制的显示
Set_Color(GUI_WHITE); // 设置字体颜色
Set_Font(&GUI_Font8x16); // 设置字号
GUI_DispBinAt(126,220,150,8); // 第一个参数为要显示的二进制的
// 十进制数 , 第二个参数为显示位置的 X 坐标,第三个参数为 Y 坐标,第四个参数为长度
在字体设置的时候要用到三个嵌套结构体,这三个结构体关系密切,对字符显示很重要。
typedef struct{
void* pData; // 数据的起始地址
U16 FirstChar; // 第一个字符
U16 LastChar; /// 最后一个字符
U8 XSize; //X 轴方向的宽度,
U8 XDist; // 单个字符 X 方向占的位置大小
U8 BytesPerLine; // 一个字符每行占的字节数
}GUI_FONT_MONO ;
typedef struct{
U8 YSize; // X 轴方向的宽度
U8 YDist; // 单个字符 Y 方向占的位置大小
U8 XMag; //
U8 YMag; //
const GUI_FONT_MONO* pMono;
}GUI_FONT;
typedef struct {
const GUI_FONT* pAFont;
I16P LBorder; /// 边界坐标
I16P DispPosX; // 显示起点 X 坐标
I16P DispPosY; /// 显示起点 Y 坐标
}Context;
在理解了这三个结构体中的量的含义后看代码基本上没有什么障碍了。
void Set_Font( GUI_FONT* pFont)
{
if (pFont)
{
GUI_Context.pAFont = pFont;
}
}
用定义好的字体信息初始化结构体。
void GUI_DispBinAt(U32 v, I16P x, I16P y, U8 Len) {
char ac[33];
char* s = ac;
GUI_AddBin(v, Len, &s); 将十进制转化为二进制
Disp_String(ac, x, y); 将二进制信息,以设定好的字号显示出来
}
2) 字体库中的字显示:
以 16 × 16 的点阵汉字库文件为例。一个汉字用了 256 个点共 32 个字节表示。汉字共分 94 区,每个区有 94 位汉字。机内码用两个字节表示,第一个字节存储区号( qh ),为了和 ASCII 码相区别,范围从十六进制的 A1H 开始(小于 80H 地为 ASCII 码字符),对应区码的第一区;第二个字节是位号( wh ),范围也从 A1H 开始,对应某区中的第一个位码。这样,将汉字机内码减去 A0A0H 就得到该汉字的区位码。从而可以得到汉字在字库中的具体位置:
位置 =(94*(qh-1) + wh-1) * 一个汉字字模占用的字节数
对于 16 × 16 的点阵汉字库,汉字在字库中的具体位置的计算公式就是: (94*(qh-1)+wh-1)*32 。例如,“房”的机内码为十六进制的 B7BF ,则其区位码是 B7BFH-A0A0H=171FH ,转化为十进制就是 2331 ,在汉字库中的位置就是 32*[94*(23-1)+(31-1)]=67136 字节以后的 32 个字节为“房”的显示点
因此只要将该字体库的起始地址加上这个字节数后,得到的地址就是存放该字的数据区的地址。然后一行一行扫描,一行结束后 Y 值加 1 ,至到这个字显示结束。
2、 图片显示。
我个人认为,图片显示有两种实现方法,一种方法按照字符实现的方法,另写一个实现文件,将图片信息一行一行打印出来。但这样比较麻烦,你自己得算这个像素的色值。
第二种方法比较简单,就是 CPU 文档说明部分介绍的,可以将 LCDCON1-5 寄存器按要求设置正确为输出模式,并把要显示的图片文件的二进制数据的起始地址赋给输出地址 LCDSADDR1-2. 。在 LCDSADDR3 设置显示缓冲区 -- 虚拟屏 OFFSIZE=0 ,单位为半字 PAGEWIDTH=640 ( 单位为半字 ) 。
然后用下面的两个函数来实现输出。
void DispDesktop(void)
{
extern U16 gImage_bliss[]; // 声明外部图片资源
GUI_DispPic(0,0, 640,480, gImage_bliss); // 显示桌面
}
void GUI_DispPic( U16 x, U16 y,
U16 w, U16 h,
U16 *buffer)
{
I16 i, j;
volatile U16 *p_buffer;
// 需填充区域参数过滤
if( (x >= LCD_XSIZE_TFT_640480) ||
(y >= LCD_YSIZE_TFT_640480)
)
{ return;
}
if((x+w) > LCD_XSIZE_TFT_640480)
{ return;
}
if((y+h) > LCD_YSIZE_TFT_640480)
{ return;
}
// 更新显示数据
for(i=0; i<h; i++) // 输出 h 行数据
{
// 输出一行 (w) 数据
p_buffer = (U16 *)LCDFRAMEBUFFER; // 将缓冲区地址赋给 p_buffer
p_buffer = p_buffer + y*LCD_XSIZE_TFT_640480 + x; // 定义当前要显示一行数据
// 的结束地址
for(j=0; j<w; j++)
{
*p_buffer++ = *buffer++; // 输出数据
}
// 指向下一行
y++;
} // end of for(i=0; i<h; i++)...
}
想要源码的可以联系我哦