单片机GUI编程显示汉字
int8 GetGB12_Address( int8 *ptr )
{
int8 addr;
for (addr=0;addr // 查找定位
{
if (( *ptr == gb12Dot[addr].Index[0]) && ( *(ptr+1) == gb12Dot[addr].Index[1]))
{break;}
}
return addr;
}
GUI_PutHZ(x1,y1,(uint8*)gb12Dot[GetGB12_Address(ptr)].Msk,12, 12);
const typFNT_GB12 gb12Dot[] = {
" ", 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
":", 0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,
0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
"敏", 0x41,0x00,0x7F,0x00,0x81,0xE0,0x7F,0x40,0x55,0x40,0xFF,0x40,0x55,0x40,0x54,0x80,
0x7E,0x80,0x05,0x40,0x1A,0x20,0x00,0x00,
"感", 0x01,0x40,0x7F,0xE0,0x41,0x00,0x7F,0x40,0x5D,0x40,0x54,0xA0,0x9D,0x60,0x82,0x20,
0x54,0x40,0x52,0xA0,0x9F,0x80,0x00,0x00,
"度", 0x02,0x00,0x7F,0xE0,0x48,0x80,0x7F,0xE0,0x48,0x80,0x4F,0x80,0x40,0x00,0x5F,0x80,
0x45,0x00,0x87,0x00,0xB8,0xE0,0x00,0x00
}
typedef struct // 汉字字模数据结构
{
int8 Index[2]; // 汉字内码索引
int8 Msk[24]; // 点阵码数据
}typFNT_GB12;
void GUI_PutHZ(uint32 x, uint32 y, uint8 *dat, uint8 hno, uint8 lno)
{ uint8 i;
for(i=0; i
{ GUI_LoadLine(x, y, dat, hno); // 输出一行数据
y++; // 显示下一行
dat += (hno>>3); //计算下一行的数据
if( (hno&0x07)!=0 ) dat++;
}
}
uint8 GUI_LoadLine(uint32 x, uint32 y, uint8 *dat, uint32 no)
{
uint8 bit_dat;
uint8 i;
TCOLOR bakc;
if(x>=GUI_LCM_XMAX)
return(0);
if(y>=GUI_LCM_YMAX)
return(0);
for(i=0; i
{
if( (i%8)==0 ) bit_dat = *dat++;
if( (bit_dat&DCB2HEX_TAB[i&0x07])==0 )
GUI_CopyColor(&bakc, back_color);
else
GUI_CopyColor(&bakc, disp_color);
GUI_Point(x, y, bakc);
if( (++x)>=GUI_LCM_XMAX )
return(0);
}
return(1);
}
uint8 GUI_Point(uint8 x, uint8 y, TCOLOR color)
{
if(x>=GUI_LCM_XMAX)
return(0);
if(y>=GUI_LCM_YMAX)
return(0);
if( (color&0x01) != 0 )
gui_disp_buf[y][x>>3] |= DCB_HEX_TAB[x&0x07];
else
gui_disp_buf[y][x>>3] &= (~DCB_HEX_TAB[x&0x07]);
LCD_UpdatePoint(x, y);
return(1);
}
uint8 const DCB_HEX_TAB[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
TCOLOR gui_disp_buf[GUI_LCM_YMAX][GUI_LCM_XMAX/8];
void LCD_UpdatePoint(uint32 x, uint32 y)
{ // uint32 addr;
uint32 addr11;
uint32 addr22;
//addr = y*(GUI_LCM_XMAX>>3) + (x>>3);
addr11 = y*32%6 + (x>>3);
addr22 = y*32/256;
//WriteCmd3(addr&0xFF, addr>>8,AddrSet); // 置地址指针
WriteCmd3(addr11, addr22,AddrSet); // 置地址指针
delay(10);
WriteCmd2(gui_disp_buf[y][x>>3],DataWAddrI);
delay(10);
}
[page]
uint8 ReadSdate(void)
{
uint8 checkbusy;
//LCD_BUS = 0xff;
OutData(0xff);
//CD1=1;
SCD1();
//RD1=0;
CRD1();
//checkbusy=((IO0PIN&0x00ff0000)>>16);
checkbusy = (GPIOD->IDR&0x00ff);
//RD1=1;
SRD1();
return ( checkbusy );
}
void RWcheck(void)
{
uint8 databusy;
do
{
databusy=ReadSdate();
}while( !(databusy&0x03) );
}
void AutoRcheck(void)
{
uint8 databusy;
do
{
databusy=ReadSdate();
}while( !(databusy&0x04) );
}
void AutoWcheck(void)
{
uint8 databusy;
do
{
databusy=ReadSdate();
}while( !(databusy&0x08) );
}
//写数据
void WriteData(uint8 dat)
{
RWcheck();
//CD1=0;
CCD1();
//LCD_BUS=dat;
OutData(dat);
//WR1=0;
CWR1();
//WR1=1;
SWR1();
}
//写指令
void WriteCmd1(unsigned char cmd)
{
RWcheck();;
//CD1=1;
SCD1();
//LCD_BUS=cmd;
OutData(cmd);
//WR1=0;
CWR1();
//WR1=1;
SWR1();
}
//先写数据再写指令
void WriteCmd2(uint8 dat,uint8 cmd)
{
WriteData(dat);
WriteCmd1(cmd);
}
//先写2组数据 再写1组指令
void WriteCmd3(uint8 dat1,uint8 dat2,uint8 cmd)
{
WriteData(dat1);
WriteData(dat2);;
WriteCmd1(cmd);
}
//数据自动写
void AutoWriteData( uint8 dat)
{
AutoWcheck();;
//CD1 = 0;
CCD1();
// LCD_BUS= dat;
OutData(dat);
//WR1=0;
CWR1();
//WR1=1;
SWR1();
}
#define OutData(dat) GPIOD->BRR = 0xff<BSRR = (dat&0xff)<
#define LCM_WR1 12
#define SWR1() GPIOB->BSRR = 1<
#define CWR1() GPIOB->BRR = 1<
#define LCM_RD1 13
#define SRD1() GPIOB->BSRR = 1<
#define CRD1() GPIOB->BRR = 1<
#define LCM_CE1 14
#define SCE1() GPIOB->BSRR = 1<
#define CCE1() GPIOB->BRR = 1<
#define LCM_CD1 15
#define SCD1() GPIOB->BSRR = 1<
#define CCD1() GPIOB->BRR = 1<
图形显示的操作,最根本是对缓存的操作。
从应用层到底层的整个过程解析如下:
1、 调用写字函数在LCD上显示一个汉字。
GUI_PutHZ(x1,y1,(uint8*)gb12Dot[GetGB12_Address(ptr)].Msk,12, 12);
l 参数参考上面的函数说明,其中要显示的字需要通过一个数组查找。
l 该数组是一个结构体数组,每一个结构体中有两个分量,第一个是要显示的汉字,第二个是该汉字的字库。
l 把需要写入的汉字及字库先存放在数组中,根据汉字的内容查找到相应字库。
2、 在GUI_PutHZ函数中调用了GUI_LoadLine(x, y, dat, hno);
字库的实质是点矩阵,写字的实质就是把字库里安排的点阵写进缓存里。
这里调用画线函数,对矩阵进行操作。
3、 在GUI_LoadLine函数中调用了GUI_Point(x, y, bakc);
l 对画线的操作,实质就是对线上的每一点进行操作。
l 对于黑白屏来说,点的操作就是点亮与熄灭。
l 对于彩色屏就是对像素位的操作来实现颜色的变化。
l 所有的图案及字,都是不同颜色组合后给人的一种感官视觉。
l gui_disp_buf[y][x>>3] |= DCB_HEX_TAB[x&0x07];改变显示缓存中的数据。
l LCD_UpdatePoint(x, y);调用更新点函数实现刷屏。
4、 LCD_UpdatePoint函数中,调用了WriteCmd3和WriteCmd2函数
WriteCmd3这两个函数是对底层最基本的IO口操作,涉及硬件原理,涉及时序。
GUI的操作原理及程序例子基本完成。操作关键总结归纳如下:
l 如何设计外围接口。
l 如何编写底层驱动函数。
l 如何根据需求编写应用软件。