📄 lcd_fun.c
字号:
#include "at89x52.h"
#include "stdio.h"
#define uchar unsigned char
#define uint unsigned int
sbit sclk=P1^0;//时钟
sbit sdin=P1^1; //数据
sbit dc=P1^2;//1写数据,0写指令
sbit sce=P1^3;//片选
sbit res=P1^7;//复位,0复位
extern uchar code gFontLib[][24];
extern uchar code font6x8[][6];
//-------------------------------延时----------------------------------
void delayus(uchar m)
{
while(m--);
}
void delay_1ms(void) //1ms延时函数
{
uint i;
for (i=0;i<1140;i++);
}
void delay_nms(uint n) //N ms延时函数
{
uint i=0;
for (i=0;i<n;i++)
delay_1ms();
}
//----------------------------写一字节--------------------------------------------
void LCD_write_byte(uchar datatemp,bit mod)
{
uchar data i=8;
sce=0;
dc=mod; //mod=0,命令模式。mod=1,数据模式。
while (i--)
{
if (datatemp&0x80)
sdin=1;
else
sdin=0;
sclk=0;
sclk=1;
datatemp<<=1;
}
dc=1;
sce=1;
sdin=1;
}
//-----------------------LCD初始化--------------------------------------------
void LCD_init(void)
{
res=0;
delayus(100);
res=1;
sce=1;
sdin=1;
sclk=1;
LCD_write_byte(0x21,0);//初始化Lcd,功能设定使用扩充指令
LCD_write_byte(0xd5,0);//设定液晶偏置电压(高--低)
LCD_write_byte(0x20,0);//使用基本指令
LCD_write_byte(0x0C,0);//设定显示模式,正常显示
}
//----------------------设定地址 y=0~5,x=0~83----------------------------------------
void LCD_set_XY(uchar X, uchar Y)
{
LCD_write_byte(Y|0x40, 0); // column
LCD_write_byte(X|0x80 , 0); // row
}
//----------------------清全屏 ------------------------------------------------------
extern bit r0,r1,r2,r3;//对应某一行反显标志位;
extern uchar gLCDScr[4][7];
void LCD_clr(void)
{
uchar data m,n;
LCD_set_XY(0,0);
for (m=0;m<6;m++)
{
for (n=0;n<84;n++)
LCD_write_byte(0,1);
}
r0=r1=r2=r3=0;//对应某一行反显标志位同时清零
for(m=0;m<4;m++)//字符点阵跟踪表同时清零
for(n=0;n<7;n++)
gLCDScr[m][n]=0;
}
//----------------------正/反显示英文字符-------------------------------------------------
void LCD_write_char(uchar c,bit reverse)
{
uchar data line;
if(c>127)
c='?';
if(reverse)
for (line=0; line<6; line++)
LCD_write_byte(~font6x8[c][line], 1);
else
for (line=0; line<6; line++)
LCD_write_byte(font6x8[c][line], 1);
}
//-------------------正/反显示英文字符串显示函数-----------------------------------------------
//reverse为1则反显示。
void LCD_write_english_string(uchar X,uchar Y,char *s,bit reverse)
{
LCD_set_XY(X,Y);
while (*s)
{
LCD_write_char(*s,reverse);
s++;
}
}
/*--------------------在LCD上显示汉字------------------------------------------------------
输入参数:X、Y :显示汉字的起始X、Y坐标;
ch_wide :汉字点阵的宽度
num :显示汉字的个数;
line :汉字点阵数组中的起始行数
row :汉字显示的行间距
编写日期 :2004-8-11
最后修改日期 :2004-8-12
测试:
LCD_write_chi(0,0,12,7,0,0);
LCD_write_chi(0,2,12,7,0,0);
LCD_write_chi(0,4,12,7,0,0);
void LCD_write_chinese_string(uchar X, uchar Y,
uchar ch_wide,uchar num,
uchar line,uchar row)
{
uchar data i,n;
LCD_set_XY(X,Y); //设置初始位置
for (i=0;i<num;)
{
for (n=0; n<ch_wide*2; n++) //写一个汉字
{
if (n==ch_wide) //写汉字的下半部分
{
if (i==0) LCD_set_XY(X,Y+1);
else
LCD_set_XY((X+(ch_wide+row)*i),Y+1);
}
LCD_write_byte(gFontLib[line+i][n],1);
}
i++;
LCD_set_XY((X+(ch_wide+row)*i),Y);
}
}
*/
/*-----------------位图绘制函数------------------------------------------------------
输入参数:X、Y :位图绘制的起始X、Y坐标;
*map :位图点阵数据;
Pix_x :位图像素(长)
Pix_y :位图像素(宽)
编写日期 :2004-8-13
最后修改日期 :2004-8-13 */
void LCD_DrawPic(uchar X,uchar Y,uchar *map,
uchar Pix_x,uchar Pix_y)
{
uint data i,n;
uchar row;
if (Pix_y%8==0) row=Pix_y/8; //计算位图所占行数
else
row=Pix_y/8+1;
for (n=0;n<row;n++)
{
LCD_set_XY(X,Y);
for(i=0; i<Pix_x; i++)
{
LCD_write_byte(map[i+n*Pix_x], 1);
}
Y++; //换行
}
}
//----------------------写一屏图 -----------------------------------------------
/*void LCD_write_pic(uchar *map)
{
uchar e;
uchar t;
uchar k;
uint d=0;
for (t=0;t<6;t++)
{
for (k=0;k<84;k++)
{
e=*(map+d);
d++;
LCD_write_byte(e,1);
}
}
}*/
//---------------------------正/反显示 12*12点阵字符-------------------------------
/* 屏幕划分为4*7=28个区,用X,Y表示
0<=X<4, 0<=Y<7
字符点阵数据以小字库形式置于FLASH中
3310LCD以水平寻址模式时,每次接收8位,以列形式显示到屏幕中
因此,显示12*12点阵相当于用3字节显示2行字符
则第一行字符会履盖第二行的头4位
解决:设置一个显示字符点阵跟踪表
满屏显示4*7=28,需保存28个字符的点阵链接
表元素由1字节组成,可寻址256个字符 */
unsigned char idata gLCDx,gLCDy;//输出8位数据的最低位为点阵字的最高位
unsigned char gLCDScr[4][7]; // 字符点阵跟踪表
void LCD_set_RC(unsigned char x, unsigned char y) //R(row),C(column);
{
gLCDx = x;
gLCDy = y;
if(y>6) { //如果某行字数大于6
gLCDy = 0;
gLCDx ++; //跳向另一行开始位置
}
if(x>3)
gLCDx = 0;
if(x<2)
LCD_set_XY(y*12,x);
else
LCD_set_XY(y*12,x+1);
}
bit r0,r1,r2,r3;//对应某一行反显标志位;
void LCD_putc(unsigned char iIndex,bit reverse)
{
unsigned char data i,iTmp,dat;
gLCDScr[gLCDx][gLCDy] = iIndex;
LCD_set_RC(gLCDx,gLCDy);
switch(gLCDx) {
case 0:
if(reverse)
{ for(i=0;i<12;i++){ // 显示高8位
LCD_write_byte(~gFontLib[iIndex][i],1);
}
r0=1;
}
else
{ for(i=0;i<12;i++){ // 显示高8位
LCD_write_byte(gFontLib[iIndex][i],1);
}
r0=0;
}
LCD_set_XY(gLCDy*12,1);
for(i=0;i<12;i++) { // 显示低4位
iTmp = gLCDScr[1][gLCDy];
iTmp = gFontLib[iTmp][i]<<4;
//iTmp <<= 4;
dat = gFontLib[iIndex][i+12];
if(r0)
dat=~dat&0x0f;
if(r1) //避免写完第二行再写第一行时候有冲突。
iTmp=~iTmp&0xf0;
dat |= iTmp;
LCD_write_byte(dat,1);
}
break;
case 1:
if(reverse)
r1=1;//如果本行有反显;
else
r1=0;
for(i=0;i<12;i++) { // 显示高4位
iTmp = gLCDScr[0][gLCDy]; //
iTmp = gFontLib[iTmp][i+12];
dat = gFontLib[iIndex][i];
if(reverse)
dat=~dat;
dat <<= 4;
if(r0)//如果第一行有反显。避免写完第一行再写第二行有冲突;
iTmp=~iTmp&0x0f;
dat |= iTmp;
LCD_write_byte(dat,1);
}
LCD_set_XY(gLCDy*12,2);
for(i=0;i<12;i++) { // 显示低8位
iTmp = gFontLib[iIndex][i]>>4;
dat = gFontLib[iIndex][i+12]<<4;
dat |= iTmp;
if(r1)
dat=~dat;
LCD_write_byte(dat,1);
}
break;
case 2:
if(reverse)
{ for(i=0;i<12;i++){ // 显示高8位
LCD_write_byte(~gFontLib[iIndex][i],1);
}
r2=1;
}
else
{ for(i=0;i<12;i++){ // 显示高8位
LCD_write_byte(gFontLib[iIndex][i],1);
}
r2=0;
}
LCD_set_XY(gLCDy*12,4);
for(i=0;i<12;i++) { // 显示低4位
iTmp = gLCDScr[3][gLCDy]; //
iTmp = gFontLib[iTmp][i];
iTmp <<= 4;
dat = gFontLib[iIndex][i+12];
if(r2)
dat=~dat&0x0f;
if(r3)
iTmp=~iTmp&0xf0;
dat |= iTmp;
LCD_write_byte(dat,1);
}
break;
case 3:
if(reverse)
r3=1;//如果本行有反显;
else
r3=0;
for(i=0;i<12;i++) { // 显示高4位
iTmp = gLCDScr[2][gLCDy]; //
iTmp = gFontLib[iTmp][i+12];
dat = gFontLib[iIndex][i];
if(reverse)
dat=~dat;
dat <<= 4;
if(r2)//如果第三行有反显。避免写完第四行再写第三行有冲突;
iTmp=~iTmp&0x0f;
dat |= iTmp;
LCD_write_byte(dat,1);
}
LCD_set_XY(gLCDy*12,5);
for(i=0;i<12;i++) { // 显示低8位
iTmp = gFontLib[iIndex][i]>>4;
dat = gFontLib[iIndex][i+12]<<4;
dat |= iTmp;
if(r3)
dat=~dat;
LCD_write_byte(dat,1);
}
break;
default:
;
}
gLCDy ++;
if(gLCDy>6) {
gLCDy = 0;
gLCDx ++;
}
if(gLCDx>3)
gLCDx = 0;
}
//---------------------------正/反显示多个汉字-------------------------------
//因为每一行只有一个正反标志位,所以反显移动时,只能纵向。
void LCD_puts(unsigned char iIndex[],bit reverse)
{
unsigned char data i=0;
while(iIndex[i]){
LCD_putc(iIndex[i++], reverse);
}
}
//---------------修改putc函数,用于printf直接输出到液晶,只支持英文------------
bit printf_reverse=0;
char putchar(char c)
{
LCD_write_char(c,printf_reverse);
return 0;
}
//----------------条项显示函数,在函数一个制定位置显示条项文字-------------------
//*s条项文字字符串;r0 c0,条项文字起始坐标;c1,条项文字的尾坐标;Mode,对齐方式
/*void GUI_DispStringAtBar(unsigned char *s,unsigned char r0, unsigned char c0,
unsigned char c1,unsigned char Mode)
{ unsigned char data i,Cnt;
if(Mode==0)//左对齐
{
LCD_set_RC(r0,c0);
for(i=0;i<c1-c0;i++)
LCD_putc(*(s+i),0);
}
if(Mode==1)//居中
{
for(Cnt=0;*(s+Cnt);Cnt++);//计算所要显示的字体个数。
LCD_set_RC(r0,(c1-c0-Cnt)/2+c0);
for(i=0;i<Cnt;i++)
LCD_putc(*(s+i),0);
}
if(Mode==2)//右对齐
{ for(Cnt=0;*(s+Cnt)!=0;Cnt++);//计算所要显示的字体个数。
LCD_set_RC(r0,c1-Cnt);
for(i=0;i<Cnt;i++)
LCD_putc(*(s+i),0);
}
}*/
//-------------------------------比上一个函数增加反显----------------------------
void GUI_DispStringAt(unsigned char *s,unsigned char r0, unsigned char c0,
unsigned char c1,unsigned char Mode,bit reverse)
{ unsigned char data i,Cnt;
for(Cnt=0;*(s+Cnt)!=0;Cnt++);//计算所要显示的字体个数。
LCD_set_RC(r0,c0);
if(Mode==0)//左对齐
{
for(i=0;*(s+i);i++)
LCD_putc(*(s+i),reverse);//写字符
for(i=0;i<c1-c0-Cnt;i++) //写零
LCD_putc(0,reverse);
}
if(Mode==1)//居中
{
for(i=0;i<(c1-c0-Cnt)/2;i++)
LCD_putc(0,reverse);
for(i=0;i<Cnt;i++)
LCD_putc(*(s+i),reverse);
for(i=0;i<c1-c0-Cnt-1;i++)
LCD_putc(0,reverse);
}
if(Mode==2)//右对齐(未完成)
{
LCD_set_RC(r0,c1-Cnt);
for(i=0;i<Cnt;i++)
LCD_putc(*(s+i),0);
}
}
//-----------------------滚动条显示--------------------------------------------
//itembar所要显示项数,当前所在项数目;
#define BARBITLONG 32 //滚动杆像数长度。
#define LCDXEND 83 //x坐标最大值
void GUI_ScrollBar(unsigned char Item,unsigned char curbar)
{ uchar data i;//用做计数辅助以及计算结果暂存器,避免重复计算。
uchar data SmalBarStar;//滚动条开始像素位置
uchar data SmalBarEnd;//滚动条结束像素位置
i=BARBITLONG/Item;//暂存小滚动条像素长度。
SmalBarStar=curbar*i;//滚动条开始像素位置
SmalBarEnd=(curbar+1)*i;//滚动条结束像素位置
for(i=0;i<BARBITLONG/8;i++)
{ LCD_set_XY(LCDXEND-2,i);
LCD_write_byte(0,1);
LCD_write_byte(0xff,1);
LCD_write_byte(0,1);
}
if(BARBITLONG%8)
{
LCD_set_XY(LCDXEND-2,BARBITLONG/8);
LCD_write_byte(0,1);
LCD_write_byte(0xff>>(8-BARBITLONG%8),1);
LCD_write_byte(0,1);
}
//----滚动条横夸两字节时候---------
LCD_set_XY(LCDXEND-2,SmalBarStar/8); //显示第一字节部分
LCD_write_byte(0xff<<(SmalBarStar%8),1);
LCD_set_XY(LCDXEND,SmalBarStar/8);
LCD_write_byte(0xff<<(SmalBarStar%8),1);
if(SmalBarEnd!=BARBITLONG) //当不是拉到最后
{
LCD_set_XY(LCDXEND-2,SmalBarEnd/8); //显示第二字节部分
LCD_write_byte(0xff>>(8-SmalBarEnd%8),1);
LCD_set_XY(LCDXEND,SmalBarEnd/8);
LCD_write_byte(0xff>>(8-SmalBarEnd%8),1);
}
for(i=1;i<(char)(SmalBarEnd/8-SmalBarStar/8);i++)//当滚动条长度大于一个字节的时候。
{
LCD_set_XY(LCDXEND-2,SmalBarStar/8+i);
LCD_write_byte(0xff,1);
LCD_set_XY(LCDXEND,SmalBarStar/8+i);
LCD_write_byte(0xff,1);
}
LCD_set_XY(73,0);
printf("%d",(uint)(curbar+1));
}
//---------------------------------英文条项层-----------------------
void LCD_write_english_bar(unsigned char *s,unsigned char x0, unsigned char y0,
unsigned char x1,unsigned char Mode,bit reverse)
{ unsigned char i,Cnt;
for(Cnt=0;*(s+Cnt)!=0;Cnt++);//计算所要显示的字符个数。
LCD_set_XY(x0,y0);
if(Mode==0)//左对齐
{
for(i=0;*(s+i);i++)
LCD_write_char(*(s+i),reverse);//写字符
for(i=0;i<(x1-x0)/6-Cnt;i++) //写零
LCD_write_char(' ',reverse);
}
if(Mode==1)//居中
{
for(i=0;i<((x1-x0)/8-Cnt)/2;i++)
LCD_write_char(' ',reverse);
for(i=0;i<Cnt;i++)
LCD_write_char(*(s+i),reverse);
for(i=0;i<(x1-x0)/8-Cnt-1;i++)
LCD_write_char(' ',reverse);
}
if(Mode==2)//右对齐(未完成)
{
LCD_set_XY(r0,x1/8-Cnt);
for(i=0;i<Cnt;i++)
LCD_write_char(*(s+i),0);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -