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