📄 lcm16x16.c
字号:
/*--------------------------------------------
主题:LCM-NT7534显示程序
功能:将输入的字符内码显示在LCM上,支持全角字符。字库存于SRAM中
LCM驱动IC型号为:NT7534
MCU型号为:STC89LE52
晶振频率为11.0592MHz
;连线图:
;*LCM---89S52* *LCM---89S52* *LCM-------89S52* *LCM----------89S52* *
;*DB0---P0.0* *DB4---P0.4* *D/I-------P2.6* *CS1----------P2.4* *
;*DB1---P0.1* *DB5---P0.5* *R/W-------P2.7* *CS2----------P2.5* *
;*DB2---P0.2* *DB6---P0.6* *RST--------VCC* *CS3----------P3.2* *
;*DB3---P0.3* *DB7---P0.7* *E---------P2.3* *
-------------------------------------------------*/
/*#pragma src /*生成ASM文件开关,必要时打开 */
#include <reg52.h>
#include <stdarg.h>
#include<INTRINS.H>
#define Uchar unsigned char
/***********液晶显示器接口引脚定义***************/
/*说明:由于LCM的CS1端是通过74HC138控制的,当P2.0/P2.1/P2.2均为0时是选中LCM
的CS1端,LCM被激活,如果单片机I/O直接控制CS1端,则请取消下面的CS_2/CS_3两
项,并修改下LCM读写函数即可。*/
sbit CS_1=P2^0; //74HC138控制端口A
sbit CS_2=P2^1; //74HC138控制端口B
sbit CS_3=P2^2; //74HC138控制端口C
sbit Alcm= P2^4; //LCD命令和数据控制口,为1时是读写数据;为0时写入命令
sfr Data= 0x80; //数据口为P0
/***********LCM常用操作命令和参数定义***************/
#define DISPON 0xAf /*显示on */
#define DISPOFF 0xAe /*显示off */
#define DISPFIRST 0x40 /*显示起始行定义 */
#define SETX1 0x00 /*X定位低4位设定指令(列) */
#define SETX2 0x10 /*X定位高4位设定指令(列) */
#define SETY 0xb0 /*Y定位设定指令(页) */
#define Lcdbusy 0x80 /*LCM忙判断位,当读出数据的最高位为1时,表示正忙。 */
#define DISCURRENT 0x81 /*进入到电流量设定 */
/*初始化LCD时用到的指令和参数定义*/
#define DISADC 0xA0 /*LCM显示ADC设定,顺方向 */
#define DISVOL 0xA2 /*LCM显示偏压设定(取中间值) */
#define DISCOM 0xCF /*LCM公共输出模式选择,逆方向 */
#define DISNORMAL 0xA6 /*一般显示指令 */
#define DISREVERSE 0xA7 /*反显指令 */
#define DISVR 0x24 /*调整V0电阻比率,这里折中*/
#define DISCURVUL 0x5D /*设定电流量值,这里折中 */
#define DISfrequency 0xE4 /*设定LCM工作频率,这里是最大值 */
#define DISPOWER 0x2F /*LCM电源控制项设定,这里全开 */
#define LCMLIMIT 132 /*本程序驱动13264LCM,所以这里为132.
/****************全局变量定义*******************/
Uchar col,row; /*列x,行(页)y,输出数据 */
bit Reverse; /*反显控制标志位,=1时反显 */
/*****************函数列表**********************/
void Lcminit(void); /*液晶模块初始化 */
void wtcom(void); /*busy判断、等待 */
void Lcmcls( void ); /*LCM全屏幕清零(填充0) */
void Loadxy (void); /* 写入地址函数 */
void Wrcmd(Uchar); /*命令输出 */
void Wrdata(Uchar); /*数据输出 */
void Wrcom(Uchar); /*写入数据函数*/
Uchar Rddata(void); /* 从液晶片上读数据 */
Uchar Rdcmd(void); /* 从液晶片上读出状态 */
Uchar Rdcom(void); /* 从LCM上读数据和状态的共享函数 */
void Putcdot(unsigned int Order); /* 向LCM写入全角字符 */
void Outcdata (unsigned long x); /*写入全角点陈函数 */
void Putedot(Uchar Order); /* 向LCM写入半角字符 */
unsigned int Outedata (unsigned int x); /*写入半角点陈函数 */
void Alldot(Uchar i,Uchar r); /* 判断当前行及列是否足够显示函数 */
void show_enter(Uchar i); /* 显示入口字符型数函数 */
void show_long(unsigned long i); /* 显示入口长整型数函数 */
void show_HEX(Uchar i); /* 将入口数(字符型)直接以HEX格式显示在LCM上 */
void myprintf(const char *format,...); /* 字符串显示输出 */
void M_address(Uchar high,Uchar mid,Uchar low); /* 对ROM/SRAM写地址函数 */
void Lcm_dot (Uchar i,bit j); /*LCM显示功能点函数*/
/******************数组列表*********************/
Uchar code Ezk[]; /*ASCII常规字符点阵码表 */
/****************************************/
/* 字符串显示输出 */
/* 本函数是可变函数,入口数为要显示的字符串 */
/****************************************/
void myprintf(const char *format,...)
{
va_list ap;//说明变量ap
Uchar c,d;
c=*format; //取第一个值。
va_start(ap,format);//ap被初始化为指向format第一个参数
while(c!='%')
{ // 利用指针取数。
if (c<0x80)
{
Alldot(8,2);
Putedot(c-0x20); /*ascii码表从0x20开始*/
}
else
{
++format; /*继续取下一个*/
d=*format; //取出位码
Alldot(16,2);
Putcdot(((c-0xA1)*94)+(d-0xA1)); /*全角字符码表从0xA1A1开始*/
}
++format;
c=*format;
}
va_end(ap);//清除变量x
}
/****************************************/
/* 将入口数直接以HEX格式显示在LCM上 */
/* 显示HEX入口数函数 */
/****************************************/
void show_HEX(Uchar i)
{
Uchar a,n=2;
while(n!=0) /*当n=0时退出函数*/
{
if(n!=1) {a=(i>>4);} /*显示高位*/
else {a=(i&0x0f);} /*第二次显示低位*/
if (a<10)
{
Putedot(a+(0x30-0x20)); /*0x30是字符0内码,0x20是自带字库的首地址*/
}
else
{ /*如果入口数小于10,则直接显示*/
a=a-10;
Putedot(a+(0x41-0x20)); /*0x41是字符A内码,0x20是自带字库的首地址*/
}
--n; /*n减1以显示下一轮及判断是否完成。*/
}
}
/****************************************/
/* 将入口数转换成十进制数字显示在LCM上 */
/* 显示入口长整型数函数 */
/****************************************/
void show_long(unsigned long i)
{
Uchar a;
unsigned long b;
if (i<10)
{ /*如果入口数小于10,则直接显示*/
Putedot(i+(0x30-0x20)); /*0x30是字符0内码,0x20是自带字库的首地址*/
return; /*返回*/
}
for (b=i;b>9;b=(b/10))
{
a=b%10; /*求b的每次除10后的最低个位的值*/
Putedot(a+(0x30-0x20)); /*显示数值*/
col=(col-16); /*列地址减16即两个半角字符的宽度,以便后面的高位数显示在后面*/
}
Putedot(b+(0x30-0x20)); /*显示最高位数值*/
}
/****************************************/
/* 将入口数转换成十进制数字显示在LCM上 */
/* 显示入口字符型数函数 */
/****************************************/
void show_enter(Uchar i)
{
Uchar a,b;
if (i<10)
{ /*如果入口数小于10,则直接显示*/
Putedot(i+(0x30-0x20)); /*0x30是字符0内码,0x20是自带字库的首地址*/
return; /*返回*/
}
for (b=i;b>9;b=(b/10))
{
a=b%10; /*求b的每次除10后的最低个位的值*/
Putedot(a+(0x30-0x20)); /*显示数值*/
col=(col-16); /*列地址减16即两个半角字符的宽度,以便后面的高位数显示在后面*/
}
Putedot(b+(0x30-0x20)); /*显示最高位数值*/
}
/****************************************/
/* 全角字符点阵码数据输出 */
/* 入口数Order是指要输出的汉字序号 */
/****************************************/
void Putcdot(unsigned int Order) /* 向LCM写入全角字符 */
{
/*这里开始输出字符 */
Uchar bakerx,bakery; /*定义2个局部变量*/
unsigned long x; /*偏移量,字符量少的可以定义为int或char*/
Alldot(16,2); /* 调用列、行判断函数 */
bakerx = col; /*暂存x,y坐标,备下半个字符使用 */
bakery = row;
x=Order; //这里必须先赋值给x再进行下面的乘法运算,不然会高位丢失。
x=x * 0x20; /*每个字符32字节 */
/*上半个字符输出,16列 */
Loadxy(); /*输入当前字符的首地址*/
Outcdata(x);
/*上半个字符输出结束 */
col = bakerx; /*列对齐 */
row = bakery+1; /*指向下半个字符行 */
Loadxy(); /*输入当前字符下半个字符的首地址*/
/*下半个字符输出,16列 */
x=(x+16);
Outcdata(x);
/*整个字符输出结束 */
col = (bakerx+16); /*列增加16,便于输入下个字符*/
row=bakery; /*恢复原来的row值*/
}
/****************************************/
/* 全角字符点阵码数据输出 */
/* 入口数x是要输出的点阵首地址量 */
/****************************************/
void Outcdata (unsigned long i) /*写入全角点陈函数 */
{ //字库存于SRAM中
Uchar high,mid,low;
low = i;
mid =(i>>8);
high=(i>>16);
/*写入SRAM中该字符的初始地址*/
CS_1=1;CS_2=1;CS_3=1; /*选中第三个74HC373*/
Data=high; /*改变高位地址*/
CS_1=0;CS_2=1;CS_3=1; /*选中第二个74HC373*/
Data=mid; /*改变中位地址*/
CS_1=1;CS_2=0;CS_3=1; /*选中第一个74HC373*/
Data=low; /*改变低位地址*/
WR = 1; //开始读出
for(i=0;i<16;i++)
{
CS_1=1;CS_2=1;CS_3=0; //片选SRAM的CE端
Data = 0xFF;
Wrdata(Data); //写输出一字节
if(low==0xff)
{
if(mid==0xff)
{
++high;
}
++mid;
}
++low;
M_address(high,mid,low); //写入地址
}
}
/****************************************/
/* 半角字符点阵码数据输出 */
/* 入口数Order是指要输出的半角字序号,比如输出"空格",那么Order=0 */
/****************************************/
void Putedot(Uchar Order)
{
/*这里开始输出字符 */
Uchar bakerx,bakery; /*定义3个局部变量*/
int x; /*偏移量,字符量少的可以定义为UCHAR*/
Alldot(8,2); /* 调用列、行判断函数 */
bakerx = col; /*暂存x,y坐标,备下半个字符使用 */
bakery = row;
x=Order * 0x10; /*半角字符,每个字符16字节 */
/*上半个字符输出,8列 */
Loadxy(); /*输入当前字符的首地址*/
x=Outedata(x);
/*上半个字符输出结束 */
col = bakerx; /*列对齐 */
row = bakery+1; /*指向下半个字符行 */
Loadxy(); /*输入当前字符下半个字符的首地址*/
/*下半个字符输出,8列 */
Outedata(x);
/*整个字符输出结束 */
col = (bakerx+8); /*列增加8,便于输入下个字符*/
row=bakery; /*恢复原来的row值*/
}
/****************************************/
/* 半角字符点阵码数据输出 */
/* 入口数x是要输出的点阵首地址量 */
/****************************************/
unsigned int Outedata (unsigned int x) /*写入全角点陈函数 */
{
Uchar i;
for(i=0;i<8;i++)
{
Wrdata(Ezk[x]); /*取点阵码,并写输出一字节 */
x++;
}
return x;
}
/*************************************************/
/* 对ROM/SRAM写地址函数 */
/* 入口数i是读或写的地址*/
/*************************************************/
void M_address(Uchar high,Uchar mid,Uchar low)
{
CS_1=1;CS_2=0;CS_3=1; /*选中第一个74HC373*/
Data=low; /*输出低位地址*/
CS_1=0;CS_2=1;CS_3=1; /*选中第二个74HC373*/
Data=mid; /*输出中位地址*/
CS_1=1;CS_2=1;CS_3=1; /*选中第三个74HC373*/
Data=high; /*输出高位地址*/
}
/****************************************/
/* 判断当前行及列是否足够显示函数 */
/* 入口数i是要输出的图形总列数,r是图形的总页数 */
/****************************************/
void Alldot(Uchar i,Uchar r)
{
if((LCMLIMIT-col)<i) /*判断当页所剩的列数是否小于i*/
{
col=0; /*如果所剩列数不够显示,则换行*/
row=(2+row);
}
if((8-row)<r) /*判断所剩的页数是否小于r*/
{
Lcmcls(); /*清屏处理*/
Loadxy(); /*输入当前字符首地址*/
}
}
/****************************************/
/*LCM显示功能点函数*/
/*入口数i是指定要显示的点的列数,j为1时表示点亮该点,为0时消隐*/
/****************************************/
void Lcm_dot (Uchar i,bit j)
{
Uchar bakerx,bakery; //定义两个变量,用于存放col及row的初值
bakerx=col;bakery=row; //备份地址
col=i; /*写入标志的列地址*/
row=8; /*功能点都在第8页,即第65行*/
Loadxy(); /* 写入地址 */
if (j)
{Wrdata(0xFF);} /*j=1,则点亮此点*/
else
{Wrdata(0);} /*j=0,关掉此点*/
col=bakerx;row=bakery; //还原地址
}
/****************************************/
/* 清屏,全屏幕清零 */
/****************************************/
void Lcmcls( void )
{
row=0,col=0;
for(row=0;row<8;row++) /*这里不清功能指示行*/
{
col=0; /*回归到初始值0*/
Loadxy(); /* 写入页首地址 */
for(;col<LCMLIMIT;col++)Wrdata(0); /* 写入数据0 */
}
row=0,col=0; /* 地址归位 */
}
/****************************************/
/* 写入地址函数 */
/****************************************/
void Loadxy(void)
{
Uchar cbyte;
cbyte=row;
cbyte=cbyte | SETY; /* 合成命令 */
Wrcmd(cbyte); /* 写入页地址 */
cbyte =((col>>4) | SETX2); /* 合成命令 */
Wrcmd(cbyte); /*写入列地址的高4位*/
cbyte =((col & 0x0F) | SETX1); /* 合成命令 */
Wrcmd(cbyte); /* 写入列地址的低4位 */
}
/****************************************/
/* 从液晶片上读数据,保留在全局变量中 */
/****************************************/
Uchar Rddata(void)
{
Alcm = 1; /*读数据操作 */
Rdcom(); /*调用读数据共享程序,假读一次*/
return(Rdcom()); /*调用读数据共享程序*/
}
/****************************************/
/* 读出LCD状态,保留在全局变量中 */
/****************************************/
Uchar Rdcmd(void)
{
Alcm = 0; /*读状态操作 */
return(Rdcom()); /*调用读数据共享程序*/
}
/****************************************/
/* 读LCD状态、数据共享函数 */
/****************************************/
Uchar Rdcom(void)
{
Uchar cbyte;
Data=0xFF; /* P0口全置1*/
CS_1 = 0; /*74HC138的A端置0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -