📄 lcd1602.c
字号:
#include <AT89X52.H>
#include <intrins.h>
//#define LCD1602VAR
#include "LCD1602.H"
#define NOP() _nop_();_nop_();_nop_();_nop_();_nop_();
#if CustomCharCount
unsigned char code CustomChar[CustomCharCount][8]=
{
{0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02},//年0
{0x00,0x0F,0x09,0x0F,0x09,0x0F,0x09,0x11},//月1
{0x00,0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F},//日2
{0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00},//一3
{0x00,0x00,0x0E,0x00,0x00,0x1F,0x00,0x00},//二4
{0x00,0x0F,0x00,0x0F,0x00,0x0F,0x00,0x00},//三5
{0x1F,0x13,0x1D,0x11,0x1D,0x13,0x1F,0x00},//四6
{0x00,0x1F,0x08,0x1F,0x09,0x0A,0x0A,0x1F} //五7
};
#endif
/*************************************************
* 函数说明:读取AC地址 *
* 输出参数: unsigned char AC: 表示AC地址
**************************************************/
#if LCD_EN_readBFAC
unsigned char LCDreadBFAC(void)
{
unsigned char redata;
#if LCD_DL<8
unsigned char temp;
#endif
LCD_RS=0;//选择指令寄存器
NOP();
LCD_RW=1;//读取指令寄存器
NOP();
#if LCD_DL>4
LCD_Data_Port=0xff;
LCD_EN=1;
NOP();
redata=LCD_Data_Port;
#else
LCD_Data_Port=LCD_Data_Port | 0xf0;
LCD_EN=1;
NOP();
redata=LCD_Data_Port;
LCD_EN=0;
redata=redata & 0xf0;
NOP();
LCD_EN=1;
NOP();
temp=LCD_Data_Port;
LCD_EN=0;
temp=temp>>4;
temp=temp & 0xf;
redata=redata | temp;
#endif
return (redata);
}
#endif
/*************************************************
* 函数说明:等等LCD16B20空闲 *
**************************************************/
#if LCD_EN_waitForReady
void LCDwaitForReady(void)
{
unsigned char i,re;
i=100;
do
{
re=LCDreadBFAC();
if((re & 0x80)==0)
break;
} while(i--!=0);
}
#endif
/********************************************************
* 函数说明:向LCD发送指令函数 *
* 输入: 需要发送的指令 *
********************************************************/
#if LCD_EN_SendCommand
void LCDSendCommand(unsigned char Command)
{
#if LCD_DL<8
unsigned char order;
#endif
LCDwaitForReady();
LCD_RS=0;//选择指令寄存器
NOP();
LCD_RW=0;//MCU向LCD写入命令数据
NOP();
#if LCD_DL>4
LCD_Data_Port=Command;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
#else
{
order=Command;
order=order & 0xf0;
LCD_Data_Port=LCD_Data_Port & 0xf;
LCD_Data_Port=LCD_Data_Port | order;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
order=Command;
order=order & 0xf;
order=order << 4;
LCD_Data_Port=LCD_Data_Port & 0xf;
LCD_Data_Port=LCD_Data_Port | order;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
}
#endif
}
#endif
/*********************************************************************
* 函数说明:LCD清屏,DD RAM的内容被清除,光标回到左上角原点,AC=0 *
**********************************************************************/
#if LCD_EN_clear
void LCDclear(void)
{
LCDSendCommand(0x1);
}
#endif
/*******************************************************************************
* 函数说明:LCD软复位,DD RAM的内容不变,但光标和光标所在的字符回到左上角原点 *
********************************************************************************/
#if LCD_EN_goHome
void LCDgoHome(void)
{
LCDSendCommand(0x2);
}
#endif
/********************************************************
* 函数说明:输入方式设置,设置光标、画面移动方式 *
* 输入参数: bit I_D:表示读写之后AC情况,I_D=1 *
* 表示AC+1;I_D=0表示AC-1; *
* bit S: 表示画面是否移动,S=1表示 *
* 画面平移;S=0表示画面不动 *
********************************************************/
/*
当S=1且数据写入DD RAM中时候,显示将全部左边移动(I_D=1),或者全部右边移动(I_D=0),即光标不移动
当S=0,画面不动,光标移动(左边移动:I_D=0,右边移动:I_D=1)
*/
#if LCD_EN_setInputModel
void LCDsetInputModel(bit I_D,bit S)
{
unsigned char order;
order=0x4;
if(I_D)
order=order+0x2;
if(S)
order=order+0x1;
LCDSendCommand(order);
}
#endif
/***************************************************************
* 函数说明:显示模式设置,设置画面、光标以及光标是否闪烁开关 *
* 输入参数: bit D: 表示画面是否显示 *
* bit C: 表示光标是否显示 *
* bit B: 表示光标是否闪烁 *
****************************************************************/
#if LCD_EN_setDisplayModel
void LCDsetDisplayModel(bit D,bit C,bit B)
{
unsigned char order;
order=0x8;
if(D)
order=order+0x4;
if(C)
order=order+0x2;
if(B)
order=order+0x1;
LCDSendCommand(order);
}
#endif
//画面和光标一起右边移动n个字符位置
#if LCD_EN_shiftRight
void LCDshiftRight(unsigned char n) //shift by n characters Right
{
unsigned char i;
for(i=0;i<n;i++)
LCDSendCommand(0x1e);
}
#endif
//-----------------------------------------------------------------
//画面和光标一起左边移动n个字符位置
#if LCD_EN_shiftLeft
void LCDshiftLeft(unsigned char n) //shift by n characters Left
{
unsigned char i;
for(i=0;i<n;i++)
LCDSendCommand(0x18);
}
#endif
//-----------------------------------------------------------------
//光标往右边移动n个字符位置
#if LCD_EN_cursorRight
void LCDcursorRight(unsigned char n) //shif cursor right by n
{
unsigned char i;
for(i=0;i<n;i++)
LCDSendCommand(0x14);
}
#endif
//------------------------------------------------------------------
//光标往左边移动n个字符位置
#if LCD_EN_cursorLeft
void LCDcursorLeft(unsigned char n) //Shift cursor left by n
{
unsigned char i;
for(i=0;i<n;i++)
LCDSendCommand(0x10);
}
#endif
//------------------------------------------------------------------
/*******************************************************************
* 函数说明:设置数据接口位数是4为还是8位,显示行数是一行还是二行, *
字体格式是5*7还是5*10 *
* 输入参数: bit DL: 表示数据接口长度,DL=1,表示8位;DL=0,表示4为 *
* bit N: 表示显示行数,N=1,表示两行;N=0,表示一行 *
* bit F: 表示字体格式,F=1,表示5*10;F=0,表示5*7 *
********************************************************************/
#if LCD_EN_setFunction
void LCDsetFunction(bit DL,bit N,bit F)
{
unsigned char order;
order=0x20;
if(DL)
order=order+0x10;
if(N)
order=order+0x8;
if(F)
order=order+0x4;
LCDSendCommand(order);
}
#endif
/**************************************************
* 函数说明:设置CG RAM地址 *
* 输入参数: unsigned char CG: 表示CG RAM地址 *
***************************************************/
#if CustomCharCount
void LCDsetCGRAMAddress(unsigned char CG)
{
unsigned char order;
order=0x40;
order=order+CG;
LCDSendCommand(order);
}
#endif
/*************************************************
* 函数说明:MCU向LCD16B20写入数据 *
* 输入参数: unsigned char DATA *
**************************************************/
#if LCD_EN_writeData
void LCDwriteData(unsigned char DATA)
{
#if LCD_DL<8
unsigned char d;
#endif
LCDwaitForReady();
LCD_RS=1;//选择数据寄存器
NOP();
LCD_RW=0;//MCU向LCD写入
NOP();
#if LCD_DL>4
LCD_Data_Port=DATA;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
#else
d=DATA & 0xf0;
LCD_Data_Port=LCD_Data_Port & 0xf;
LCD_Data_Port=LCD_Data_Port | d;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
d=DATA & 0xf;
d=d<<4;
d=d & 0xf0;
LCD_Data_Port=LCD_Data_Port & 0xf;
LCD_Data_Port=LCD_Data_Port | d;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
#endif
}
#endif
/*************************************************
* 函数说明:MCU向LCD16B20读取数据 *
* 输出参数: unsigned char DATA *
**************************************************/
#if LCD_EN_readData
unsigned char LCDreadData(void)
{
unsigned char redata;
#if LCD_DL<8
unsigned char temp;
#endif
LCDwaitForReady();
LCD_RS=1;//选择数据寄存器
NOP();
LCD_RW=1;//读取数据寄存器
NOP();
#if LCD_DL>4
LCD_Data_Port=0xff;
LCD_EN=1;
NOP();
redata=LCD_Data_Port;
LCD_EN=0;
#else
LCD_Data_Port=LCD_Data_Port | 0xf0;
LCD_EN=1;
NOP();
redata=LCD_Data_Port;
LCD_EN=0;
redata=redata & 0xf0;
NOP();
LCD_EN=1;
NOP();
temp=LCD_Data_Port;
LCD_EN=0;
temp=temp >>4;
temp=temp & 0xf;
redata=redata | temp;
#endif
return (redata);
}
#endif
/**************************************
* 函数说明:背光灯控制 *
* 输入参数: bit onoff *
***************************************/
#if LCD_EN_light
void LCDlight(bit onoff)
{
LCD_LED=!onoff;
}
#endif
/***********************************************
* 函数说明:设置显示坐标函数 *
************************************************/
//控制器内部带有80个*8位RAM(即80字节RAM),对于关系:
//第一行:00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10......27(40个)
//第二行:40,41,42,43,44,45,46,47,48,49,4A,4B,4C,4D,4E,4F,50......67(40个)
//第一行首个地址为:0x80+00;
//第二行首个地址为:0x80+0x0x40+00,即:0xc0+00
#if LCD_EN_setXY
void LCDsetXY(unsigned char X,unsigned char Y)
{
unsigned char Address;
if(X>39)
X=39;
if (Y == 0)
{
Address = 0x80 + X;
}
else
{
Address = 0xc0 + X;
}
LCDSendCommand(Address);
}
#endif
/********************************************************
* 函数说明:LCD字符串显示函数 *
********************************************************/
#if LCD_EN_displayStr
void LCDdisplayStr(char *String)
{
while(*String)
{
LCDwriteData(*String);
String++;
}
}
#endif
/********************************************************
* 函数说明:指定XY坐标显示一个字符 *
* 输入参数:unsigned char X: X坐标 *
* unsigned cahr Y: Y坐标 *
* char ch: 被显示的字符 *
********************************************************/
#if LCD_EN_putChar
void LCDputChar(unsigned char X,unsigned char Y,char ch)
{
LCDsetXY(X,Y);
LCDwriteData((unsigned char)ch);
}
#endif
/************************************************************
* 从指定位置开始显示字符串,如果是从第一行开始显示的,但是
* 无法显示完,自动从第二行开始显示,如果还没有显示完,就将余下的
*抛弃;如果是从第二行开始显示的,但是无法显示完,
*就抛弃没有显示的内容.
**************************************************************/
#if LCD_EN_printf
void LCDprintf(unsigned char X,unsigned char Y,char *String)
{
if(Y==0)
{
if(X<16)
{
LCDsetXY(X,Y);
for(;X<16 && *String!='\0';X++)
{
LCDwriteData((unsigned char)*String);
String++;
}
if(*String!='\0')
{
X=0;
Y=1;
}
}
}
if(Y==1)
{
LCDsetXY(X,Y);
for(;X<16 && *String!='\0';X++)
{
LCDwriteData((unsigned char)*String);
String++;
}
}
}
#endif
/*************************************************
* 函数说明:清除指定的一行显示,然后光标回到行首 *
* 输入参数:bit line: 如果line=0,表示是第一行 *
* 如果line=1,表示是第二行 *
**************************************************/
#if LCD_EN_clearLine
void LCDclearLine(bit line)
{
unsigned char i;
if(line) //第二行
LCDsetXY(0,1);
else //第一行
LCDsetXY(0,0);
for(i=0;i<16;i++)
LCDwriteData(' '); //向LCD写入16个空格
if(line) //回到第二行的第一个位置
LCDsetXY(0,1);
else //回到第一行的第一个位置
LCDsetXY(0,0);
}
#endif
//--------------------------------------------------
//不需要指定位置显示字符
#if LCD_EN_displayChar
void LCDdisplayChar(unsigned char ch)
{
LCDwriteData(ch);
}
#endif
//--------------------------------------------------
//延时nms函数
#if LCD_EN_delaynms
void delaynms(unsigned char n)
{
unsigned char i,j,k;
i=1;
#if Fosc>6
i=2;
#endif
for(;i>0;i--)
{
for(j=0;j<n;j++)
{
for(k=0;k<166;k++);
for(k=0;k<166;k++);
}
}
}
#endif
//将自定义字符写进CGRAM中
#if CustomCharCount
void LCDloadUserChar(unsigned char code * p)
{
unsigned char i,j;
for(i=0;i<CustomCharCount;i++)
{
for(j=0;j<8;j++)
{
LCDsetCGRAMAddress(8*i+j);
LCDwriteData(*p);
p++;
}
}
}
#endif
/********************************************
* 函数说明:LCD复位 *
*********************************************/
/*
1.延时15ms
2.写入指令:0x38(不检测忙信号)
3.延时5ms
4.写入指令:0x38(不检测忙信号)
5.延时5ms
6.写入指令:0x38(不检测忙信号)
以后读写都要检测忙信号
7.如果定义8位数据接口设置8位数据线,两行显示,字体格式:5*8
(7).如果定义是4为数据接口设置8位数据线,两行显示,字体格式:5*8
8.设置显示画面、光标、光标是否闪烁开关
9.设置输入模式,默认增量方式,画面不动,光标移动
10.清屏
*/
#if LCD_EN_reset
void LCDreset(void)
{
delaynms(15); //延时15ms
LCD_EN=0;
LCD_RS=0;//选择指令寄存器
NOP();
LCD_RW=0;//MCU向LCD写入命令数据
NOP();
#if LCD_DL>4
LCD_Data_Port=0x38;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCDsetFunction(1,1,1); //设置8位数据线,两行显示,字体格式:5*8
#else
LCD_Data_Port=LCD_Data_Port & 0x3f;
LCD_Data_Port=LCD_Data_Port | 0x30;
NOP();
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCD_EN=1;
NOP();
LCD_EN=0;
delaynms(5);
LCDsetFunction(0,1,1); //设置4位数据线,两行显示,字体格式:5*7
#endif
LCDsetDisplayModel(1,0,0);//设置显示画面、光标、光标是否闪烁开
LCDsetInputModel(1,0);//设置输入模式,默认增量方式,画面不动,光标向右边移动
LCDclear();
#if CustomCharCount
LCDloadUserChar(CustomChar[0]);
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -