📄 lcddrv.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 + -