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

📄 lcd_fun.c

📁 使用51单片机作为控制器
💻 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 + -