⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcddrv.c

📁 广东肇庆金鹏实业有限公司液晶显示模块OMC12864-3驱动程序
💻 C
字号:
/********************************************************************/
/*    通用LCD 驱动程序 V0.01                                        */
/*                                                                  */
/*    作者:赵世平  2008/09                                         */
/*                                                                  */
/*    LCD 驱动程序源程序(LCDDRV.C)                                */
/*                                                                  */
/*    本驱动程序适用于NXP LPC2138 ARM7和128×64 单色LCD (KS0108 LCD*/
/*驱动器/控制器)                                                  */
/********************************************************************/

#include "config.h"

#include "..\FNT\asc12.h"
#include "..\FNT\hzk12_ct.h"
#include "..\FNT\hzk12_1.h"

#include "lcddrv.h"

#define NULL 0

#define LCD_USINGVERTICALLINE  /*如果LCD 输出垂直直线速度更快,可定义此宏,以加快某些基本图形的输出速度,否则应去掉此宏的定义*/

/********************************************************************/
/*    LPC2138 与KS0108 LCD通信使用的常量和宏,硬件相关。            */
/********************************************************************/

/*LCD 指令*/

#define LCD_DISPLAY_OFF 0x3e
#define LCD_DISPLAY_ON 0x3f
#define LCD_DISPLAY_X 0xb8
#define LCD_DISPLAY_Y 0x40
#define LCD_DISPLAY_Z 0xc0

#define LCD_COMMAND 0  /*指令*/
#define LCD_DATA 1  /*数据*/

/********************************************************************/
/*    LPC2138 与KS0108 LCD连接说明                                  */
/*                                                                  */
/*    液晶模块数据总线DB0—DB7连接在P1.16—P1.23上;                */
/*    读写使能连接在P0.2上;                                        */
/*    读/写连接在P0.3上,高电平:读,低电平:写;                  */
/*    数据/指令选择连接在P0.4上,高电平:写数据,低电平:写指令;  */
/*    /CS2连接在P0.5上,低电平:选择右半屏。                        */
/*    /CS1连接在P0.6上,低电平:选择左半屏;                        */
/********************************************************************/

#define SET_LCD_DB_PORT_INPUT() IO1DIR&=0xff00ffff
#define SET_LCD_DB_PORT_OUTPUT() IO1DIR|=0x00ff0000

#define READ_LCD_DB_PORT() (unsigned char)((IO1PIN>>16)&0x000000ff)
#define WRITE_LCD_DB_PORT(Content) {IO1CLR=0x00ff0000;IO1SET=((((unsigned long)Content)<<16)&0x00ff0000);}

#define INIT_LCD_E() IO0DIR|=(1<<2)
#define SET_LCD_E() IO0SET=(1<<2)
#define CLR_LCD_E() IO0CLR=(1<<2)

#define INIT_LCD_RW() IO0DIR|=(1<<3)
#define SET_LCD_RW() IO0SET=(1<<3)
#define CLR_LCD_RW() IO0CLR=(1<<3)

#define INIT_LCD_RS() IO0DIR|=(1<<4)
#define SET_LCD_RS() IO0SET=(1<<4)
#define CLR_LCD_RS() IO0CLR=(1<<4)

#define INIT_LCD_CS2() IO0DIR|=(1<<5)
#define SET_LCD_CS2() IO0SET=(1<<5)
#define CLR_LCD_CS2() IO0CLR=(1<<5)

#define INIT_LCD_CS1() IO0DIR|=(1<<6)
#define SET_LCD_CS1() IO0SET=(1<<6)
#define CLR_LCD_CS1() IO0CLR=(1<<6)

/********************************************************************/
/*    LCD 驱动程序内部使用的函数原型                                */
/********************************************************************/

static void LCD_Write(unsigned char DataCommand,unsigned char Content);  /*写数据或指令到 LCD*/
static unsigned char LCD_Read(void);  /*读LCD 数据*/
static void LCD_CheckBusy(void);  /*检查LCD 是否BUSY*/

/*在晶振频率为11.0592MHz的LPC2138 (系统频率为晶振频率的4 倍)上,本函数约延时count 毫秒*/

/*调用本函数时,为保证延时准确,应选择DebugInRAM或者RelInFLASH生成目标,尽量不要选择DebugInFLASH生成目标*/

static void dmsec(unsigned int count);

/********************************************************************/
/*    初始化LCD 和简单图形输出函数,直接访问LCD ,硬件相关。        */
/********************************************************************/

/*初始化 LCD*/

void LCD_Init(void)
{
	dmsec(1000);
	
	SET_LCD_DB_PORT_INPUT();

	INIT_LCD_E();
	INIT_LCD_RW();
	INIT_LCD_RS();
	INIT_LCD_CS2();
	INIT_LCD_CS1();

	CLR_LCD_CS1();
	CLR_LCD_CS2();

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_OFF);
	LCD_Write(LCD_COMMAND,LCD_DISPLAY_ON);

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_Z);
}

/*填充背景*/

void LCD_FillBackground(LCD_COLOR Color)
{
	unsigned char i,j;
	unsigned char Data1;

	CLR_LCD_CS1();
	CLR_LCD_CS2();

	Data1=(Color ? 0x00 : 0xff);

	for(i=0;i<8;i++)
	{
		for(j=0;j<128;j++)
		{
			LCD_Write(LCD_COMMAND,LCD_DISPLAY_X+i);
			LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+j);

			LCD_Write(LCD_DATA,Data1);
		}
	}
}

/*输出像素点*/

void LCD_PutPixel(LCD_CX x,LCD_CY y,LCD_COLOR Color)
{
	unsigned char LCD_x,LCD_y;
	unsigned char Data1;

	SET_LCD_CS1();
	SET_LCD_CS2();

	LCD_x=(unsigned char)y;
	
	if(x<64)
	{
		CLR_LCD_CS1();

		LCD_y=(unsigned char)x;
	}
	else
	{
		CLR_LCD_CS2();

		LCD_y=(unsigned char)x-64;
	}

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_X+(LCD_x>>3));
	LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+LCD_y);

	LCD_Read();
	Data1=LCD_Read();  /*设置列地址后,首次读LCD 数据,需连续读2 次*/

	Data1=(Color ? (Data1&(~(1<<(LCD_x&0x07)))) : (Data1|(1<<(LCD_x&0x07))));

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+LCD_y);

	LCD_Write(LCD_DATA,Data1);
}

/*输出水平直线*/

void LCD_PutHorizontalLine(LCD_CX x,LCD_CY y,LCD_CX Len,LCD_COLOR Color)
{
	unsigned char LCD_x,LCD_y1,LCD_y2;
	unsigned char Data1,Data2;
	unsigned char i,j;

	LCD_x=(unsigned char)y;
	LCD_y1=(unsigned char)x;
	LCD_y2=LCD_y1+(unsigned char)(Len-1);

	CLR_LCD_CS1();
	SET_LCD_CS2();

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_X+(LCD_x>>3));

	for(i=LCD_y1;(i<64)&&(i<=LCD_y2);i++)
	{
		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+i);

		LCD_Read();
		Data1=LCD_Read();  /*设置列地址后,首次读LCD 数据,需连续读2 次*/

		Data1=(Color ? (Data1&(~(1<<(LCD_x&0x07)))) : (Data1|(1<<(LCD_x&0x07))));

		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+i);

		LCD_Write(LCD_DATA,Data1);
	}

	if(LCD_y2<64) return;

	SET_LCD_CS1();
	CLR_LCD_CS2();

	LCD_Write(LCD_COMMAND,LCD_DISPLAY_X+(LCD_x>>3));

	for(j=(LCD_y1<64 ? 0 : LCD_y1-64);j<=LCD_y2-64;j++)
	{
		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+j);

		LCD_Read();
		Data2=LCD_Read();  /*设置列地址后,首次读LCD 数据,需连续读2 次*/

		Data2=(Color ? (Data2&(~(1<<(LCD_x&0x07)))) : (Data2|(1<<(LCD_x&0x07))));

		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+j);

		LCD_Write(LCD_DATA,Data2);
	}
}

/*输出垂直直线*/

void LCD_PutVerticalLine(LCD_CX x,LCD_CY y,LCD_CY Len,LCD_COLOR Color)
{
	unsigned char LCD_x1,LCD_x2,LCD_y;
	unsigned char Data1,Data2,Data3;
	unsigned char i,j;

	SET_LCD_CS1();
	SET_LCD_CS2();

	LCD_x1=(unsigned char)y;
	LCD_x2=LCD_x1+(unsigned char)(Len-1);

	if(x<64)
	{
		CLR_LCD_CS1();

		LCD_y=(unsigned char)x;
	}
	else
	{
		CLR_LCD_CS2();

		LCD_y=(unsigned char)x-64;
	}
	
	i=LCD_x1;
	
	while(i<=LCD_x2)
	{
		LCD_Write(LCD_COMMAND,LCD_DISPLAY_X+(i>>3));
		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+LCD_y);

		LCD_Read();
		Data1=LCD_Read();  /*设置列地址后,首次读LCD 数据,需连续读2 次*/
		
		Data2=0xff;
		Data3=0xff;
		
		j=i+8;

		if((i>>3)==(LCD_x1>>3))
		{
			Data2<<=(LCD_x1&0x07);
			
			j=((LCD_x1>>3)+1)<<3;
		}
		
		if((i>>3)==(LCD_x2>>3))
		{
			Data3>>=(7-(LCD_x2&0x07));
			
			j=LCD_x2+1;
		}

		Data1=(Color ? (Data1&(~(Data2&Data3))) : (Data1|(Data2&Data3)));
			
		LCD_Write(LCD_COMMAND,LCD_DISPLAY_Y+LCD_y);

		LCD_Write(LCD_DATA,Data1);
		
		i=j;
	}
}

/********************************************************************/
/*    基本图形输出函数,硬件无关,移植时通常无需修改。              */
/********************************************************************/

/*输出(任意)直线*/

void LCD_PutLine(LCD_CX x1,LCD_CY y1,LCD_CX x2,LCD_CY y2,LCD_COLOR Color)
{
	LCD_CX dx;
	LCD_CY dy;
	int dm,dn;
	int i;
	LCD_CX u;
	LCD_CY v;
	LCD_CX x;
	LCD_CY y;
	int Draw1;

	if(y1==y2)
	{
		LCD_PutHorizontalLine((x1<x2 ? x1 : x2),y1,(x1<x2 ? x2-x1+1 : x1-x2+1),Color);

		return;
	}

	if(x1==x2)
	{
		LCD_PutVerticalLine(x1,(y1<y2 ? y1 : y2),(y1<y2 ? y2-y1+1 : y1-y2+1),Color);

		return;
	}

	dx=(x1<x2 ? x2-x1 : x1-x2);
	dy=(y1<y2 ? y2-y1 : y1-y2);
	dm=(x1<x2 ? 1 : -1);
	dn=(y1<y2 ? 1 : -1);
	i=(dx>dy ? dx : dy);

	u=0;
	v=0;

	x=x1;
	y=y1;

	LCD_PutPixel(x,y,Color);

	Draw1=0;

	while(Draw1<i)
	{
		u+=dx;
		if(u>=i)
		{
			u-=i;
			x+=dm;
		}

		v+=dy;
		if(v>=i)
		{
			v-=i;
			y+=dn;
		}

		LCD_PutPixel(x,y,Color);

		Draw1++;
	}
}

/*输出矩形*/

void LCD_PutRectangle(LCD_CX x,LCD_CY y,LCD_CX Width,LCD_CY Height,LCD_COLOR Color)
{
	LCD_PutHorizontalLine(x,y,Width,Color);
	LCD_PutHorizontalLine(x,y+Height-1,Width,Color);
	LCD_PutVerticalLine(x,y,Height,Color);
	LCD_PutVerticalLine(x+Width-1,y,Height,Color);
}

/*输出填充矩形*/

void LCD_PutFilledRectangle(LCD_CX x,LCD_CY y,LCD_CX Width,LCD_CY Height,LCD_COLOR Color)
{

#ifdef LCD_USINGVERTICALLINE

	LCD_CX Draw1;

	for(Draw1=x;Draw1<x+Width;Draw1++)
	{
		LCD_PutVerticalLine(Draw1,y,Height,Color);
	}

#else

	LCD_CY Draw1;

	for(Draw1=y;Draw1<y+Height;Draw1++)
	{
		LCD_PutHorizontalLine(x,Draw1,Width,Color);
	}

#endif

}

/********************************************************************/
/*    文本输出函数,硬件无关,移植时根据字库进行修改。              */
/********************************************************************/

/********************************************************************/
/*    本驱动程序支持的字库说明                                      */
/*                                                                  */
/*    字体:宋体;                                                  */
/*    大小:西文6×12 ,远东字符(汉字)12×12;                    */
/*    西文字符集:可显示字符(ASCII 码32—126 );                  */
/*    远东字符集:GB2312常用特殊字符(01—03 区)和一级汉字( 16—55*/
/*区),包含全角字母、数字和标点符号,以及3755个一级汉字。          */
/*                                                                  */
/*    字库全部装载入LPC2138 的 Flash                                */
/********************************************************************/

/*文本输出(兼容西文字符和远东字符)*/

void LCD_TextOut(LCD_CX x,LCD_CY y,LCD_COLOR Color,LCD_PTEXTSTR TextStr,LCD_FONTNAME FontName,LCD_FONTSIZE FontSize)
{
	unsigned char *TextStr1;
	const unsigned char *FontDataPtr;
	int FontDataSize;
	LCD_CX CurrX;
	LCD_CX FontWidth;
	LCD_CY FontHeight;
	LCD_CY Draw1;
	LCD_CX Draw2;
	int Sch1,Sch2,Sch3;
	
	TextStr1=(unsigned char *)TextStr;

	CurrX=x;

	Sch1=0;

	while(TextStr1[Sch1]!=0)
	{
		FontDataPtr=NULL;
		FontDataSize=0;
		
		if(((TextStr1[Sch1]&0x80)==0x80)&&(TextStr1[Sch1+1]!=0))
		{
			if((FontName==LCD_FN_SONGTI)&&(FontSize==12))
			{
				/*GB2312常用特殊字符(01—03区)*/
			
				if((TextStr1[Sch1]>=161)&&(TextStr1[Sch1]<=163)&&(TextStr1[Sch1+1]>=161)&&(TextStr1[Sch1+1]<=254))
				{
					FontDataPtr=LCD_HZ12FontDataCT+24*(94*(TextStr1[Sch1]-161)+(TextStr1[Sch1+1]-161));
				}

				/*GB2312一级汉字(16—55区)*/
			
				if((TextStr1[Sch1]>=176)&&(TextStr1[Sch1]<=215)&&(TextStr1[Sch1+1]>=161)&&(TextStr1[Sch1+1]<=254))
				{
					FontDataPtr=LCD_HZ12FontData1+24*(94*(TextStr1[Sch1]-176)+(TextStr1[Sch1+1]-161));
				}
				
				FontDataSize=24;
			}

			FontWidth=(LCD_CX)FontSize;
			FontHeight=(LCD_CY)FontSize;

			Sch1+=2;
		}
		else
		{
			if((FontName==LCD_FN_SONGTI)&&(FontSize==12))
			{
				/*西文可显示字符*/
			
				if((TextStr1[Sch1]>=32)&&(TextStr1[Sch1]<=126))
				{
					FontDataPtr=LCD_Char12FontData+12*(TextStr1[Sch1]-32);
				}
				
				FontDataSize=12;
			}
			
			FontWidth=(LCD_CX)((FontSize+1)/2);
			FontHeight=(LCD_CY)FontSize;

			Sch1++;
		}
		
		if(FontDataPtr!=NULL)
		{
			Draw1=0;
			Draw2=0;
			
			for(Sch2=0;(Sch2<FontDataSize)&&(Draw1<FontHeight);Sch2++)
			{
				if(Draw2<FontWidth)
				{
					for(Sch3=0;Sch3<8;Sch3++)
					{
						if(FontDataPtr[Sch2]&((unsigned char)0x80>>Sch3))
						{
							LCD_PutPixel(CurrX+Draw2,y+Draw1,Color);
						}
						
						Draw2++;
						
						if(Draw2>=FontWidth)
						{
							Draw1++;
							Draw2=0;
							
							break;
						}
					}
				}
			}
		}

		CurrX+=FontWidth;
	}
}

/********************************************************************/
/*    LCD 驱动程序内部使用的函数,硬件相关。                        */
/********************************************************************/

/*写数据或指令到 LCD*/

static void LCD_Write(unsigned char DataCommand,unsigned char Content)
{
	unsigned int i;
	
	LCD_CheckBusy();

	if(DataCommand==0)
	{
		CLR_LCD_RS();
	}
	else
	{
		SET_LCD_RS();
	}

	CLR_LCD_RW();
	
	for(i=0;i<6;i++);
	
	SET_LCD_DB_PORT_OUTPUT();
	
	WRITE_LCD_DB_PORT(Content);	

	SET_LCD_E();

	for(i=0;i<6;i++);

	CLR_LCD_E();

	SET_LCD_DB_PORT_INPUT();
}

/*读LCD 数据*/

static unsigned char LCD_Read(void)
{
	unsigned char Data1;
	unsigned int i;

	LCD_CheckBusy();

	SET_LCD_RS();

	SET_LCD_RW();
	
	for(i=0;i<6;i++);

	SET_LCD_E();

	for(i=0;i<6;i++);
	
	Data1=READ_LCD_DB_PORT();

	CLR_LCD_E();

	return Data1;
}

/*检查LCD 是否BUSY*/

static void LCD_CheckBusy(void)
{
	unsigned char Data1;
	unsigned int i;

	CLR_LCD_RS();

	SET_LCD_RW();

	for(i=0;i<6;i++);

	SET_LCD_E();
	
	for(i=0;i<6;i++);
	
	do
	{
		Data1=READ_LCD_DB_PORT();
	}
	while((Data1&(1<<7))||(Data1&(1<<4)));

	CLR_LCD_E();
}

/*在晶振频率为11.0592MHz的LPC2138 (系统频率为晶振频率的4 倍)上,本函数约延时count 毫秒*/

/*调用本函数时,为保证延时准确,应选择DebugInRAM或者RelInFLASH生成目标,尽量不要选择DebugInFLASH生成目标*/

static void dmsec(unsigned int count)
{
	unsigned int i,j;

	for(i=0;i<count;i++)
	{
		for(j=0;j<7372;j++);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -