📄 lcd_drv.c
字号:
//=============================================
// 320X240@单色LCD基本函数
//控制电路SED1335,总线方式
//==============================================
#include "lcd_defs.h"
#include "ha_defs.h" //LCD寄存器地址
#include "type.h"
#include "font.h"
//--------1335初始化-------------------
void Init1335(void)
{
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
LcdCommand(0x40); //系统设置指令,8个参数
LcdDataWrite(0x30);
LcdDataWrite(0x87);
LcdDataWrite(0x07);
LcdDataWrite(39); //显示域长度为320dot
LcdDataWrite(66); //确定液晶工作频率66
LcdDataWrite(240); //显示屏高度为240dot
LcdDataWrite(40); //显示屏一行所占显示缓冲区字节数(L)
LcdDataWrite(0); //显示屏一行所占显示缓冲区字节数(H)
LcdCommand(0x44); //显示区设置,最多10个参数
LcdDataWrite(0x00); //显示1区对应的显示RAM起始地址(L)
LcdDataWrite(0x00); //显示1区对应的显示RAM起始地址(H)
LcdDataWrite(240); //显示1区控制240行
LcdDataWrite(9600%256);//显示2区对应的显示RAM起始地址(L) (0+40×240=9600)
LcdDataWrite(9600/256);//显示2区对应的显示RAM起始地址(H)
LcdDataWrite(240); //显示2区控制240行
LcdDataWrite(SAD3%256);//显示3区对应的显示RAM起始地址(L) (19200)
LcdDataWrite(SAD3/256);//显示3区对应的显示RAM起始地址(H)
LcdDataWrite(SAD4%256);//显示4区对应的显示RAM起始地址(L) (28800)
LcdDataWrite(SAD4/256);//显示4区对应的显示RAM起始地址(H)
LcdCommand(0x5a); //水平卷动,初始化时必须清零
LcdDataWrite(0x00);
LcdCommand(0x5b); //各个显示区的合成方式,1个参数
LcdDataWrite(0x0c); //简单叠加,图形模式
LcdCommand(0x59); //打开显示,1个参数
LcdDataWrite(0x14); //开显示区1和2,不闪烁,光标关闭
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//----清一、二屏-----------------
void LcdClear(void)
{
INT8U i,j;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
LcdCommand(0x4c); //光标向后移动
LcdLocate(0,0,SAD1); //第1区
LcdCommand(0x42);
for(j=0;j<240;j++)
{
for(i=0;i<40;i++)
LcdDataWrite(0x00);
}
LcdLocate(0,0,SAD2); //第2区
LcdCommand(0x42);
for(j=0;j<240;j++)
{
for(i=0;i<40;i++)
LcdDataWrite(0x00);
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//--------清指定区域--------------------------------------------
//入口:(x1,y1)=左上角
// (x2,y2)=右上角
void DisClrRec(INT16U x1,INT16U y1,INT16U x2,INT16U y2,INT16U offset)
{
INT16U j,i;
INT8U temp;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
LcdCommand(0x4c); //光标向后移动
for(j=y1;j<y2;j++)
{
temp = LcdRead(x1,j,offset);
temp &= (0xff<<(8-x1%8));
LcdWrite(x1,j,temp,offset);
}
for(j=y1;j<y2;j++)
{
LcdLocate(x1+8,j,offset);
LcdCommand(0x42);
for(i=x1+8;i<x2;i=i+8)
{
LcdDataWrite(0x00);
}
}
for(j=y1;j<y2;j++)
{
temp = LcdRead(x2,j,offset);
temp &= (0xff>>(x2%8));
LcdWrite(x2,j,temp,offset);
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//--------填充指定区域--------------------------------------------
//入口:(x1,y1)=左上角
// (x2,y2)=右上角
void DisFullRec(INT16U x1,INT16U y1,INT16U x2,INT16U y2,INT16U offset)
{
INT8U temp;
INT16U i,j;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
LcdCommand(0x4c); //光标向后移动
for(j=y1;j<y2;j++)
{
temp = LcdRead(x1,j,offset);
temp |= (0xff>>(x1%8));
LcdWrite(x1,j,temp,offset);
}
for(j=y1;j<y2;j++)
{
LcdLocate(x1+8,j,offset);
LcdCommand(0x42);
for(i=x1+8;i<x2;i=i+8)
{
LcdDataWrite(0xff);
}
}
for(j=y1;j<y2;j++)
{
temp = LcdRead(x2,j,offset);
temp |= (0xff<<(8-x2%8));
LcdWrite(x2,j,temp,offset);
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//----画点-------------------------
//入口:(x,y)=位置
void DisDot(INT16U x,INT16U y,INT16U offset)
{
INT8U temp;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
temp = LcdRead(x,y,offset);
temp |= (0x80>>(x%8));
LcdWrite(x,y,temp,offset);
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//----擦除1点-------------------------
//入口:(x,y)=位置
void DisClrDot(INT16U x,INT16U y,INT16U offset)
{
INT8U temp,temp1;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
temp = LcdRead(x,y,offset);
temp1 = (0x80>>(x%8));
temp1 = ~temp1;
temp &= temp1;
LcdWrite(x,y,temp,offset);
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//-----虚线 只提供X或Y方向的,不支持斜线(11110000)-------------
//4点实4点虚间隔
//入口:(x1,y1)=起点
// (x2,y2)=终点
//注意:终点坐标必须>=起点坐标
void Dashed(INT16U x1,INT16U y1,INT16U x2,INT16U y2,INT16U offset)
{
INT16U i;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
//画竖线
if(x1==x2)
{
for(i=y1;i<=y2-3;i=i+8)
{
DisDot(x1,i,offset);
DisDot(x1,i+1,offset);
DisDot(x1,i+2,offset);
DisDot(x1,i+3,offset);
}
}
//画横线
else if(y1==y2)
{
for(i=x1;i<x2-3;i=i+8)
{
DisDot(i,y1,offset);
DisDot(i+1,y1,offset);
DisDot(i+2,y1,offset);
DisDot(i+3,y1,offset);
}
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//----画实线-支持斜线-------------
//入口:neg=0,画,=1擦
// (x1,y1)=起点,(x2,y2)=终点
//注意:画直线时终点坐标必须>=起点坐标
void Line(INT8U neg,INT16U x1,INT16U y1,INT16U x2,INT16U y2,INT16U offset)
{
INT16U i;
INT16U xerr=0,yerr=0;
INT16U delta_x,delta_y,distance;
INT16U incx,incy;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
//画竖线
if(x1==x2)
{
for(i=y1;i<y2;i++)
{
if(neg) DisClrDot(x1,i,offset);
else DisDot(x1,i,offset);
}
}
//画横线
else if(y1==y2)
{
for(i=x1;i<x2;i++)
{
if(neg) DisClrDot(i,y1,offset);
else DisDot(i,y1,offset);
}
}
//画斜线
else
{
if(x2>x1)
{
delta_x = x2-x1; // 计算两个方向的距离
incx = 1;
}
else
{
delta_x = x1-x2;
incx = 2;
}
if(y2>y1)
{
delta_y = y2-y1; // 计算两个方向的距离
incy = 1;
}
else
{
delta_y = y1-y2;
incy = 2;
}
if(delta_x>delta_y) //判断哪个方向增量大
distance = delta_x;
else
distance = delta_y;
for(i=0;i<distance;i++) //画线
{
if(neg) DisClrDot(x1,y1,offset);
else DisDot(x1,y1,offset);
xerr += delta_x ;
yerr += delta_y ;
if(xerr>=distance ) //计算哪些地方为45度斜线,哪些地方为横线或竖线
{ //当x方向大于45度时,x+1,否则x不变
xerr -= distance;
if(incx==2) x1 -= 1;
else x1 += incx;
}
if(yerr>=distance )
{ //当y方向大于45度时,y+1,否则y不变
yerr -= distance;
if(incy==2) y1 -= 1;
else y1 += incy;
}
}
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//--------矩形框-----------------------------------------------------
//入口:(x1,y1)=左上角
// (x2,y2)=右上角
void DisRec(INT16U x1,INT16U y1,INT16U x2,INT16U y2,INT16U offset)
{
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
Line(0,x1,y1,x1,y2,offset);
Line(0,x2,y1,x2,y2,offset);
Line(0,x1,y1,x2,y1,offset);
Line(0,x1,y2,x2+1,y2,offset);
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//-----在液晶屏指定位置显示一个8*12字符---------
//入口:neg=1 反白
// (x,y)=起始坐标
// ps=点阵指针
//注意:.x必须被8整除
void Dis8X12Chr(INT8U neg,INT16U x,INT16U y,INT8U chr,INT16U offset)
{
INT8U i,temp;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
LcdCommand(0x4f); //光标向下移动
LcdLocate(x,y,offset);
LcdCommand(0x42); //设置写命令
for(i=0;i<12;i++)
{
temp = S8X12Tab[(chr-0x20)*12+i];
if(neg) temp = ~temp;
LcdDataWrite(temp); //写数据
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//-----在液晶屏指定位置显示一个8*12字符串---------
//入口:neg=1 反白
// (x,y)=起始坐标
// ps=字符串指针
//注意:1.x必须被8整除,不处理换行
// 2.字符串为Ascii码
void Dis8X12Str(INT8U neg,INT16U x,INT16U y,INT8U *ps,INT16U offset)
{
INT8U i;
INT16U xbak;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
xbak = x;
for(i=0;i<strlen((char *)(ps));i++)
{
Dis8X12Chr(neg,xbak,y,*(ps+i),offset);
xbak += 8;
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//-----在液晶屏指定位置显示一个8*12字符串(无效0不显示)---------
//入口:neg=1 反白
// (x,y)=起始坐标
// ps=字符串指针
//注意:1.x必须被8整除,不处理换行
// 2.字符串为Ascii码
void Dis8X12DStr(INT8U neg,INT16U x,INT16U y,INT8U *ps,INT16U offset)
{
INT8U i,flag=0;
INT8U *pt;
for(i=0;i<strlen((char *)(ps));i++)
Dis8X12Chr(0,x+i*8,y,' ',offset);
for(i=0;i<strlen((char *)(ps));i++)
{
if(*ps == '-')
{
ps++;
flag = 1;
continue;
}
if((*ps == '0')&&(*(ps+1) != '.'))
ps++;
else
break;
}
pt = ps;
if(flag)
{
Dis8X12Chr(neg,x,y,'-',offset);
x += 8;
}
Dis8X12Str(neg,x,y,pt,offset);
}
//-----在液晶屏指定位置显示一个16*16汉字---------
//入口:neg=1 反白
// (x,y)=起始坐标
// p=点阵指针
//注意:x必须被8整除
void Dis16X16Chr(INT8U neg,INT16U x,INT16U y,INT8U *p,INT16U offset)
{
INT8U i,j,temp;
INT16U xbak;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
xbak = x;
LcdCommand(0x4c);
for(i=0;i<16;i++)//16
{
LcdLocate(xbak,y+i,offset);
LcdCommand(0x42); //设置写命令
for(j=0;j<2;j++)
{
temp = *(p+i*2+j);
if(neg) temp = ~temp;
LcdDataWrite(temp); //写数据
}
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
/*
//-----在液晶屏指定位置显示一个16*16字符串---------
//字库按顺序排列,2分法查表
//x必须被8整除,不处理换行
//入口:neg=1 反白
// (x,y)=起始坐标
// p=字符串指针
//注意:1.x必须被8整除,不处理换行
// 2.字符串为汉字国标内码
void Dis16X16Str(INT8U neg,INT16U x,INT16U y,INT8U *p,INT16U offset)
{
INT16U xbak,temp,i;
INT8U *zikupoint;
xbak = x;
while(*p != 0x00) //0x00是字符串的结束标志
{
temp = *p;
temp = (temp<<8)|*(p+1);
i = Font2Tab(temp); //2分法查
zikupoint = S16X16Tab+i*32;
Dis16X16Chr(neg,xbak,y,zikupoint,offset);
xbak += 16;
p += 2;
}
}
*/
//-----在液晶屏指定位置显示一个16*16字符串---------
//字库随机排列,从头顺序查表
//x必须被8整除,不处理换行
//入口:neg=1 反白
// (x,y)=起始坐标
// p=字符串指针
//注意:1.x必须被8整除,不处理换行
// 2.字符串为汉字国标内码
void Dis16X16Str(INT8U neg,INT16U x,INT16U y,INT8U *p,INT16U offset)
{
INT16U xbak,temp,i;
INT8U *zikupoint;
INT8U j;
xbak = x;
while(*p != 0x00) //0x00是字符串的结束标志
{
for(i=0;;i++)
{
if(((GB_16[i].Index[0]== *p)&&(GB_16[i].Index[1]== *(p+1)))||(GB_16[i].Index[0]==0xff))
break;
}
zikupoint = &GB_16[i].Msk[0];
Dis16X16Chr(neg,xbak,y,zikupoint,offset);
xbak += 16;
p += 2;
}
}
//-------在液晶屏指定位置显示一个32X32图标------------
void Dis32X32Chr(INT8U neg,INT16U x,INT16U y,INT16U chr,INT16U offset)
{
INT8U i,j,temp;
INT16U xbak;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
xbak = x;
LcdCommand(0x4c); //光标向右移动
for(i=0;i<32;i++)
{
LcdLocate(xbak,y+i,offset);
LcdCommand(0x42); //设置写命令
for(j=0;j<4;j++)
{
temp = S32X32Tab[chr*128+i*4+j];
if(neg) temp = ~temp;
LcdDataWrite(temp); //写数据
}
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
/*
//------字库2分法查表---------------------
INT16U Font2Tab(INT16U ch)
{
INT16U max,min,t;
INT16U temp;
min = 0; max = strlen((INT8U *)(GB16X16Tab));
do{
t = ((max-min)/4)*2 + min;
temp = GB16X16Tab[t];
temp = (temp<<8)|GB16X16Tab[t+1];
if(temp<ch) min = t;
else if(temp>ch) max = t;
else
{
min = t; break;
}
}while((max-min)>2);
return(min/2);
}*/
//-------在液晶屏指定位置显示一个图片PICTab[220*32]------------
void DisPic(INT16U x,INT16U y,INT16U offset)
{
INT8U i,j,temp;
INT16U xbak;
#ifndef LCD_DATABUS
LCDCS = 0;
#endif
xbak = x;
LcdCommand(0x4c); //光标向右移动
for(i=0;i<220;i++)
{
LcdLocate(xbak,y+i,offset);
LcdCommand(0x42); //设置写命令
for(j=0;j<32;j++)
{
temp = PICTab[i*32+j];
LcdDataWrite(temp); //写数据
}
}
#ifndef LCD_DATABUS
LCDCS = 1;
#endif
}
//--------光标定位在指定位置------------------
void LcdLocate(INT16U x,INT16U y,INT16U offset)
{
INT16U add;
LcdCommand(0x46); //设置光标地址,2个参数
add = x/8+y*40+offset;
LcdDataWrite((unsigned char)add); //低位地址
LcdDataWrite((unsigned char)(add>>8)); //高位地址
}
//-------读液晶显存 ----------------
unsigned char LcdRead(INT16U x,INT16U y,INT16U offset)
{
INT8U temp=1;
LcdLocate(x,y,offset);
LcdCommand(0x43); //设置读命令
temp = LcdDataRead();
return(temp);
}
//-------写液晶显存 ----------------
void LcdWrite(INT16U x,INT16U y,INT8U dat,INT16U offset)
{
LcdLocate(x,y,offset);
LcdCommand(0x42); //设置写命令
LcdDataWrite(dat); //写数据
}
//-----写命令---------------------
void LcdCommand(INT8U c)
{
#ifndef LCD_DATABUS
LCDRS = 1;
LCDRD = 1;
LCDWR = 0;
_nop_();_nop_();
LcmDataPort = c;
_nop_();_nop_();
LCDWR = 1;
#else
LcdWriteCmd = c;
#endif
}
//-----写数据---------------------
void LcdDataWrite(INT8U d)
{
#ifndef LCD_DATABUS
LCDRD = 1;
LCDRS = 0;
LCDWR = 0;
_nop_();_nop_();
LcmDataPort = d;
_nop_();_nop_();
LCDWR = 1;
#else
LcdWriteData = d;
#endif
}
//-----读数据---------------------
INT8U LcdDataRead(void)
{
unsigned char temp;
#ifndef LCD_DATABUS
LCDRS = 1;
LCDWR = 1;
LcmDataPort = 0xff;
LCDRD = 0;
_nop_();_nop_();_nop_();_nop_();_nop_();
temp = LcmDataPort;
LCDRD = 1;
#else
temp = LcdReadData;
#endif
return(temp);
}
//==============end==========================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -