www.pudn.com > Src.rar > Ks0108.C


/****************************************************************************** 
 * Ks0108.C - Ks0108 液晶控制器驱动程序 
 * 
 * 
 * DESCRIPTION: - 
 * 
 * modification history 
 * -------------------- 
 * 01a, 04/sep/2007, 梁炎昌 written 
 * -------------------- 
 ******************************************************************************/ 
 
#include "CPU.H" 
#include "Ks0108.H" 
#include "Chinese.C" 
#include "ASCII.c" 
 
 
 
//------------------------------------------------------------------------------------------ 
 
/* 
------------------------------------------------------------------------- 
GUI相关全局变量 
------------------------------------------------------------------------- 
*/ 
U8  GUIEnFont = En_8x16;                //英文字体 
U8  GUITextMode = GUI_TEXTMODE_NORMAL;  //显示模式 
 
U8 Char_XSIZE;   //英文字体X宽度 
U8 Char_YSIZE;   //英文字体Y宽度 
 
U8 PosX = 0;     //当前系统X坐标 
U8 PosY = 0;     //当前系统Y坐标 
 
U8 NoXY = true;//是否使用PosX PosY的标志   1-->不使用   0-->使用 
 
 
// ---- 延迟程序 ---------------------------------------------------- 
#if OSC_48MHZ == true 
 
#define SomeNop();      {               \ 
    _nop_(); _nop_(); _nop_(); _nop_(); \ 
    _nop_(); _nop_(); _nop_(); _nop_(); \ 
   } 
 
#elif OSC_24MHZ == true 
 
#define SomeNop();      {               \ 
    _nop_(); _nop_(); _nop_(); _nop_(); \ 
    } 
 
#endif 
 
 
 
 
 
 
/* 
***************************************************************************** 
* WriteCommand_0108 - 写命令到KS0108 
* DESCRIPTION: - 
* 本函数不接管片选信号 
* @Param CmdData:命令码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void WriteCommand_0108(U8 CmdData) 
{ 
    LCD_E = 0; 
    LCD_RS = 0; 
    LCD_RW = 0; 
    LCD_Bus = CmdData; 
    SomeNop(); 
    LCD_E = 1; 
    SomeNop(); 
    LCD_E = 0; 
 
} 
 
 
/* 
***************************************************************************** 
* WriteData_0108 - 写数据到KS0108 
* DESCRIPTION: - 
* 本函数不接管片选信号 
* @Param Data:写入的数据 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void WriteData_0108(U8 Data) 
{ 
    LCD_E = 0; 
    LCD_RS = 1; 
    LCD_RW = 0; 
    LCD_Bus = Data; 
    SomeNop(); 
    LCD_E = 1; 
    SomeNop(); 
    LCD_E = 0; 
 
} 
/*-------------------读LCD数据----------------------------*/ 
#if 0 
U8 ReadData_0108(void) 
{   U8 Temp; 
    LCD_Bus = 0xFF;//切换成输入 
    LCD_RS = 1; 
    LCD_RW = 1; 
    SomeNop(); 
    LCD_E = 1; 
    SomeNop(); 
    Temp = LCD_Bus; 
    return(Temp); 
/* 
    U8 Temp; 
    PIN_KS0108_Di_HIGH; 
    PIN_KS0108_RW_HIGH; 
    DelayS(0); 
    PIN_KS0108_Enable_HIGH; 
    DelayS(0); 
    PIN_KS0108_Enable_LOW; 
    Temp = PIN_KS0108_Lcd_InBus; 
    return (Temp); 
*/ 
} 
 
U8 ReadState_0108(void) 
{ 
    U8 Temp; 
    LCD_Bus = 0xFF; 
    LCD_RS = 0; 
    LCD_RW = 1; 
    SomeNop(); 
    LCD_E = 1; 
    SomeNop(); 
    LCD_E = 0; 
    Temp = LCD_Bus; 
    return (Temp); 
 
 
} 
 
U8 Busy(void) 
{ 
    U16 TimeOut; 
    U8 Flag; 
    TimeOut = 200; 
    do{ 
        Flag = ReadState_0108(); 
        LED1 ^= 0x01; 
        if (TimeOut-- == 0){ 
            return 0; 
        } 
    }while(Flag &0x80); 
    return 1; 
} 
#endif 
//Option = 1   --->Disp On 
//Option = 0   --->Disp Off 
void KS0108_DisplayOn(U8 Option) 
{ 
    if (Option == 1) { 
        WriteCommand_0108(Ks0108_CMD_Disp_ON); 
    }else{ 
        WriteCommand_0108(Ks0108_CMD_Disp_OFF); 
    } 
} 
 
void KS0108_SetStartRow(U8 Row) 
{ 
    WriteCommand_0108(Ks0108_CMD_Disp_Start_Line + Row); 
} 
/* 
***************************************************************************** 
* Display_Locate - LCD上指定位置 显示指定数据 
* DESCRIPTION: - 
* 
* @Param x0:0--191横向坐标 
* @Param y0:0--7  纵向坐标 
* @Param DisplayData:写入的数据 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_Locate(U8 DisplayData, U8 x0, U8 y0) 
{ 
    if ((x0 <= (LCD_XSIZE-1))&(y0 <= (LCD_YSIZE-1))){ 
        if (x0 <= 63){                                //0--191 
            LCD_CSA(); 
//            Busy();//判忙 
            WriteCommand_0108(Ks0108_CMD_Set_Addr + x0); 
        } else if (x0 <= 127){ 
            LCD_CSB(); 
//            Busy();//判忙 
            WriteCommand_0108(Ks0108_CMD_Set_Addr + x0 - 64); 
        } else if (x0 <= 191){ 
            LCD_CSC(); 
//            Busy();//判忙 
            WriteCommand_0108(Ks0108_CMD_Set_Addr + x0 -128); 
        } 
//        Busy();//判忙 
        WriteCommand_0108(y0 + Ks0108_CMD_Set_Page);   //0--7 
//        Busy();//判忙 
        WriteData_0108(DisplayData); 
        LCD_CS_None();//不再片选任何一个Ks0108 
    } 
} 
 
 
/* 
***************************************************************************** 
* Display_Clear - 清空LCD显示 
* DESCRIPTION: - 
* 
* @Param void: 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_Clear(void) 
{ 
    U8 j,k; 
//-------------------------------------- 
    LCD_CSA(); 
    for(k = 0; k < 8; k++){ 
        WriteCommand_0108(0 + Ks0108_CMD_Set_Addr); //0--7 
        WriteCommand_0108(k + Ks0108_CMD_Set_Page); //0--63 
        for(j = 0;j < 64;j++){ 
            WriteData_0108(0x00); 
        } 
    } 
    KS0108_SetStartRow(0); 
//-------------------------------------- 
    LCD_CSB(); 
    for(k = 0; k < 8; k++){ 
        WriteCommand_0108(0 + Ks0108_CMD_Set_Addr); //0--7 
        WriteCommand_0108(k + Ks0108_CMD_Set_Page); //0--63 
        for(j = 0;j < 64;j++){ 
            WriteData_0108(0x00); 
        } 
    } 
    KS0108_SetStartRow(0); 
//------------------------------------- 
    LCD_CSC(); 
    for(k = 0; k < 8; k++){ 
        WriteCommand_0108(0 + Ks0108_CMD_Set_Addr);//0--7 
        WriteCommand_0108(k + Ks0108_CMD_Set_Page);//0-63 
        for(j = 0;j < 64;j++){ 
            WriteData_0108(0x00); 
        } 
    } 
    KS0108_SetStartRow(0); 
//------------------------------------- 
    LCD_CS_None(); 
} 
 
 
/* 
***************************************************************************** 
* Display_Init - 初始化LCD 
* DESCRIPTION: - 
* 
* @Param void: 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_Init(void) 
{ 
//--------------------------- 
    LCD_CSA(); 
    KS0108_DisplayOn(0); 
    KS0108_SetStartRow(0); 
    KS0108_DisplayOn(1); 
//--------------------------- 
    LCD_CSB(); 
    KS0108_DisplayOn(0); 
    KS0108_SetStartRow(0); 
    KS0108_DisplayOn(1); 
//--------------------------- 
    LCD_CSC(); 
    KS0108_DisplayOn(0); 
    KS0108_SetStartRow(0); 
    KS0108_DisplayOn(1); 
//--------------------------- 
    LCD_CS_None(); 
} 
 
 
 
 
/* 
***************************************************************************** 
* Display_Chinese - 指定位置显示一个16x16的汉字 
* DESCRIPTION: - 
* 
* @Param x0:X轴坐标0--(192-16) 
* @Param y0:Y轴坐标0--(8-2) 
* @Param UniCode:汉字内码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_Chinese(U16 UniCode, U8 x0, U8 y0) 
{ 
  U16 CodeID; 
  U8 i, ImgData; 
  U8 HZ_X = x0; 
  // 在字库里搜索汉字 
    for(CodeID=0; CodeID < hzNum; CodeID++){ 
        // 找到 指定汉字的 Index 后, 跳出循环 
        if ( (hzIndex[2*CodeID] == UniCode/256) && (hzIndex[2*CodeID+1] == UniCode%256) ){ 
            break; 
        }else if(CodeID == (hzNum-1)){//未检索到的汉字,显示个"##"提示吧 
            GUI_DispCharAt('#',x0,y0); 
            GUI_DispCharAt('#',x0+Char_XSIZE,y0); 
            return; 
        } 
    } 
//---------------------------------- 
    switch (GUITextMode) { 
        case GUI_TEXTMODE_NORMAL : 
//------------------------------------------------------------------------- 
            // 写汉字的上半部分  (一个汉字 32 个字节,  显示为2行 * 16列) 
            for(i=0; i<16; i++){ 
                ImgData = hzdot[i+CodeID*32]; 
                Display_Locate(ImgData, HZ_X, y0); 
                HZ_X++; 
            } 
            // 写汉字的下半部分 
            HZ_X = x0; 
            for(i=16; i<32; i++){ 
                ImgData = hzdot[i+CodeID*32]; 
                Display_Locate(ImgData, HZ_X, y0 + 1); 
                HZ_X++; 
            } 
//------------------------------------------------------------------------- 
             break; 
        case GUI_TEXTMODE_REVERSE : 
//------------------------------------------------------------------------- 
            // 写汉字的上半部分  (一个汉字 32 个字节,  显示为2行 * 16列) 
            for(i=0; i<16; i++){ 
              ImgData = hzdot[i+CodeID*32]^0xFF; 
              Display_Locate(ImgData, HZ_X, y0); 
              HZ_X++; 
            } 
            // 写汉字的下半部分 
            HZ_X = x0; 
            for(i=16; i<32; i++){ 
              ImgData = hzdot[i+CodeID*32]^0xFF; 
              Display_Locate(ImgData, HZ_X, y0 + 1); 
              HZ_X++; 
            } 
//------------------------------------------------------------------------- 
             break; 
        case GUI_TEXTMODE_UNDERLINE : 
//------------------------------------------------------------------------- 
            // 写汉字的上半部分  (一个汉字 32 个字节,  显示为2行 * 16列) 
            for(i=0; i<16; i++){ 
              ImgData = hzdot[i+CodeID*32]; 
              Display_Locate(ImgData, HZ_X, y0); 
              HZ_X++; 
            } 
            // 写汉字的下半部分 
            HZ_X = x0; 
            for(i=16; i<32; i++){ 
              ImgData = hzdot[i+CodeID*32]|0x80; 
              Display_Locate(ImgData, HZ_X, y0 + 1); 
              HZ_X++; 
            } 
//------------------------------------------------------------------------- 
             break; 
        default : 
             break; 
    } 
} 
 
 
/* 
***************************************************************************** 
* Display_ASCII - 显示一个ASCII 
* DESCRIPTION: - 
* 
* @Param X:X轴坐标 0--192  (注意边界) 
* @Param Y:Y轴坐标 0-- 7   (注意边界) 
* @Param Char:ASCII码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_ASCII(U8 Char, U8 X, U8 Y) 
{ 
    U8 i, ImgData; 
    U8 HZ_X = X; 
    if(GUIEnFont == En_5x8){ 
        Display_Locate(0x00, HZ_X, Y); 
        HZ_X++; 
        for(i = 0; i < 5; i++){ 
            ImgData = chardot_5x8[i+(Char-0x20)*5]; 
            Display_Locate(ImgData, HZ_X, Y); 
            HZ_X++; 
        } 
        Display_Locate(0x00, HZ_X, Y); 
        HZ_X++; 
        Display_Locate(0x00, HZ_X, Y); 
    } else { 
        for(i=0;i<8;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16]; 
            Display_Locate(ImgData, HZ_X, Y); 
            HZ_X++; 
        } 
        HZ_X=X; 
        for(i=8;i<16;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16]; 
            Display_Locate(ImgData, HZ_X, Y + 1); 
            HZ_X++; 
      } 
 
   } 
} 
 
 
 
 
/* 
***************************************************************************** 
* Display_InvASCII - 反显示ASCII 
* DESCRIPTION: - 
* 
* @Param X:X轴坐标  0--191 
* @Param Y:Y轴坐标  0--7 
* @Param Char:ASCII码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_InvASCII(U8 Char, U8 X, U8 Y) 
{ 
 
    U8 i, ImgData; 
    U8 HZ_X = X; 
    if(GUIEnFont == En_5x8){ 
        Display_Locate(0xFF, HZ_X, Y); 
        HZ_X++; 
        for(i = 0; i < 5; i++){ 
            ImgData = chardot_5x8[i+(Char-0x20)*5]^0xFF; 
            Display_Locate(ImgData, HZ_X, Y); 
            HZ_X++; 
        } 
        Display_Locate(0xFF, HZ_X, Y); 
        HZ_X++; 
        Display_Locate(0xFF, HZ_X, Y); 
    } else { 
        for(i=0;i<8;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16] ^ 0xFF; 
            Display_Locate(ImgData, HZ_X, Y); 
            HZ_X++; 
        } 
        HZ_X=X; 
        for(i=8;i<16;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16] ^ 0xFF; 
            Display_Locate(ImgData, HZ_X, Y + 1); 
            HZ_X++; 
        } 
    } 
} 
 
/* 
***************************************************************************** 
* Display_ASCII_UnderLine - 显示一个带有下划线的ASCII 
* DESCRIPTION: - 
* 
* @Param X:X轴坐标 
* @Param Y:Y轴坐标 
* @Param Char:ASCII码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void Display_ASCII_UnderLine(U8 Char, U8 X, U8 Y) 
{ 
  //U16 Position; 
  U8 i, ImgData; 
  U8 HZ_X = X; 
    if(GUIEnFont == En_5x8){ 
        Display_Locate(0x80, HZ_X, Y); 
        HZ_X++; 
        for(i = 0; i < 5; i++){ 
          ImgData = chardot_5x8[i+(Char-0x20)*5] | 0x80; 
          Display_Locate(ImgData, HZ_X, Y); 
          HZ_X++; 
        } 
        Display_Locate(0x80, HZ_X, Y); 
        HZ_X++; 
        Display_Locate(0x80, HZ_X, Y); 
    } else { 
        for(i=0;i<8;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16]; 
            Display_Locate(ImgData, HZ_X, Y); 
            HZ_X++; 
        } 
        HZ_X=X; 
        for(i=8;i<16;i++){ 
            ImgData = chardot_8x16[i+(Char-0x20)*16] | 0x80; 
            Display_Locate(ImgData, HZ_X, Y + 1); 
            HZ_X++; 
        } 
    } 
} 
 
/* 
---------------------------------------------------------------------------------------------- 
 
---------------------------------------------------------------------------------------------- 
*/ 
#if 0 
/* 
---------------------------------------------------------------------------------------------- 
//移动当前Y坐标 
---------------------------------------------------------------------------------------------- 
*/ 
void GUI_GotoY(U8 y) 
{ 
    if (y > 7) { 
        PosY = 7; 
    } else { 
        PosY = y; 
    } 
} 
/* 
---------------------------------------------------------------------------------------------- 
//移动当前Y坐标 
---------------------------------------------------------------------------------------------- 
*/ 
void GUI_GotoX(U8 x) 
{ 
    if (x > 127) { 
        PosX = 127; 
    } else { 
        PosX = x; 
    } 
} 
/* 
***************************************************************************** 
* GUI_GotoXY - 系统光标移动到指定位置 
* DESCRIPTION: - 
* 
* @Param y:Y轴坐标 
* @Param x:X轴坐标 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_GotoXY(U8 x,U8 y) 
{ 
    GUI_GotoX(x); 
    GUI_GotoY(y); 
} 
 
#endif 
/* 
***************************************************************************** 
* GUI_SetTextMode - 设置文字显示模式 
* DESCRIPTION: - 
* 
* @Param TextMode:模式代码 
* @Return :模式代码 
* ---- 
***************************************************************************** 
*/ 
 
U8 GUI_SetTextMode(U8 TextMode) 
{ 
    GUITextMode = TextMode; 
    return GUITextMode; 
} 
 
/* 
***************************************************************************** 
* GUI_SetEnFont - 设置显示的英文字体 
* DESCRIPTION: - 
* 目前支持两种字体8x16 5x8 
* @Param EnFont:字体代码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_SetEnFont(U8 EnFont) 
{ 
  if (EnFont == En_5x8){ 
    GUIEnFont = En_5x8; 
    Char_XSIZE = En_5x8_XSIZE; 
    Char_YSIZE = En_5x8_YSIZE; 
  } else { 
    GUIEnFont = En_8x16; 
    Char_XSIZE = En_8x16_XSIZE; 
    Char_YSIZE = En_8x16_YSIZE; 
 
  } 
 
} 
/* 
---------------------------------------------------------------------------------------------- 
 
---------------------------------------------------------------------------------------------- 
*/ 
void GUI_Delay(U16 Period) 
{ 
    U8 j; 
    for (;  Period>0 ; Period--) { 
        for (j = 0; j < 200; j++) { 
        } 
    } 
} 
/* 
***************************************************************************** 
* GUI_DispCharAt - 指定位置显示一个ASCII码 
* DESCRIPTION: - 字体使用是系统设定的字体 
* 
* @Param x:X轴坐标 
* @Param y:Y轴坐标 
* @Param c:ASCII码 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_DispCharAt(U8 c, U8 x, U8 y) 
{ 
    switch (GUITextMode) { 
        case GUI_TEXTMODE_NORMAL : 
             Display_ASCII(c, x, y); 
             break; 
        case GUI_TEXTMODE_REVERSE : 
             Display_InvASCII(c, x, y); 
             break; 
        case GUI_TEXTMODE_UNDERLINE : 
             Display_ASCII_UnderLine(c, x, y); 
             break; 
        default : 
             break; 
    } 
} 
/* 
---------------------------------------------------------------------------------------------- 
 
---------------------------------------------------------------------------------------------- 
*/ 
#if 0 
void GUI_DispChar(U8 c) 
{ 
    GUI_DispCharAt(c, PosX, PosY); 
    PosX += 8; 
} 
#endif 
/* 
***************************************************************************** 
* GUI_Init - 初始化GUI显示 
* DESCRIPTION: - 
* 
* @Param void: 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_Init(void) 
{ 
    Display_Init(); 
    GUIEnFont = En_8x16; 
    GUITextMode = GUI_TEXTMODE_NORMAL; 
    Char_XSIZE = En_8x16_XSIZE; 
    Char_YSIZE = En_8x16_YSIZE; 
    PosX = 0; 
    PosY = 0; 
    NoXY = true; 
 
 
} 
void GUI_Clear(void) 
{ 
    Display_Clear(); 
} 
#if 0 
void GUI_DispCEOL(void) 
{ 
    U8 i; 
    for(i = PosX; i <= LCD_XSIZE-8; i += 8) { 
        GUI_DispCharAt(' ', i, PosY); 
 
    } 
} 
#endif 
/* 
***************************************************************************** 
* GUI_DispStringAt - 指定位置显示一个字符串 
* DESCRIPTION: - 
* 支持中英混合 当中英混合时英文字体强制为8x16 如果单单英文 按照设定字体 
* @Param x0:X轴坐标 
* @Param y0:Y轴坐标 
* @Param s:字符串 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
//void GUI_DispStringAt(U8 _CONST_ *s,U8 x0,U8 y0) 
void GUI_DispStringAt(U8 *s,U8 x0,U8 y0) 
{ 
    U8 i; 
    if (NoXY == false){//没有提供坐标,则使用系统坐标 
        x0 = PosX; 
        y0 = PosY; 
    } 
    i = 0; 
    while(s[i]!='\0'){ 
        if (s[i] < 0x80) {//是ASCII 
             if(s[i] == '\n'){ 
                    x0 = 0; 
                    y0 += Char_YSIZE; 
             } else { 
                if (x0 > (LCD_XSIZE-1)) {//换行 
                    x0 = 0; 
                    y0 += Char_YSIZE; 
                } 
                switch (GUITextMode) { 
                    case GUI_TEXTMODE_NORMAL : 
                         Display_ASCII(s[i], x0, y0); 
                         break; 
                    case GUI_TEXTMODE_REVERSE : 
                         Display_InvASCII(s[i], x0, y0); 
                         break; 
                    case GUI_TEXTMODE_UNDERLINE : 
                         Display_ASCII_UnderLine(s[i], x0, y0); 
                         break; 
                    default : 
                         break; 
                } 
                x0 += Char_XSIZE; 
             } 
        } else {//是中文 
            if (x0 > LCD_XSIZE-16){ 
                x0 = 0; 
                y0 += Chinese_YSIZE; 
            } 
            Display_Chinese(s[i]*256+s[i+1],x0,y0);//中文 
            i++; 
            x0 += Chinese_XSIZE; 
       } 
       s++; 
    } 
    if (NoXY == false){ 
        PosX = x0; 
        PosY = y0; 
    } 
 
} 
#if 0 
/* 
***************************************************************************** 
* GUI_DispString - 在当前系统坐标下显示字符串 
* DESCRIPTION: - 
* 除了坐标不能指定外 功能跟GUI_DispStringAt一致 
* @Param s:字符串 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_DispString(U8 _CONST_ *s) 
{ 
    NoXY = false; 
    GUI_DispStringAt(s,PosX,PosY); 
    NoXY = true; 
} 
 
void GUI_DispStringLen(U8 _CONST_ *s, U16 Len) 
{ 
    U8 i; 
    i = 0; 
    while(s[i]!='\0'){ 
        if (i >= Len ){ 
            return; 
        } 
        if (s[i] < 0x80) {//是ASCII 
             if(s[i] == '\n'){ 
//                    PosX = 0; 
//                    PosY += 2; 
             } else { 
               if (PosX > (LCD_XSIZE-1)) {//换行 
                    PosX = 0; 
//                    PosY += 2; 
                } 
                switch (GUITextMode) { 
                    case GUI_TEXTMODE_NORMAL : 
                         Display_ASCII(s[i], PosX, PosY); 
                         break; 
                    case GUI_TEXTMODE_REVERSE : 
                         Display_InvASCII(s[i], PosX, PosY); 
                         break; 
                    case GUI_TEXTMODE_UNDERLINE : 
                         Display_ASCII_UnderLine(s[i], PosX, PosY); 
                         break; 
                    default : 
                         break; 
                } 
                PosX += 8; 
             } 
        } else {//是中文 
            if (PosX > LCD_XSIZE-16){ 
//                PosX = 0; 
//                PosY += 2; 
                return; 
            } 
            Display_Chinese(s[i]*256+s[i+1],PosX,PosY);//中文 
            i++; 
            PosX += 16; 
       } 
       i++; 
    } 
 
} 
 
void GUI_DrawCursor(U8 x, U8 y) 
{ 
    if(GUITextMode == GUI_TEXTMODE_NORMAL){ 
        Display_Locate(0xFF,x,y); 
        Display_Locate(0xFF,x,y+1); 
    } else if (GUITextMode == GUI_TEXTMODE_REVERSE){ 
        Display_Locate(0x00,x,y); 
        Display_Locate(0x00,x,y+1); 
    } else { 
        Display_Locate(0xFF,x,y); 
        Display_Locate(0xFF,x,y+1); 
    } 
} 
 
void GUI_CursorOn(U8 x, U8 y) 
{ 
    Display_Locate(0xFF,x,y); 
    Display_Locate(0xFF,x,y+1); 
} 
 
void GUI_CursorOFF(U8 x, U8 y) 
{ 
    Display_Locate(0x00,x,y); 
    Display_Locate(0x00,x,y+1); 
} 
#endif 
 
/* 
***************************************************************************** 
* GUI_DispStringAtBar - 显示一个字符串在一个BAR中 
* DESCRIPTION: - 
* 可以设定对齐方式 
* @Param s:字符串 
* @Param x0:BAR起始X轴坐标 
* @Param x1:BAR结束点的X轴坐标 
* @Param y0:BAR的Y轴坐标 
* @Param Mode:对齐方式 居中于BAR 左对齐BAR 右对齐BAR 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
//void GUI_DispStringAtBar(U8 _CONST_ *s,U8 x0, U8 y0, U8 x1,U8 Mode) 
void GUI_DispStringAtBar(U8 *s,U8 x0, U8 y0, U8 x1,U8 Mode) 
{ 
    U8 ENCount;//英文统计 
    U8 CNCount;//中文统计 
    U8 XLen; 
    U8 X; 
    U8 Y; 
    U8 i; 
    CNCount = 0; 
    ENCount = 0; 
    XLen = 0; 
    i = 0; 
    while(s[i]!='\0'){//统计中英文个数 
        if (s[i] > 0x80) { 
            CNCount ++; 
            i++; 
        } else { 
           ENCount++; 
        } 
        i++; 
    } 
        GUI_SetEnFont(En_8x16); 
/* 
    if(CNCount){ 
        GUI_SetEnFont(En_8x16); 
    } else { 
        GUI_SetEnFont(En_5x8); 
    } 
*/ 
    XLen = ENCount*8 + CNCount*16; 
 
    if (XLen > 127) {//我们只能显示一行 
        XLen = 127; 
    } 
//识别对其方式属性 
    switch (Mode&0x30) {//只有这两个Bit是这个属性 
        case GUI_TA_LEFT: //左对齐 
            XLen = 0; 
            break; 
        case GUI_TA_HCENTER:  //居中 
            XLen  = ((x1-x0)-XLen)/2; 
            break; 
        case GUI_TA_RIGHT:   //右对齐 
            XLen  = (x1-x0)-XLen; 
            break; 
        default: 
            break; 
    } 
//-------------------------------------- 
//得到喀什显示的起点坐标 
    X = x0+XLen; 
    Y = y0; 
 
//--------------------- 
//清除字符前面的空白部分 
    if(Mode&GUI_JUST_TEXT){ 
    } else { 
        x0 = X; 
        if (GUITextMode == GUI_TEXTMODE_REVERSE){ 
            for(i = 0; i (128-8)){//换行 
        X += 2; 
        Y  = 0; 
    } 
    if(!Nor){ 
        for(i=0;i<8;i++){ 
            if(EnFont == 0){ 
                WriteByte(X,(Y+i),chardot[i+(Char-0x20)*16]); 
            }else{ 
                dot = chardot[i+(Char-0x20)*16]; 
                temp = Changedot[dot]; 
//这段代码把字体纵向放大2倍,外部调用时换行需要加倍 
                WriteByte(X,(Y+i),(U8)(temp&0x00FF)); 
                WriteByte(X+1,(Y+i),(U8)((temp&0xFF00)>>8)); 
 
/* 
//这段代码把字体放大4倍,但由于横向轴被放大,因此外部调用函数时也需要加倍 
                WriteByte(X,(Y+i*2),(U8)(temp&0x00FF)); 
                WriteByte(X,(Y+i*2+1),(U8)(temp&0x00FF)); 
                WriteByte(X+1,(Y+i*2),(U8)((temp&0xFF00)>>8)); 
                WriteByte(X+1,(Y+i*2+1),(U8)((temp&0xFF00)>>8)); 
*/ 
            } 
 
        } 
        for(i=8;i<16;i++){ 
            if(EnFont == 0){ 
                WriteByte(X+1,(Y+i-8),chardot[i+(Char-0x20)*16]); 
            }else{ 
                dot = chardot[i+(Char-0x20)*16]; 
                temp = Changedot[dot]; 
 
                WriteByte(X+2,(Y+i-8),(U8)(temp&0x00FF)); 
                WriteByte(X+3,(Y+i-8),(U8)((temp&0xFF00)>>8)); 
 
/* 
                WriteByte(X+2,(Y+(i-8)*2),(U8)(temp&0x00FF)); 
                WriteByte(X+2,(Y+(i-8)*2+1),(U8)(temp&0x00FF)); 
                WriteByte(X+3,(Y+(i-8)*2),(U8)((temp&0xFF00)>>8)); 
                WriteByte(X+3,(Y+(i-8)*2+1),(U8)((temp&0xFF00)>>8)); 
*/ 
            } 
        } 
    }else{ 
        for(i=0;i<8;i++){ 
            if(EnFont == 0){ 
                WriteByte(X,(Y+i),0xFF-chardot[i+(Char-0x20)*16]); 
            }else{ 
                dot = 0xFF-chardot[i+(Char-0x20)*16]; 
                temp = Changedot[dot]; 
                WriteByte(X*2,(Y+i),(U8)(temp&0x00FF)); 
                WriteByte(X*2,(Y+i+1),(U8)(temp&0x00FF)); 
                WriteByte(X*2+1,(Y+i),(U8)((temp&0xFF00)>>8)); 
                WriteByte(X*2+1,(Y+i+1),(U8)((temp&0xFF00)>>8)); 
 
            } 
        } 
        for(i=8;i<16;i++){ 
            if(EnFont == 0){ 
                WriteByte(X+1,(Y+i-8),0xFF-chardot[i+(Char-0x20)*16]); 
            }else{ 
                dot = 0xFF-chardot[i+(Char-0x20)*16]; 
                temp = Changedot[dot]; 
                WriteByte((X+1)*2,(Y+i-8+1),(U8)(temp&0x00FF)); 
                WriteByte((X+1)*2,(Y+i-8),(U8)(temp&0x00FF)); 
                WriteByte((X+1)*2+1,(Y+i-8+1),(U8)((temp&0xFF00)>>8)); 
                WriteByte((X+1)*2+1,(Y+i-8),(U8)((temp&0xFF00)>>8)); 
            } 
        } 
    } 
} 
#endif 
//-------------------------- 
 
#if 0 
//-------------显示普通图片 
//------(图像 长度 起始位置) 
void Display_Image(U8 _CONST_ *IMG) 
{ 
    U8 XAddr; 
    U8 YAddr; 
    U16 Count; 
    Count = 0; 
    for(XAddr=0;XAddr<8;XAddr++){//0--7 
        for(YAddr=0;YAddr<128;YAddr++){//0--127 
            WriteByte(XAddr,YAddr,IMG[Count++]); 
        } 
    } 
} 
#endif 
 
/* 
***************************************************************************** 
* GUI_DrawIcon - 制定位置显示一个32x32的图标 
* DESCRIPTION: - 
* 
* @Param x0:X轴坐标 
* @Param y0:Y轴坐标 注意边界! 
* @Param Ico:图标数据 
* @Return : 
* ---- 
***************************************************************************** 
*/ 
void GUI_DrawIcon(U8 _CONST_ *Ico,U8 x0,U8 y0) 
{ 
    U8 i; 
    U16 Count; 
    Count = 0; 
    if( y0 > 4){//边界保护 
        y0 = 4; 
    } 
    if(x0 >(LCD_XSIZE-32)){ 
        x0 = LCD_XSIZE-32; 
    } 
    for(i=0;i<32;i++){//第一行 
        Display_Locate(Ico[Count++],x0+i,y0); 
    } 
    for(i=0;i<32;i++){//第二行 
        Display_Locate(Ico[Count++],x0+i,y0+1); 
    } 
    for(i=0;i<32;i++){//第三行 
        Display_Locate(Ico[Count++],x0+i,y0+2); 
    } 
    for(i=0;i<32;i++){//第四行 
        Display_Locate(Ico[Count++],x0+i,y0+3); 
    } 
} 
#if 0 
 
/* 
***************************************************************************** 
* GUI_DispDecAt - 显示十进制数值 
* DESCRIPTION: - 
* 处理长度最多5个数字(因为U16--->65536) 
* @Param v:显示的数据 
* @Param x:X轴坐标 
* @Param y:Y轴坐标  XY 均是起点位置坐标 也就是数值最高位的坐标 
* @Param Len:指定的显示长度1--5内 
* @Return : 
* 
***************************************************************************** 
*/ 
void GUI_DispDecAt(U16 v, U16 x, U16 y, U8 Len) 
{ 
    U8 i; 
    U8 CharBuf[5]; 
    U8 HighByte; 
 
    HighByte = 0; 
    for(i = 0; i < 5; i++){ 
        CharBuf[i] = (U8)(v%10); 
        v = v/10; 
        if(CharBuf[i]){ 
            HighByte = i; 
        } 
    } 
    //第0位无论如何也显示 
    i = 0; 
    GUI_DispCharAt(CharBuf[i]+'0',x+((Len-1)-i)*Char_XSIZE,y); 
    for(i = 1; i < Len; i++){ 
        if(CharBuf[i]){ 
            GUI_DispCharAt(CharBuf[i]+'0',x+((Len-1)-i)*Char_XSIZE,y); 
        }else if(i > HighByte){ 
            GUI_DispCharAt(' ',x+((Len-1)-i)*Char_XSIZE,y); 
        } 
    } 
 
} 
 
/* 
***************************************************************************** 
* GUI_DispHexAt - 显示一个数据的十六进制值 
* DESCRIPTION: - 
* 最大长度4个 
* @Param v:数据 
* @Param x:X轴坐标 
* @Param y:Y轴坐标  XY均是起点坐标 也就是数据最高字节坐标 
* @Param Len:长度1--4 
* @Return : 
* 
***************************************************************************** 
*/ 
void GUI_DispHexAt(U32 v, U8 x, U8 y, U8 Len) 
{ 
    U8 i; 
    U8 HexData; 
    if(Len > 8){//限制范围 
        Len = 8; 
    } 
    for(i = 0; i < Len; i++){ 
        HexData = v&0x0F; 
        v = v >>4; 
        if(HexData < 0x0A){ 
            GUI_DispCharAt(HexData+'0',x+Char_XSIZE*(Len-1-i),y); 
        }else{ 
            GUI_DispCharAt(HexData-0x0A+'A',x+Char_XSIZE*(Len-1-i),y); 
        } 
    } 
} 
/* 
***************************************************************************** 
* HBar - 显示一个水平的进度条 
* DESCRIPTION: - 
* 附加有百分比显示 
* @Param x0:进度条起点X轴坐标   0-->127 
* @Param x1:进度条结束点X坐标   0-->127  必须大于x0  百分比显示于该坐标之后 
* @Param y:进度条Y轴坐标        0--7 
* @Param percent:当前百分值     0-->100 
* @Return : 
* 
***************************************************************************** 
*/ 
void HBar(U8 y, U8 x0, U8 x1,U8 percent) 
{ 
    U8 U8Temp; 
    U8 i; 
    float Center; 
    Center = (x1-x0); 
    Center *= percent; 
    Center /= 100; 
//    U8Temp = (x1-x0)*percent/100;//这个计算做法在430上能用,但C51下似乎必须用浮点算 
    U8Temp = (U8)Center; 
    Display_Locate(0xFF, x0, y); 
    Display_Locate(0xFF, x1, y); 
    for(i = 1; i < U8Temp; i++){ 
        Display_Locate(0xBD, x0+i, y); 
    } 
    for(i = x0+U8Temp+1; i < x1; i++){ 
        Display_Locate(0x81, i, y); 
    } 
} 
/*                  x1 +3 
|-------------------| 
|                   || 
|                   ||| 
|                   |||| 
|                   |||| 
-------------------- 
 ------------------- 
  ------------------ 
x0--->x1+3 
y0--->y1 
 
 
*/ 
 
void TipDisp( U8 x0, U8 y0, U8 x1, U8 y1) 
{ 
    U8 i; 
    for(i = 0; i < x1-x0+4; i++){ 
        Display_Locate(0x01, x0+i, y0); 
        Display_Locate(0x0F, x0+i, y1); 
    } 
    Display_Locate(0x01, x0+0, y1); 
    Display_Locate(0x01, x0+1, y1); 
    Display_Locate(0x03, x0+2, y1); 
    Display_Locate(0x03, x0+3, y1); 
    Display_Locate(0x07, x0+4, y1); 
    Display_Locate(0x07, x0+5, y1); 
 
    for(i = 0; i < y1-y0; i++){ 
        Display_Locate(0xFF, x0, y0+i); 
        Display_Locate(0xFF, x1, y0+i); 
        Display_Locate(0xFF, x1+1, y0+i); 
        Display_Locate(0xFF, x1+2, y0+i); 
        Display_Locate(0xFF, x1+3, y0+i); 
    } 
    Display_Locate(0xFC, x1+1, y0); 
    Display_Locate(0xF0, x1+2, y0); 
    Display_Locate(0xC0, x1+3, y0); 
} 
 
/* 
清空Tip 
坐标应该跟TipDisp一样 
*/ 
void TipClr( U8 x0, U8 y0, U8 x1, U8 y1) 
{ 
    U8 i; 
    U8 j; 
    for(i = 0; i <= x1+3-x0; i++){ 
        for(j = 0; j <= y1-y0; j++){ 
            Display_Locate(0x00, x0+i, y0+j); 
        } 
    } 
 
} 
#endif 
/* 
// ---- 显示不带符号的整数  (数字 起始位置XY,显示长度) ----------------------------- 
void Display_Number(U16 Number, U8 X, U8 Y, U8 Lenth) 
{ 
  U8 DispNum; 
 
  X = ( X + Lenth * 8 - 8 ); 
  for(; Lenth>0; Lenth--) 
  { 
    DispNum = Number%10 + 0x30; 
    Display_ASCII(DispNum, X, Y); 
    X -= 8; 
    Number = Number / 10; 
  } 
} 
 
// ---- 显示带符号的整数  (数字 起始位置XY,显示长度) --------------------------------- 
void Display_SignedNumber(int Number,U8 X,U16 Y,U8 Lenth) 
{ 
  if(Number < 0) 
  { 
    Display_ASCII('-', X, Y); 
    Display_Number(-Number, X+8, Y, Lenth); 
  } 
  else 
  { 
    Display_ASCII(' ', X, Y); 
    Display_Number(Number, X+8, Y, Lenth); 
  } 
} 
 
// ---- 显示不带符号的小数 (数字 起始位置XY,整数位数,小数位数) ------------------------------ 
void Display_Decimal(unsigned long int Number, char X, U16 Y, U8 INT, U8 DEC) 
{ 
  U8 DispNum, Lenth; 
  //Y = Y +(( X + INT * 8 + DEC * 8 ) / 84) * 2; 
  X = ( X + ( INT + DEC ) *8); 
  // 显示小数部分 
  for(Lenth=DEC; Lenth>0; Lenth--) 
  { 
    DispNum = Number%10 + 0x30; 
    Display_ASCII(DispNum, X, Y); 
    //if (X < 8) {Y -= 2; X += 84;} 
    X -= 8; 
    Number = Number / 10; 
  } 
  // 显示小数点 
  Display_ASCII('.', X, Y); 
  //if (X < 8) {Y -= 2; X += 84;} 
    X -= 8; 
  // 显示整数部分 
  for(Lenth=INT; Lenth>0; Lenth--) 
  { 
    DispNum = Number%10 + 0x30; 
    Display_ASCII(DispNum, X, Y); 
    //if (X < 8) {Y -= 2; X += 84;} 
    X -= 8; 
    Number = Number / 10; 
  } 
} 
 
// ---- 显示带符号的小数 (数字 起始位置XY,整数位数,小数位数) ------------------------------ 
void Display_SignedDecimal(long int Number, char X, U16 Y, U8 INT, U8 DEC) 
{ 
  if(Number < 0) 
  { 
    Display_ASCII('-', X, Y); 
    Display_Decimal(-Number, X+8, Y, INT, DEC); 
  } 
  else 
  { 
  Display_ASCII(' ',X,Y); 
  Display_Decimal(Number, X+8, Y, INT, DEC); 
  } 
} 
*/ 
 
 
//-------------- 
/* 
Bar的算法 
    ___ 
 |   | 
 |   | 
| |<-|-----BarLen 
 |   L 
 |   | 
 |   | 
 |  _|_ 
Bar的滑动距离是L-BarLen 
为了美观,可以在开始和结尾部分多流出来一些点,那么滑动距离要扣除这些点的长度,并在计算结果 
得到0的时候,添加上上端要留出来的点BarRemainDot 
2种显示方式: 
一种是BarLen是定长的, 
一种BarLen是根据显示总共的项数定下来的 
*/ 
 
 
//-------------- 
//Bar的长度 
//预留出来的点 
#define BarRemainDot  3 
//数字显示位置 
//#define BarNumPosX (128-8+2) 
#define BarNumPosY (7) 
//Bar的显示开始/结束位置 
//#define BarBeginPosX (126) 
#define BarBeginPosY (0*8) 
#define BarEndPosX (126) 
#define BarEndPosY (6*8) 
 
U8 _CONST_ BarCode0[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00}; 
U8 _CONST_ BarCode1[]={0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF}; 
extern U8 ItemBackup_i; 
extern U8 ItemBackup[]; 
 
void Bar(U8 Item_,U8 ItemNum_,U8 BarPosX,U8 BarNumPosX) 
{ 
    U8 U8_temp; 
    U8 DispFlag; 
    U8 YOffset; 
    U16 Temp; 
    U8 BarLen; 
    U8 Y; 
    U8 i; 
//    U8 CharBuf[5]; 
//    Bool HighBit; 
 
    BarLen = (BarEndPosY-BarBeginPosY-BarRemainDot)/(ItemNum_);//BarLen根据ItemNum_得到 
    if (BarLen == 0) { 
        BarLen = 5; 
    } 
    BarLen = 8; 
    Temp = Item_*(BarEndPosY-BarBeginPosY-BarLen-BarRemainDot);//BarRemainDot是被扣除的部分 
    Temp = Temp/(ItemNum_-1); 
    YOffset = (U8)Temp; 
    if(!Temp){//顶端,把预留的加上 
        YOffset = BarRemainDot; 
    } 
 
    for(Y = 0;Y < BarEndPosY/8;Y++){ 
        if((Y != (YOffset/8))&&(Y != (YOffset/8+1))){ 
            Display_Locate(0x00,BarPosX,Y);//清除 X=125 列 
            Display_Locate(0xFF,BarPosX+1,Y);//X=126列画线 
            Display_Locate(0x00,BarPosX+2,Y);//清除 X=127 列 
        }else{//Y = YOffset/8 Y = YOffset/8+1 
            Display_Locate(BarCode0[YOffset%8],BarPosX,(YOffset/8)); 
            Display_Locate(0xFF-BarCode0[YOffset%8],BarPosX+1,(YOffset/8)); 
            Display_Locate(BarCode0[YOffset%8],BarPosX+2,(YOffset/8)); 
            if((YOffset/8)+1 < (BarEndPosY/8)){//防止下越界 
                Display_Locate(BarCode1[YOffset%8],BarPosX,(YOffset/8+1)); 
                Display_Locate(0xFF-BarCode1[YOffset%8],BarPosX+1,(YOffset/8+1)); 
                Display_Locate(BarCode1[YOffset%8],BarPosX+2,(YOffset/8+1)); 
            } 
        } 
    } 
 
    GUI_SetEnFont(En_5x8); 
    Item_ += 1; 
    //显示Bar数字 
/* 
    for(i = 0; i < 5; i++){ 
        CharBuf[i] = (U8)(Item%10); 
        Item = Item/10; 
    } 
    HighBit = false; 
    for(i = 0; i < 5; i++){ 
        if(CharBuf[4-i]){//从最高位开始显示 
            GUI_DispCharAt(CharBuf[4-i]+'0',x+8*i,y); 
            HighBit = true; 
        }else{ 
            if(HighBit == true){ 
                GUI_DispCharAt('0',x+Char_XSIZE*i,y);//如果高位不为0,当前值为0 ,显示0 
            } 
        } 
    } 
*/ 
    DispFlag = false; 
    U8_temp = (U8)(Item_/100);//  百位 
    if(U8_temp){ 
        GUI_DispCharAt(U8_temp+'0',BarNumPosX-12,BarNumPosY); 
        DispFlag = true;//通知低位显示 
    }else{ 
        GUI_DispCharAt(' ',BarNumPosX-12,BarNumPosY); 
    } 
 
    Item_ = (Item_-U8_temp*100);//剔除百位 
    U8_temp = (U8)(Item_/10);//  十位 
    if(U8_temp||(DispFlag == true)){//本位不为0,或者高位已经显示,那么必须显示 
        GUI_DispCharAt(U8_temp+'0',BarNumPosX-6,BarNumPosY); 
        DispFlag = 1; 
    }else{ 
        GUI_DispCharAt(' ',BarNumPosX-6,BarNumPosY); 
    } 
 
    U8_temp = (U8)(Item_%10);//  个位 
    GUI_DispCharAt(U8_temp+'0',BarNumPosX,BarNumPosY); 
 
//---------------------------------- 
//显示历史索引号 
    if(ItemBackup_i > 1){//大于1才是 
        for(i = 0; i