12864液晶屏驱动程序

/*
控制器:st7565
串行驱动方式,唯一要注意的一点就是WR和RD这两个引脚虽然用不到,但是要接地,
否则无法正常显示。当时调了很久。不知道其他厂家的是否也这样。

*/
#include
#include

#include "LCD_Driver.h"
//字库
#include "hzk.h"

//当前字符显示的位置
//unsigned char Lcd_Charcter_CurrentX,Lcd_Charcter_CurrentY;
//当前像素显示位置
unsigned char Lcd_CurrentX,Lcd_CurrentY;
//图像反色显示 0 否 1是
bit LCD_DisplayReserve_Driver;

//定义LCD显示的全局变量
#define CS_Port P3_0
#define A0_Port P3_1
#define SI_Port P3_2
#define SCL_Port P3_3
#define RST_Port P3_4
enum PINDefine{CS,A0,SI,SCL,RST};

//设置某一位
void SETBit(unsigned char PIN)
{

switch (PIN)
{
case CS :
CS_Port=1;
break;

case A0 :
A0_Port=1;
break;

case SI :
SI_Port=1;
break;

case SCL :
SCL_Port=1;
break;

case RST :
RST_Port=1;
break;
}


}

//清某一位
void CLRBit(unsigned char PIN)
{
switch (PIN)
{
case CS :
CS_Port=0;
break;

case A0 :
A0_Port=0;
break;

case SI :
SI_Port=0;
break;

case SCL :
SCL_Port=0;
break;

case RST :
RST_Port=0;
break;
}
}


/***********************************
** 函数名称: Delay
** 功能描述: 延时时间=(n*9+17)*12/F
** 输 入: n
** 输 出 : 无
** 全局变量:无
** 调用模块: 无
******************************************/

void LCD_DelayMS(unsigned int n)
{
while(n--);
return;
}

//--------------------------------------------------------------------------
//串口移位输出
//--------------------------------------------------------------------------
void LCDShiftWrite(char datain)
{
unsigned char i;
unsigned char Series,Temp;
Series = datain;

for(i=8;i>0;i--)
{
CLRBit(SCL); //SCL=0
Temp=Series & 0x80;
if(Temp)
{
SETBit(SI);//SI=1
}
else
{
CLRBit(SI);//SI=0
}
SETBit(SCL); //SCL=1
Series = Series << 1;
}

}
/***********************************
** 函数名称: Write_Data
** 功能描述: 传送数据
** 输 入: dat
** 输 出 : 无
** 全局变量:无
** 调用模块: Busy,
******************************************/

void Write_Data(unsigned char dat)
{
CLRBit(CS); //CS=0
SETBit(A0); //A0=1,数据
LCDShiftWrite(dat);
SETBit(CS); //CS=1;
return;
}

/***********************************
** 函数名称: Write_Instruction
** 功能描述: 传送命令
** 输 入: dat
** 输 出 : 无
** 全局变量:无
** 调用模块: Busy,
******************************************/

void Write_Instruction(unsigned char cmd)
{
CLRBit(CS); //CS=0
CLRBit(A0); //A0=0,命令
LCDShiftWrite(cmd);
SETBit(CS); //CS=1;
return;
}

//==============================================================================高一级函数
//设置像素显示坐标(x:0-127,y:0-7


void LCD_setpos_Driver(unsigned char Lx,unsigned char Ly)
{
Write_Instruction(0xB0|Ly);// Page(Row)
Write_Instruction((0x10|(Lx>>4)));
Write_Instruction((0x0f&Lx));
Lcd_CurrentX=Lx;
Lcd_CurrentY=Ly;

}
/*
//设置像素显示坐标(x:0-127)
void LCD_setposX_Driver(unsigned char Lx)
{
Write_Instruction((0x10|(Lx>>4)));
Write_Instruction((0x0f&Lx));
}
//设置像素显示坐标(y:0-7)
void LCD_setposY_Driver(unsigned char Ly)
{
Write_Instruction(0xB0|Ly);// Page(Row)
}
*/

//设置字符位置(x:0-8,y:0-3)
void LCD_setCharpos_Driver(unsigned char Lx,unsigned char Ly)
{
//当前像素显示位置
Lcd_CurrentX=Lx*16;
Lcd_CurrentY=Ly*2;
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
}


//清屏
void LCD_CLS_Driver(char value)
{
unsigned char i,n;

for(i=0;i<9;i++)
{
LCD_setpos_Driver(0,i);

for(n=0;n<128;n++)
{
Write_Data(value);
}
}

}
//显示BMP图片
void LCD_DisplayBMP_Driver(unsigned char *PicData) //信息显示
{
unsigned char BMPwithLen,BMPheightLen;
unsigned char BMPwith;
unsigned char BMPheight;
BMPwith=*PicData;
PicData++;
BMPheight=(*PicData)/8;
PicData++;

//BMPLen=BMPheight/8*BMPwith

for(BMPheightLen=0;BMPheightLen{
Lcd_CurrentY++;
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
for(BMPwithLen=0;BMPwithLen{
//图像反色显示 0 否 1是
if (LCD_DisplayReserve_Driver==0)
{
Write_Data(*PicData);
}
else
{
Write_Data(~(*PicData));
}
PicData++;
};
}

}

void LCD_disp_DisplayImage_Driver(unsigned char * PicData,unsigned char PicLen) //信息显示
{

for(;PicLen>0;PicLen--)
{

//图像反色显示 0 否 1是
if (LCD_DisplayReserve_Driver==0)
{
Write_Data(*PicData);
}
else
{
Write_Data(~(*PicData));
}


PicData++;
};

}




//显示一个Unicode
void LCD_disp_Putchar_Driver(unsigned int uChar)
{
unsigned int i;
unsigned char *p;
if(uChar<128)
{
//for(i=0;i != ENGLISHCHARNUMBER;i++)
//{
//if(uChar==EnglishCode[i][0])
//{
p=(uChar-0x20)*(ENGLISHCHARLegth)+&nAsciiDot[0];

LCD_disp_DisplayImage_Driver(p, ENGLISHCHARLegth/2);
Lcd_CurrentY++;
//设置像素显示坐标(y:0-7)
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
LCD_disp_DisplayImage_Driver(p+(ENGLISHCHARLegth/2),(ENGLISHCHARLegth/2));
Lcd_CurrentY--;
Lcd_CurrentX+=8;
//设置像素显示坐标(y:0-7)
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
//break;
//}
//}
}
else
{
for(i=0;i!=GB_ZK_NUM;i++)
{
if(uChar==(GB_16[i].Index[0]*256+GB_16[i].Index[1]))
{
//分别在两页显示
LCD_disp

_DisplayImage_Driver(GB_16[i].Msk,(CHINESECHARlegth/2));
Lcd_CurrentY++;
//设置像素显示坐标(y:0-7)
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
LCD_disp_DisplayImage_Driver(GB_16[i].Msk+(CHINESECHARlegth/2),(CHINESECHARlegth/2));
Lcd_CurrentY--;
Lcd_CurrentX+=16;
//设置像素显示坐标(y:0-7)
LCD_setpos_Driver(Lcd_CurrentX,Lcd_CurrentY);
break;
}
}
}
}


//图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
void LCD_disp_SetReverse_Driver(unsigned char ReverseTrue)
{
//图像反色显示 0 否 1是
if (ReverseTrue==0)
{
LCD_DisplayReserve_Driver=0;
}
else
{
LCD_DisplayReserve_Driver=1;
}
}
//对比度设置
void Set_Contrast_Control_Register(unsigned char Level)
{
unsigned char Num,Temp1,Temp2;
Temp1 = (Level/16)<<4;
switch(Level%16)
{
case 10:
Temp2 = 0x0a;
break;
case 11:
Temp2 = 0x0b;
break;
case 12:
Temp2 = 0x0c;
break;
case 13:
Temp2 = 0x0d;
break;
case 14:
Temp2 = 0x0e;
break;
case 15:
Temp2 = 0x0f;
break;
default:
Temp2 = Level%16;
break;
}
Num = Temp1|Temp2;
Write_Instruction(0x81);
Write_Instruction(Num);
}




//初始化LCD屏
void init_LCD_Driver()
{

CLRBit(RST); // RST=0;
LCD_DelayMS(50);
SETBit(RST); // RST=1;
LCD_DelayMS(50);
Write_Instruction(0xa2); //lcd bias select 1/9 BIAS
Write_Instruction(0xa1); //ADC select,REVERSE 127-->0(a0,a1)
Write_Instruction(0xc0); //com select,NORMAL 0-->63(c8,c0)
Write_Instruction(0x26); //RESISTOR RATIO
Write_Instruction(0x81); //ELECTRONIC VOLUME mode setting 100B 对比度命令
Write_Instruction(0x10); //Set reference voltagel register 对比度数值
Write_Instruction(0x2f); //power control(VB,VR,VF=1,1,1)
LCD_DelayMS(50);
Write_Instruction(0xaf); //set display on
Write_Instruction(0xf8); //set booster ratio
Write_Instruction(0x00);
//当前像素显示位置
Lcd_CurrentX=0;
Lcd_CurrentY=0;
//图像反色显示 0 否 1是
LCD_DisplayReserve_Driver=0;
}







#include "LCD_SoftLayer.h"
#include "LCD_Driver.h"
/*----------------------------------------------------------------------------------------*/
//图形液晶显示字符驱动程序
//控制器件为:ST7565
//程序设计:中国传惠 TranSmart gongxd@https://www.360docs.net/doc/b815250624.html,
/*----------------------------------------------------------------------------------------*/

//以8*8字符计算,显示屏横向、纵向可以显示的点阵坐标;左、上、右、下以及当前的位置坐标
#define LCD_MAX_X 7
#define LCD_MAX_Y 3

#define LCD_MIN_X 0
#define LCD_MIN_Y 0



//初始化LCD屏
void init_LCD()
{
//初始化LCD屏
init_LCD_Driver();
}

void LCD_setpos(unsigned char x,unsigned char y)
{
if(y>LCD_MAX_Y) y=LCD_MIN_Y;
if(x>LCD_MAX_X) x=LCD_MIN_X;
LCD_setCharpos_Driver(x,y);
}


void LCD_disp_Putchar(unsigned char uChar) //

信息显示
{
LCD_disp_Putchar_Driver((unsigned int)uChar);
}

void LCD_disp_printR(unsigned char code *s,unsigned char x,unsigned char y)//显示汉字或英文字符
{
unsigned int i;
LCD_setpos(x,y);
for (;*s != 0;s++)
{
i=*s;
if(*s > 127)
{
s++;
i=i*256+*s;
}
LCD_disp_Putchar_Driver(i);
}
}

void LCD_disp_CLS()
{
//清屏
LCD_CLS_Driver(0);
}

//图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
void LCD_disp_SetReverse(unsigned char ReverseTrue)
{
//图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
LCD_disp_SetReverse_Driver(ReverseTrue);
}


/*
名称:GXD LCD多层菜单 v1.2
作者:中国传惠 TranSmart gongxd@https://www.360docs.net/doc/b815250624.html,

特点:
可以在液晶LCM上显示最大254层深度的菜单,可以非常方便的使用和移植。
字符型显示适用于St7920控制芯片。
图像显示适用于st7656控制芯片,不带字库要自己实现汉字字符显示
在图像模式下支持焦点菜单反白,
焦点菜单反白流程是:
1.调用 LCD_disp_SetReverse(1),打开液晶反白显示,以后的输出都是反白显示
2.输出焦点菜单内容
3.调用 LCD_disp_SetReverse(0),关闭液晶反白显示,以后的输出都是正常显示
可以根据此流程,在各种控制芯片上实现反白显示。


历史:
2009-9-22 添加在图形模式下焦点行反白的功能
2009-8-2 添加N层菜单功能,修改屏幕参数定义
2009-3-4 初始版本

编译环境:

IDE-Version:
uVision3 V3.33
Copyright (c) Keil Elektronik GmbH / Keil Software, Inc 2006

Tool Version Numbers:
工具链路径:C:\Keil\C51\BIN\
C Compiler: C51.Exe V8.05a
Assembler: A51.Exe
Linker/Locator: BL51.Exe V6.00
Librarian: LIB51.Exe V4.24
Hex Converter: OH51.Exe V2.6
CPU DLL: S8051.DLL V3.06
Dialog DLL: DP51.DLL V2.48b
Target DLL: C:\KEIL\VW_C.DLL
Dialog DLL: TP51.DLL V2.48b

版权声明:
义务:
1.如果您在使用中发现任何BUG,请通知gongxd@https://www.360docs.net/doc/b815250624.html,,我会及时改正,并给您一份最新的代码
2.请保留本声明

权利:
如果您同意履行上面的义务,您就可以完全免费将代码应用于任何商业非商业用途
但本代码版权归中国传惠gongxd@https://www.360docs.net/doc/b815250624.html, 所有,否则严禁使用本代码

建议:
如果您作了什么改进希望能通知gongxd@https://www.360docs.net/doc/b815250624.html,,最好能共享一下,
我也会给您一份 最新 的代码,共同进步嘛

后话:大家都不容易,如果您觉得这东西有点用,就尽情传播吧
*/

#include "menu.h"
#include "menu_res.h"

//菜单是否更新 1是 0否
unsigned char MenuDisPlayUpdate;


//所有菜单板的个数
#define MenuAllCount sizeof(MenuPanel)/sizeof(MenuPanelStruct)
Menu_Statestruct Menu_State;//菜单状态定义


//=================================================================================栈函数

//栈大小,

菜单深度
#define StackSize MenuDeep

//声明堆栈元素类型
typedef Menu_Statestruct StackElementType;
//栈元素数组声明
StackElementType MenuParentStack[StackSize];

//栈顶
unsigned char StackTOP;

//栈初始化
void StackINI()
{
StackTOP=0;
}
//测试栈是否空 1 是 0 否
unsigned char StackEmpty()
{
return StackTOP==0;
}
//测试栈是否满 1 是 0 否
unsigned char StackFull()
{
return StackTOP==StackSize;
}

//出栈
StackElementType StackPOP()
{
if (StackTOP==0)
{
return MenuParentStack[0];
}
StackTOP--;
return MenuParentStack[StackTOP];
}

//入栈
void StackPush(StackElementType INElement)
{
if (StackTOP==StackSize)
{
return;
}
MenuParentStack[StackTOP]=INElement;
StackTOP++;
}

//=================================================================================菜单函数
//已经到最顶了
void StackEmptyErr()
{
unsigned char code MenuTopErrMsg[]=
{"已经到最顶了"};
LCD_disp_CLS();
LCD_disp_printR(MenuTopErrMsg,1,1);
delayms(300);
LCD_disp_CLS();
//显示主菜单
Menu_State.CurrentPanel=0;//本级菜单的菜单索引号
Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
Menu_State.FocusLine=1; //焦点在屏上是第几项
}

//菜单达到最大深度,栈满提示函数
void StackFullErr()
{
unsigned char code MenuTopErrMsg[]=
{"菜单栈满无法继续"};
LCD_disp_CLS();
LCD_disp_printR(MenuTopErrMsg,0,1);
delayms(300);
LCD_disp_CLS();
}

//默认菜单处理函数
void voidNull()
{
}

//光标所在行菜单项显示
void UpdatedisplayMenu_Focus(unsigned char *MenuTxttmp)
{
#if FocusReverse==1
//图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
LCD_disp_SetReverse(1);
#endif
//显示菜单项
LCD_disp_printR(MenuTxttmp,MenuItemDisplayStartX,Menu_State.FocusLine+MenuItemDisplayStartY);

//是否显示每行菜单前的指示 0 否 1是 ,推荐字符液晶使用,图形液晶用反白
#if FocusPointDisply==1
//显示前面的指针
LCD_setpos(MenuPointX,Menu_State.FocusLine+MenuItemDisplayStartY);
LCD_disp_Putchar(MenuPointASCII);
#endif

#if FocusReverse==1
//图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
LCD_disp_SetReverse(0);
#endif


}

//菜单显示更新函数
void UpdatedisplayMenuPanel()
{
unsigned char i,DisplayLenCount;

MenuItemStruct *p;
p=MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+Menu_State.ItemStartDisplay;
DisplayLenCount=MenuPanel[Menu_State.CurrentPanel].MenuItemCount-Menu_State.ItemStartDisplay ;
if (DisplayLenCount>ScreenHLine)
{
DisplayLenCount=ScreenHLine;
}
LCD_disp_CLS();

for (i=0;i{
if (i==Menu_State.FocusLine)
{
//光标所在行菜单项显示,可以自定义反白显示


UpdatedisplayMenu_Focus(p->MenuTxt);
}
else
{
LCD_disp_printR(p->MenuTxt,MenuItemDisplayStartX,i+MenuItemDisplayStartY);
}
p++;
}




}

//按键处理函数
void UpdateMenuPanelkeyInner(unsigned char MenuKeyCode)
{
unsigned char i;
//父菜单堆栈临时元素
Menu_Statestruct tmpParent;

//菜单是否更新 1是 0否
MenuDisPlayUpdate=1;

switch (MenuKeyCode)
{

//一直按着向上键
case MenuKey_UpCon:

case MenuKey_Up:


if (Menu_State.FocusLine>0)
{
Menu_State.FocusLine--; //焦点在屏上是第几项
}
else
{
if (Menu_State.ItemStartDisplay>0)
{
Menu_State.ItemStartDisplay--;
}
else
{
Menu_State.ItemStartDisplay=MenuPanel[Menu_State.CurrentPanel].MenuItemCount-1;
}

}

break;

//一直按着向下键
case MenuKey_DownCon:
case MenuKey_Down:
if ((Menu_State.ItemStartDisplay+Menu_State.FocusLine){
if (Menu_State.FocusLine{
Menu_State.FocusLine++; //焦点在屏上是第几项
}
else
{
Menu_State.ItemStartDisplay++; //显示第一项对应的菜单条目索引
}
}
else
{
Menu_State.FocusLine=0;
Menu_State.ItemStartDisplay=0;
}

break;
case MenuKey_Ok:

i=Menu_State.FocusLine+Menu_State.ItemStartDisplay;
if ((MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->MenuChildID==MenuNoChild)
{
(*((MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->CurrentOperate))();
}
else
{
if (StackFull()==0)
{
//父菜单显示在屏幕上的第一条条目
tmpParent.ItemStartDisplay=Menu_State.ItemStartDisplay;
//焦点在屏上是第几项
tmpParent.FocusLine=Menu_State.FocusLine;
//父菜单号
tmpParent.CurrentPanel=Menu_State.CurrentPanel;//本级菜单的菜单索引号
//入栈
StackPush(tmpParent);


Menu_State.CurrentPanel=(MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->MenuChildID;//父菜单的菜单索引号
Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
Menu_State.FocusLine=0; //焦点在屏上是第几项

}
else
{
//菜单达到最大深度,栈满提示函数
StackFullErr();

}

};
break;
//一直按着返回键
case Me

nuKey_CancelCon:
case MenuKey_Cancel:
//测试栈是否空 1 是 0 否
if( StackEmpty()==0)
{
tmpParent=StackPOP();
Menu_State.CurrentPanel=tmpParent.CurrentPanel;
Menu_State.ItemStartDisplay=tmpParent.ItemStartDisplay; //显示第一项对应的菜单条目索引
Menu_State.FocusLine=tmpParent.FocusLine; //焦点在屏上是第几项

}
else
{
//菜单已经到最顶了,栈空提示函数
StackEmptyErr();

}

break;

default:
//菜单是否更新 1是 0否
MenuDisPlayUpdate=0;
break;

}
}

void UpdateMenuPanelkey(unsigned char MenuKeyCode)
{
if (MenuKeyCode==MenuKey_Null)
{
return;
}
//弄这两个函数并列目的是减小RAM使用
UpdateMenuPanelkeyInner(MenuKeyCode);//更新按键
//菜单是否更新 1是 0否
if (MenuDisPlayUpdate==1)
{
UpdatedisplayMenuPanel();//更新菜单显示
}

}


void init_Menu()
{
//菜单栈初始化
StackINI();

Menu_State.CurrentPanel=0;//本级菜单的菜单索引号
Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
Menu_State.FocusLine=1; //焦点在屏上是第几项
UpdatedisplayMenuPanel();//更新菜单
}

相关文档
最新文档