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

📄 seriallcd.c

📁 4根串行信号线通过74HC595驱动并行点阵LCD
💻 C
字号:

//****************************************************
//  MSP430x12x利用74HC595驱动LM12864液晶程序         *
//  Project : MeterModule                            *
//  Company : ZhongYu                                *
//  Author : Jaleng                                  *
//  Time : 2006-01                                   *
//  Version : 1.0                                    *
//  LCDCLK--P1.3                                     *
//  LCDDATA--P2.0                                    *
//  LCDLATCH--P2.5                                   *
//  Built with IAR Embedded Workbench Version: 2.10A *
//****************************************************

#include "MSP430x12x.h"
#include "SerialLCD.h"

#define LCDCLK_DIROUT   P1DIR|=BIT3
#define LCDCLK_0        P1OUT&=~BIT3
#define LCDCLK_1        P1OUT|=BIT3

#define LCDDATA_DIROUT  P2DIR|=BIT0
#define LCDDATA_0       P2OUT&=~BIT0
#define LCDDATA_1       P2OUT|=BIT0

#define LCDLATCH_DIROUT P2DIR|=BIT5
#define LCDLATCH_0      P2OUT&=~BIT5
#define LCDLATCH_1      P2OUT|=BIT5

#define LCDCS1      BIT0
#define LCDCS2      BIT1
#define LCDRST      BIT2
#define LCDDI       BIT3
#define LCDRW       BIT4
#define LCDEN       BIT5
#define LCDBLK      BIT6

#define Y0_ADD 	0xb8	//x起始地址
#define X0_ADD 	0x40	//y起始地址

//unsigned char lcdmap[128][8];	//lcd内存映像区
/*unsigned char hzk[1024*265]={
#include "hzk16.dat"
};*/

/*芯片操作延时*/
void LCDDelay(void)
{
  unsigned char i;
  for(i=4;i>1;i--);
}

//LCD 初始化
void LCDInit (void)
{
  LCDLATCH_DIROUT;
  LCDCLK_DIROUT;
  LCDDATA_DIROUT;  
}

/*74HC595发送一组16位的数据*/
void HC595Shife(unsigned char Command,unsigned char LCDData)
{
  unsigned char i;
  LCDLATCH_0;
  LCDCLK_0;
  for(i=8; i>0; i--)
  {
    if ((Command & BIT7)==0)
    {
      LCDDATA_0;
      LCDCLK_1;
    }
    else
    {
      LCDDATA_1;
      LCDCLK_1;
    }
    LCDCLK_0;
    Command = Command<<1;
  }
  for(i=8; i>0; i--)
  {
    if ((LCDData & BIT7)==0)
    {
      LCDDATA_0;
      LCDCLK_1;
    }
    else
    {
      LCDDATA_1;
      LCDCLK_1;
    }
    LCDCLK_0;
    LCDData = LCDData<<1;
  }
  LCDLATCH_1;
  LCDLATCH_0;
}

//写入指令
void LCDWriteCommand(unsigned char Command,char cs)
{
  unsigned char LCDData=Command;
  if(cs==1)
  {
    Command &=~LCDCS2; Command |= LCDCS1;//选中CS1   		
  }
  if(cs==2)
  {
    Command &=~LCDCS1; Command |= LCDCS2; //选中CS2    
  }
  if(cs==3)
  {
    Command |=LCDCS1; Command |=LCDCS2;//选中CS1和CS2
  }			
  Command |= LCDEN;
  Command |= LCDRST;
  Command &=~LCDRW;	//写
  Command &=~LCDDI;	//写指令
  HC595Shife(Command,LCDData);
  LCDDelay();
  Command &=~LCDEN;
  HC595Shife(Command,LCDData);
  LCDDelay();   
}

//写入数据
void LCDWriteData(unsigned char LCDData)
{
  unsigned char Command=0;
  Command |= LCDEN;
  Command |= LCDRST;
  Command &=~LCDRW;	//写
  Command |= LCDDI;	//写数据
  HC595Shife(Command,LCDData);
  LCDDelay();
  Command &=~LCDEN;
  HC595Shife(Command,LCDData);
  LCDDelay();   
}

//往液晶写一个数据x是列地址从0~127,y是行地址0~7,对于超出屏幕范围的数据将不显示
//AG12864E液晶是纵向液晶,一个ram字节对应于屏幕上的一竖
void LCDwritedat(unsigned char dat,short x,short y)
{			
  if(x<0 || x>127 || y<0 || y>7)//数据有效性检查,超出屏幕范围的坐标直接返回
  return;
  //lcdmap[x][y]=dat;//写映像区
  if(x<64)
  {	
    LCDWriteCommand(X0_ADD+(unsigned char)x,1);
    LCDWriteCommand(Y0_ADD+(unsigned char)y,1);
    LCDWriteData(dat);
  }
  else if(x>63 && x<128)
  {
    LCDWriteCommand(Y0_ADD+(unsigned char)y,2);
    LCDWriteCommand(X0_ADD+(unsigned char)(x%64),2);
    LCDWriteData(dat);
  }
}

//往xy位置写一个英文字符
//x=0~15,y=0~3
void LCDwritechr(unsigned char *dat,short x,short y)
{
  short i,j,k;
  unsigned char chbuf[2][16];
  char f=32;
  x *= 8;
  y *= 2;	
  for(i=0;i<16;i++)
  {
    chbuf[0][i]=*(dat+i);
    chbuf[1][i]=0;
  }
  k=0;
  for(i=8;i>0;i--)
  {	
    f=16;
    for(j=0;j<8;j++)
    {
      f--;
      chbuf[1][k] |= ((chbuf[0][f] & (0x01<<(i-1)))<<(8-i))>>j;			
    }
    k++;
    //f=16;
    for(j=0;j<8;j++)
    {
      f--;
      chbuf[1][k] |= ((chbuf[0][f] & (0x01<<(i-1)))<<(8-i))>>j;			
    }
    k++;
  }	
  for(i=0;i<8;i++)
  {
      LCDwritedat(~chbuf[1][i*2],x+i,y+1);
      LCDwritedat(~chbuf[1][i*2+1],x+i,y);
  }
}

//清屏函数
void LCDclear(void)
{
  short x,y;
  for(x=0;x<128;x++)
  {
    for(y=0;y<8;y++)
    {
      LCDwritedat(0x00,x,y);
    }
  }
}

//关显示
void LCDclose(void)		
{
  LCDWriteCommand(0x3e,3);
}

//开显示					
void LCDopen(void)				
{
  LCDWriteCommand(0x3f,3);
}

//此函数用于在液晶的指定位置打印字符
//由于汉字的内码与区位码有一定的关系,
//所以,只要通过内码就可以得到区位码,从而也就得到了汉字的字模。  
//设一个汉字的内码为ddff,则此汉字的区码为dd-161;位码为ff-161;
//该汉字字模的第一个字节在字库中的位置是(94×区码+位码)×32。
//这时只要连续的读出32个字节,就可以得到该汉字的字模。
//假定全字库的首地址为hzk[];
//x,y以英文字符计算位置,x=0~15,y=0~3
//可以使用\n来回车换行,使用\r来使这一行居中显示并用空格填充前面的空格
//可以使用\n\n来填充空格到行未并换行,可以使用\r\r来使一行居右显示并用空格填充前面的空白
//可以使用\t来填充行首
void LCDprint(char *str,short x,short y)//缺省参数在当前位置打印
{
  char len,i,j;
  char ss=0;
  unsigned char *p,*ustr;
  short xpos=0,ypos=0;	//字符输出位置当前坐标
  len=strlen(str);
  ustr=(unsigned char *)str;
  if(x==-1 && y!=-1)
  { x=xpos; }
  else if(x!=-1 && y==-1)
  { y=ypos; }
  else if(x==-1 && y==-1)
  { x=xpos,y=ypos;  }
  xpos=x,ypos=y;
  for(i=0;i<len;i++)
  {
    if((ustr[i]) >= 128)			//最高位为1,是汉字
    {/*
        if(x>14)			//本行写不下汉字,则自动换行
        {
	  x=0;
	  y+=1;
	}
        p=hzk16;
        p+=(94*(ustr[i]-161)+(ustr[i+1]-161))*32;//得到当前汉字在字库中的首地址
        LCDwritechr(p,x,y);
        i++;
        x+=2;	//写入一个汉字光标右移两位(汉字)
        */ xpos=x,ypos=y;
		//对于ASC码超过128的字符自动舍去						
    }
    else if(*(str+i)<32)//对于ASC码小过32的不用的字符自动舍去
    {	
      if(*(str+i)==0x0a)		//是换行
      {
        if(*(str+i+1)==0x0a)	//填充行尾
	{
	  while(x<16)
	  {
	    LCDwritechr(&chr[0],x,y);
	    x++;
	  }
	  i++;
	}
	x=0;
	y++;
	xpos=x,ypos=y;
	continue;
      }
      if(*(str+i)==0x09)//填充行首
      {
	while(ss<x)
	{
//	  LCDwritechr(&chr[0],ss,y);
	  ss++;
	}
      }			
      if(*(str+i)==0x0d)			//接下来的字符居中显示
      {
        unsigned char k=0,t=0;
	while((*(str+i+1+t)!='\0') && (*(str+i+1+t)!=0x0a) )
	{
	  if(*(str+i+1+t)!=0x09 && *(str+i+1+t)!=0x0d)
	    k++;
	t++;																
	}				
	if(*(str+i+1)==0x0d)	//接下来的字符居右边显示
	{
	  i++;
	  if(k>=(16-xpos))
	  {
	    continue;
	  }
	  else
	  {						
	    x=xpos+(16-xpos-k);
	    for(j=xpos;j<x;j++)
//	      LCDwritechr(&chr[0],j,y);
	    xpos=x;						
	    continue;
	  }
	}
        else	//居中显示
	{
	  if(k>16)
	    continue;
	  x=(16-k)/2;
	  for(j=xpos;j<x;j++)
//	    LCDwritechr(&chr[0],j,y);
	  xpos=x,ypos=y;
	}
      	continue;
      }
    }
    else	//是英文字符
    {
      if(x>15)	//本行写不下,则自动换行
      {
        x=0;
	y++;
      }
      p =  chr;
      p += (*(str+i)-32)*16; 	//得到字符在字库中的首地址
      LCDwritechr(p,x,y);
      x++;	//写入一个字符光标右移1位
      xpos=x,ypos=y;
    }
  }
}

⌨️ 快捷键说明

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