? ? ?一? 模组简介?? ?常用的LCD模组有LCD1602、LCD12864、LCD2004等,下面讲解这三个模组驱动程序编写。
? ? ? ? A.? CD1602模组? ? LCD1602是可显示2行每行16个字符(5*7点阵)的显示模组,其尺寸与引脚如下:
? ? ? ? LCD1602共有16只引脚,4~14号引脚与数据读写有关。也就是说,按照一定的指令格式改变这11个引脚的电平高低即可实现相关数据读写操作。
? ? ? ? LCD1602指令???LCD1602共有11条指令,如下:
指令1:清除显示,指令码01H,光标复位到地址00H位置。
指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置? ? ? I/D:光标移动方向,高电平右移,低电平左移
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 则?无效。
指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?C:控制光标的开与关,高电平表示有光标,低电平表示无光标? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令6:功能设置命令? ? ?DL:高电平时为8位总线,低电平时为4位总线
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? N:低电平时为单行显示,高电平时双行显示
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM(数据存储)地址设置。
指令9:读忙信号和光标地址? ? ?BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如果为低电平表示不忙。
指令10:写数据。
指令11:读数据。
? ? ? ? ?LCD1602操作时序
? ? ? ? ?1. 读操作时序
? ? ? ? ? 2. 写操作时序
LCD1602的RAM地址映射
? ? ? ?液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电 平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在 哪里显示字符。1602 内 部 显 示 地 址如下:
? ? ? ?有内部字库(内部字符发生器)的LCD模组,将字符的ASCII码写入显示字符地址,即可显示该字符。
? ? ? ??B.? LCD 2004? 模组? LCD2004 是可显示4行,每行20个字符(5*7点阵)的显示模组? 其尺寸与Pin脚如下:
? ? ? ??LCD 2004 指令表? ?其指令表如下:
? ? ? ??LCD2004 操作时序? ?
? ? ? ? 读操作时序
? ? ? 写操作时序
? ?LCD2004的RAM地址映射? ?其地址映射如下表:
? ? ? ? C.? LCD12864 模组? ?LCD12864 模组 是128x64点阵屏,可显示字符(含汉字),也可显示点阵图形。有的带字库,有的可能不带,接口也会存在差异,有的有20Pin引脚,有的可能只有电源Pin+串口通信Pin。不同厂家的产品会有所不同,购买时需向卖家了解清楚。既支持并口又支持串口的模组,接口为20Pin,如下图:
*注释1:如在实际应用中仅使用并口通讯模式,可将PSB接固定高电平,也可以将模块上的J8和? ? ? ? ? ? ? ? ? “VCC”用焊锡短接。如果使用串口通讯模式,可将PSB接固定低电平,也可以将模块上的? ? ? ? ? ? ? ? ?J8和“GND”用焊锡短接。
*注释2:模块内部接有上电复位电路,因此在不需要经常复位的场合可将该端悬空。???
*注释3:如背光和模块共用一个电源,可以将模块上的JA、JK用焊锡短接。
? ? ? ? ?LCD12864 模组指令
模块控制芯片提供两套控制命令,基本指令和扩充指令如下:
指令表1:(RE=0:基本指令)
指 | ????????????????? 指 令 码 | 功 能 | 令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | | 清除 显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 将DDRAM填满"20H",并且设定DDRAM的地址计数器(AC)到"00H" | 地址 归位 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | X | 设定DDRAM的地址计数器(AC)到"00H",并且将游标移到开头原点位置;这个指令不改变DDRAM 的内容 | 显示状态开/关 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | D=1: 整体显示 ON C=1: 游标ON???? B=1:游标位置反白允许 | 进入点 设定 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | 指定在数据的读取与写入时,设定游标的移动方向及指定显示的移位 | 游标或显示移位控制 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | X | X | 设定游标的移动与显示的移位控制位;这个指令不改变DDRAM 的内容 | ?功能 ?设定 | 0 | 0 | 0 | 0 | 1 | DL | X | RE | X | X | DL=0/1:4/8位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 | ?设定CGRAM ?地址 | 0 | 0 | 0 | 1 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | 设定CGRAM 地址 | ?设定DDRAM ?地址 | 0 | 0 | 1 | 0 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | 设定DDRAM 地址(显示位址) 第一行:80H-87H 第二行:90H-97H | 读取忙标志和地址 | 0 | 1 | BF | AC6 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | 读取忙标志(BF)可以确认内部动作是否完成,同时可以读出地址计数器(AC)的值 | 写数据到RAM | 1 | 0 | 数据 | 将数据D7——D0写入到内部的RAM (DDRAM/CGRAM/IRAM/GRAM) | 读出RAM的值 | 1 | 1 | 数据 | 从内部RAM读取数据D7——D0 (DDRAM/CGRAM/IRAM/GRAM) |
指令表2:(RE=1:扩充指令)
指 | ????????????????? 指 令 码 | 功 能 | 令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | | ? 待命 模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 进入待命模式,执行其他指令都棵终止 待命模式 | 卷动地址开关开启 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | SR | SR=1:允许输入垂直卷动地址 SR=0:允许输入IRAM和CGRAM地址 | ? 反白 ? 选择 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | R1 | R0 | 选择2行中的任一行作反白显示,并可决定反白与否。初始值R1R0=00,第一次设定为反白显示,再次设定变回正常 | ? 睡眠 ? 模式 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | SL | X | X | SL=0:进入睡眠模式 SL=1:脱离睡眠模式 | ? 扩充 ? 功能 ? 设定 | 0 | 0 | 0 | 0 | 1 | CL | X | RE | G | 0 | CL=0/1:4/8位数据 RE=1: 扩充指令操作 RE=0: 基本指令操作 G=1/0:绘图开关 | ?设定绘图RAM ?地址 | 0 | 0 | 1 | 0 AC6 | 0 AC5 | 0 AC4 | AC3 AC3 | AC2 AC2 | AC1 AC1 | AC0 AC0 | 设定绘图RAM 先设定垂直(列)地址AC6AC5…AC0 再设定水平(行)地址AC3AC2AC1AC0 将以上16位地址连续写入即可 |
备注;当IC1在接受指令前,微处理器必须先确认其内部处于非忙碌状态,即读取BF标志时,BF需为零,方可接受新的指令;如果在送出一个指令前并不检查BF标志,那么在前一个指令和这个指令中间必须延长一段较长的时间,即是等待前一个指令确实执行完成。
?????????LCD12864 操作时序
? ? ? ? ?读时序(八位并口)
? ? ? ? 写时序(8位并口)
? ? ? ??LCD12864?的RAM地址映射(以FYD12864-0402B为例)?FYD12864-0402B每屏可显示4行8列共32个16×16点阵的汉字,每个显示RAM可显示1个中文字符或2个16×8点阵全高ASCII码字符,即每屏最多可实现32个中文字符或64个ASCII码字符的显示。FYD12864-0402B内部提供128×2字节的字符显示RAM缓冲区(DDRAM)。字符显示是通过将字符显示编码写入该字符显示RAM实现的。根据写入内容的不同,可分别在液晶屏上显示CGROM(中文字库)、HCGROM(ASCII码字库)及CGRAM(自定义字形)的内容。三种不同字符/字型的选择编码范围为:0000~0006H(其代码分别是0000、0002、0004、0006共4个)显示自定义字型,02H~7FH显示半宽ASCII码字符,A1A0H~F7FFH显示8192种GB2312中文字库字形。字符显示RAM在液晶模块中的地址80H~9FH。字符显示的RAM的地址与32个字符显示区域有着一一对应的关系,其对应关系如下表所示。
80H | 81H | 82H | 83H | 84H | 85H | 86H | 87H | 90H | 91H | 92H | 93H | 94H | 95H | 96H | 97H | 88H | 89H | 8AH | 8BH | 8CH | 8DH | 8EH | 8FH | 98H | 99H | 9AH | 9BH | 9CH | 9DH | 9EH | 9FH |
图形显示?? 先设垂直地址再设水平地址(连续写入两个字节的资料来完成垂直与水平的坐标地址)
垂直地址范围 AC5...AC0
水平地址范围 AC3…AC0
绘图RAM 的地址计数器(AC)只会对水平地址(X 轴)自动加一,当水平地址=0FH 时会重新设为00H 但并不会对垂直地址做进位自动加一,故当连续写入多笔资料时,程序需自行判断垂直地址是否需重新设定。GDRAM的坐标地址与资料排列顺序如下图:
? ? ? ? 二? 程序编写
? ? ? ?1. 新建库文件? 打开前面教程中创建的C51 Template 文件夹中Proj文件夹下的C51 Template.uvproj。创建两个新文件,分别以文件名lcd.h,lcd.c存入C51 Template文件夹下Library文件夹中。
? ? ? ?2. 完成头文件? ?在写头文件前先做一下说明,LCD1602与LCD2004可以用4线并口,也可使用8线并口,这一点可以从功能设置项看出。如下:
指令6:功能设置命令 DL:高电平时为8位总线,低电平时为4位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。DL为D5位,因此4位总线必须接高4位,否则没法将LCD配置为4line总线模式。LCD12864则有两种通信模式并口与串口。库函数设计时考虑到了以上因素。头文件如下:
/*lcd.h
Designed by Bill Liu
Version 0.0
Modified last by Bill Liu on 11/11/2021
*/
#ifndef __LCD_H_
#define __LCD_H_
#include "mtype.h"
#include "delay.h"
/************************************************************
//LCD_EA, LCD_RW, LCD_RS, LCD_DATAPINS, LCD_CS, LCD_SID, LCD_CLK,defined in myport.h
sbit LCD_RS = P4^1;
sbit LCD_RW = P4^2;
sbit LCD_EA = P4^4;
sbit LCD_CS = P4^1;
sbit LCD_SID = P4^2;
sbit LCD_CLK = P4^4;
sbit LCD12864_PSB = P3^7; //LCD12864_PSB = 1; //select parallel port input/output
sbit LCD12864_RST = P3^6; //LCD12864_RST = 1; //reset
//you may define your own needs
**************************************************************/
#include "myport.h"
extern FSYSCLOCK FSCLK; //may be define in main.h, such as "const FSYSCLOCK FSCLK = F30MHz;"
typedef enum
{
LCD1602 = 0,
LCD2004,
LCD12864
}LCDTYPE;
/***************************************************
Function: LCD_WriteCom(ui8 com, BOOL cby4line);
Return value: void
Discription: write command to LCD1602,LCD2004 & LCD12864, cby4line must be 0 for LCD12864
Example:
LCD_WriteCom(0x01, 0); //write clear command by 8pin data line
****************************************************/
void LCD_WriteCom(ui8 com, BOOL cby4line);//4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_Init(BOOL cby4line);
Return value: void
Discription: init LCD1602 & LCD2004
Example:
LCD_Init(FALSE);//communitcate by 8pin data line
LCD_Init(TRUE); //communitcate by 8pin data line
****************************************************/
void LCD_Init(BOOL cby4line);//4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_WriteData(BYTE mdata, BOOL cby4line);
Return value: void
Discription: write data to LCD1602,LCD2004 & LCD12864, cby4line must be 0 for LCD12864
Example:
LCD_WriteData('a', 0);
****************************************************/
void LCD_WriteData(BYTE mdata, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_ClearScreen(BOOL cby4line);
Return value: void
Discription: Clear scren
Example:
LCD_ClearScreen(BOOL cby4line);
****************************************************/
void LCD_ClearScreen(BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CurRet(BOOL cby4line);
Return value: void
Discription: Cursor return origin
Example:
LCD_CurRet(BOOL cby4line);
****************************************************/
void LCD_CurRet(BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CurOn(BOOL mable, BOOL cby4line);
Return value: void
Discription: Cursor On/Off
Example:
LCD_CurOn(0,1);
****************************************************/
void LCD_CurOn(BOOL mable, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CurFlicker(BOOL mable, BOOL cby4line);
Return value: void
Discription: Cursor flicker enble/disable
Example:
LCD_CurFlicker(0,1);
****************************************************/
void LCD_CurFlicker(BOOL mable, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CurShift(BOOL dirR, BOOL cby4line);
Return value: void
Discription: Cursor shift to R/L
Example:
LCD_CurShift(0,1); //cursor shift to L
****************************************************/
void LCD_CurShift(BOOL dirR, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_TextShift(BOOL dirR, BOOL cby4line);
Return value: void
Discription: Text shift to R/L
Example:
LCD_TextShift(0,1); //cursor shift to L
****************************************************/
void LCD_TextShift(BOOL dirR, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_DispOn(BOOL mable,BOOL cby4line);
Return value: void
Discription: LCD diplay enable/disable
Example:
LCD_DispOn(1,0);
****************************************************/
void LCD_DispOn(BOOL mable,BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CheckBusy();
Return value: BOOL
Discription: set position x:column no, y: row no
Example:
LCD_CheckBusy();
****************************************************/
BOOL LCD_CheckBusy(); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_SetPos(ui8 x, ui8 y, LCDTYPE mlcd,BOOL cby4line);
Return value: void
Discription: set position x:column no, y: row no
Example:
LCD_SetPos(0,0,LCD1602,0);
****************************************************/
void LCD_SetPos(ui8 x, ui8 y, LCDTYPE mlcd,BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD_CheckBusy(BOOL cby4line);
Return value: BOOL
Discription: check whether Lcd1602 or lcd2004 is busy
Example:
LCD_CheckBusy(0);
****************************************************/
BOOL LCD_CheckBusy(BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD1602_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line);
Return value: void
Discription: LCD1602 display specified string start from point (x, y)
x must be <= 15, y must be <=1, x: character position, y: line position
Example:
LCD1602_DisplayString(0,0,'abcd', 0);
****************************************************/
void LCD1602_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD1602_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line);
Return value: void
Discription: LCD1602 display specified string's n character start from point (x, y)
x must be <= 19, y must be <= 3, x: character position, y: line position
Example:
LCD1602_DisplayString(3,0,2,'abcd', 0); //display "ab",at 4th 5th pos of row 1
****************************************************/
void LCD1602_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD2004_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line);
Return value: void
Discription: LCD2004 display specified string start from point (x, y)
x must be <= 19, y must be <= 3, x: character position, y: line position
Example:
LCD2004_DisplayString(0,0,'abcd', 0);
****************************************************/
void LCD2004_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD2004_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line);
Return value: void
Discription: LCD2004 display specified string's n character start from point (x, y)
x must be <= 19, y must be <= 3, x: character position, y: line position
Example:
LCD2004_DisplayString(3,0,2,'abcd', 0); //display "ab",at 4th 5th pos of row 1
****************************************************/
void LCD2004_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line); //4lines connect to high 4 bits(D7~D4)
/***************************************************
Function: LCD12864_WriteCom(ui8 com, BOOL bSerPort);
Return value: void
Discription: write command to LCD12864
Example:
LCD12864_WriteCom(0x01, 0); //write clear command by 8pin data line
****************************************************/
void LCD12864_WriteCom(ui8 com, BOOL bSerPort);
/***************************************************
Function: LCD12864_SWrCom(ui8 com);
Return value: void
Discription: write command to LCD12864 by serial port
Example:
LCD12864_SWrCom(0x01); //write clear command
****************************************************/
void LCD12864_SWrCom(ui8 com);
/***************************************************
Function: LCD12864_Init(BOOL bSerPort);
Return value: void
Discription: init LCD12864
Example:
LCD12864_Init(0); //communicate by 8pin data line
****************************************************/
void LCD12864_Init(BOOL bSerPort);
/***************************************************
Function: LCD12864_SWrData(BYTE mdata);
Return value: void
Discription: write data to LCD12864 by serial port
Example:
LCD12864_SWrData('a');
****************************************************/
void LCD12864_SWrData(BYTE mdata);
/***************************************************
Function: LCD12864_WriteData(BYTE mdata, BOOL bSerPort);
Return value: void
Discription: write data to LCD12864
Example:
LCD12864_WriteData('a', 0);
****************************************************/
void LCD12864_WriteData(BYTE mdata, BOOL bSerPort);
/***************************************************
Function: LCD12864_RdData(BOOL bSerPort);
Return value: BYTE
Discription: read data from LCD12864
Example:
BYTE mRead;
mRead = LCD12864_RdData(0);
****************************************************/
BYTE LCD12864_RdData(BOOL bSerPort);
/***************************************************
Function: LCD12864_ClearScreen(BOOL bSerPort, BOOL bGraph);
Return value: void
Discription: Clear scren
Example:
LCD12864_ClearScreen(0,0);
****************************************************/
void LCD12864_ClearScreen(BOOL bSerPort, BOOL bGraph);
/***************************************************
Function: LCD12864_SetPos(ui8 x, ui8 y, BOOL bSerPort);
Return value: void
Discription: set position( x:column no, y: row no), x <= 15,
y <= 3
Example:
LCD12864_SetPos(0,1,0);
****************************************************/
void LCD12864_SetPos(ui8 x, ui8 y, BOOL bSerPort);
/***************************************************
Function: LCD12864_DrowPaint(ui8 x, ui8 y, BOOL bSerPort);
Return value: void
Discription: draw point(x,y)
Example:
LCD12864_DrawPoint(5, 20, 0);
****************************************************/
void LCD12864_DrawPoint(ui8 x, ui8 y, BOOL bSerPort);
/***************************************************
Function: LCD12864_DrawGraph(ui8 graph[], BOOL bSerPort);
Return value: void
Discription: draw point(x,y)
Example:
LCD12864_DrawGraph(graph, 1);
****************************************************/
void LCD12864_DrawGraph(ui8 graph[], BOOL bSerPort);
/***************************************************
Function: LCD12864_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL bSerPort);
Return value: void
Discription: LCD12864 display specified string start from point (x, y),
x: character position, y: line position.
Example:
LCD12864_DisplayString(0,0,'abcd', 0);
****************************************************/
void LCD12864_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL bSerPort);
/***************************************************
Function: LCD12864_DisplaynC(ui8 x, ui8 y, ui8 n, ui8* mstr, BOOL bSerPort);
Return value: void
Discription: LCD12864 display specified string's n character start from point (x, y)
x: character position, y: line position.
Example:
LCD12864_DisplayString(0,0,2,'abcd', 0);
****************************************************/
void LCD12864_DisplaynC(ui8 x, ui8 y, ui8 n, ui8* mstr, BOOL bSerPort);
#endif
? ? ? 3. 函数实现? 在lcd.c中实现后,如下:
/*delay.c
Designed by Bill Liu
Version 0.0
Modified last by Bill Liu on 11/11/2021
*/
#include "lcd.h"
extern FSYSCLOCK FSCLK;
//****************************************************/
void LCD_WriteCom(ui8 com, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
LCD_EA = 0;
LCD_RS = 0; //write commmand
LCD_RW = 0;
LCD_DATAPINS = com;
//Delayxms(1,8);
Delayxms(1,FSCLK);
LCD_EA = 1;
//Delayxms(5,8);
Delayxms(5,FSCLK);
LCD_EA = 0;
if(cby4line) //4lines data_bus, need to write left low 4bits
{
LCD_DATAPINS = com << 4;
Delayxms(1,FSCLK);
LCD_EA = 1;
Delayxms(5,FSCLK);
LCD_EA = 0;
}
}
//End of LCD_WriteCom(ui8 com, BOOL cby4line)
//****************************************************/
void LCD_Init(BOOL cby4line)
{
if(cby4line)
{
LCD_WriteCom(0x32, cby4line); //set 4lines data_bus
LCD_WriteCom(0x28, cby4line); //set 4lines data_bus
}
else
LCD_WriteCom(0x38, cby4line); //set 8lines data_bus, 2 row character, chaarcter5x7
LCD_WriteCom(0x0C, cby4line); //lcd display enable, cursor disable
LCD_WriteCom(0x06, cby4line); //set input mode, write a character x pos+1
LCD_WriteCom(0x01, cby4line); //clear screen
LCD_WriteCom(0x80, cby4line); //set start point (0,0)
}
//End of LCD_Init(BOOL cby4line)
//****************************************************/
void LCD_WriteData(BYTE mdata, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
LCD_EA = 0;
LCD_RS = 1; //write_data
LCD_RW = 0;
LCD_DATAPINS = mdata;
Delayxms(1,FSCLK);
LCD_EA = 1;
Delayxms(5,FSCLK);
LCD_EA = 0;
if(cby4line) //write left low 4bits
{
LCD_DATAPINS = mdata << 4;
Delayxms(1,FSCLK);
LCD_EA = 1;
Delayxms(5,FSCLK);
LCD_EA = 0;
}
}
//End of LCD_WriteData(BYTE mdata, BOOL cby4line)
//****************************************************/
void LCD_ClearScreen(BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
LCD_WriteCom(0x01, cby4line);
}
//End of LCD_ClearScreen(BOOL cby4line)
//****************************************************/
void LCD_CurRet(BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
LCD_WriteCom(0x01, cby4line);
}
//End of LCD_CurRet(BOOL cby4line)
//****************************************************/
void LCD_CurOn(BOOL mable, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
if(mable)
LCD_WriteCom(0x0E, cby4line);
else
LCD_WriteCom(0x0C, cby4line); //cursor off
}
//End of LCD_CurOn(BOOL mable, BOOL cby4line)
//****************************************************/
void LCD_CurFlicker(BOOL mable, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
if(mable) // cursor flicker enable
LCD_WriteCom(0x0F, cby4line);
else
LCD_WriteCom(0x0C, cby4line); // display enable,cursor disable
}
//End of LCD_CurFlicker(BOOL mable, BOOL cby4line)
//****************************************************/
void LCD_CurShift(BOOL dirR, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
if(dirR) //cursor shift to right
LCD_WriteCom(0x14, cby4line);
else //cursor shift to left
LCD_WriteCom(0x10, cby4line);
}
//End of LCD_CurShift(BOOL dirR, BOOL cby4line)
//****************************************************/
void LCD_TextShift(BOOL dirR, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
if(dirR) //text shift to right
LCD_WriteCom(0x1C, cby4line);
else //text shift to left
LCD_WriteCom(0x18, cby4line);
}
//End of LCD_TextShift(BOOL dirR, BOOL cby4line)
//****************************************************/
void LCD_DispOn(BOOL mable,BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
if(mable) //display enable
LCD_WriteCom(0x0C, cby4line);
else //display disable
LCD_WriteCom(0x08, cby4line);
}
//End of LCD_DispOn(BOOL mable,BOOL cby4line)
//****************************************************/
BOOL LCD_CheckBusy() //4lines connect to high 4 bits(D7~D4)
{
ui8 tem;
LCD_RS = 0; //write_data
LCD_RW = 1;
LCD_EA = 1;
Delayxms(1,FSCLK);
tem = LCD_DATAPINS;
LCD_EA = 0;
return (tem & 0x80);
}
//End of LCD_CheckBusy(BOOL cby4line)
//****************************************************/
void LCD_SetPos(ui8 x, ui8 y, LCDTYPE mlcd,BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
switch(mlcd)
{
case LCD1602:
if(x <= 16)
{
switch(y)
{
case 0:
LCD_WriteCom((0x80+x), cby4line);
break;
case 1:
LCD_WriteCom((0xC0+x), cby4line);
break;
}
}
break;
case LCD2004:
if(x < 19)
{
switch(y)
{
case 0: //0 row
LCD_WriteCom((0x80+x), cby4line);
break;
case 1: //1 row
LCD_WriteCom((0xC0+x), cby4line);
break;
case 2: //2 row
LCD_WriteCom((0x94+x), cby4line);
break;
case 3: //3 row
LCD_WriteCom((0x94+x), cby4line);
break;
}
}
break;
case LCD12864:
break;
}
}
//End of LCD_DispOn(BOOL mable,BOOL cby4line)
//****************************************************/
void LCD1602_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line)
{
ui8 i = 0;
LCD_SetPos(x, y, LCD1602,cby4line);
while(mstr[i] != 0)
{
LCD_WriteData(mstr[i], cby4line);
i++;
}
}
//End of LCD1602_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line)
//****************************************************/
void LCD1602_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
ui8 i = 0;
LCD_SetPos(x, y, LCD1602,cby4line);
for(i = 0; i < n; i++)
{
LCD_WriteData(mstr[i], cby4line);
}
}
//****************************************************/
void LCD2004_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line)
{
ui8 i = 0;
LCD_SetPos(x, y, LCD2004,cby4line);
while(mstr[i] != 0)
{
LCD_WriteData(mstr[i], cby4line);
i++;
}
}
//End of LCD2004_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL cby4line)
//****************************************************/
void LCD2004_DisplaynC(ui8 x, ui8 y, ui8 n,ui8* mstr, BOOL cby4line) //4lines connect to high 4 bits(D7~D4)
{
ui8 i = 0;
LCD_SetPos(x, y, LCD2004,cby4line);
for(i = 0; i < n; i++)
{
LCD_WriteData(mstr[i], cby4line);
}
}
//**************************LCD12864*********************************
//****************************************************/
void LCD12864_SWrCom(ui8 com)
{
ui8 i = 0;
ui8 tem = 0xF8; //11111000B, write command
while(LCD_CheckBusy())
{
if(i < 200)
{
Delayxms(1,FSCLK);
i++;
}
else
return;
}
LCD_CS = 1;
LCD_CLK = 0;
Delay1us(FSCLK);
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
tem = 0;
tem |= (com & 0xF0);
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
tem = 0;
tem |= (com & 0x0F) << 4;
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
LCD_CS = 0;
}
//End of LCD12864_SWrCom(ui8 com)
//****************************************************/
void LCD12864_WriteCom(ui8 com, BOOL bSerPort)
{
ui8 i = 0;
while(LCD_CheckBusy())
{
if(i< 200)
{
Delayxms(1,FSCLK);
i++;
}
else
return;
}
if(!bSerPort)
LCD_WriteCom(com, 0);
else
LCD12864_SWrCom(com);
}
//End of LCD12864_WriteCom(ui8 com, BOOL bySerPort)
//****************************************************/
void LCD12864_Init(BOOL bSerPort)
{
if(bSerPort)
{
LCD12864_WriteCom(0x30, 1); //select basic command
LCD12864_WriteCom(0x0C, 1); //display enable,cursor disable
LCD12864_WriteCom(0x01, 1); //clear screen
LCD12864_WriteCom(0x80, 1); //set charater start point (0,0) 0: colummn, 0: row
}
else
{
LCD12864_WriteCom(0x30, 0); //select basic command
LCD12864_WriteCom(0x0C, 0); //display enable,cursor disable
LCD12864_WriteCom(0x01, 0); //clear screen
LCD12864_WriteCom(0x80, 0); //set charater start point (0,0) 0: colummn, 0: row
}
}
//End of LCD12864_Init(BOOL bSerPort, BOOL bGraph)
//****************************************************/
void LCD12864_SWrData(BYTE mdata)
{
ui8 i = 0;
ui8 tem = 0xFA; //11111010B, write data
while(LCD_CheckBusy())
{
if(i < 200)
{
Delayxms(1,FSCLK);
i++;
}
else
return;
}
LCD_CS = 1;
LCD_CLK = 0;
Delay1us(FSCLK);
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
tem = 0;
tem |= (mdata & 0xF0);
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
tem = 0;
tem |= (mdata & 0x0F) << 4;
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
LCD_CS = 0;
}
//End of LCD12864_SWrData(BYTE mdata)
//****************************************************/
void LCD12864_WriteData(BYTE mdata, BOOL bSerPort)
{
ui8 i = 0;
while(LCD_CheckBusy())
{
if(i < 200)
{
Delayxms(1,FSCLK);
i++;
}
else
return;
}
if(!bSerPort)
LCD_WriteData(mdata, 0);
else
LCD12864_SWrData(mdata);
}
//End of LCD12864_WriteData(BYTE mdata, BOOL bySerPort)
//****************************************************/
BYTE LCD12864_RdData(BOOL bSerPort)
{
BYTE i, readValue;
i = 0;
while(LCD_CheckBusy())
{
if(i < 200)
{
Delayxms(1,FSCLK);
i++;
}
else
return 0;
}
if(!bSerPort)
{
LCD_RS = 1;
LCD_RW = 1;
LCD_EA = 0;
Delayxms(1,FSCLK);
LCD_EA = 1;
Delayxms(5,FSCLK);
readValue = LCD_DATAPINS;
LCD_EA = 0;
}
else
{
ui8 tem = 0xFE; //11111010B, read data
LCD_CS = 1;
LCD_CLK = 0;
Delay1us(FSCLK);
for(i = 0; i < 8; i++)
{
if(tem&0x80>>i)
LCD_SID = 1;
else
LCD_SID = 0;
Delay1us(FSCLK);
LCD_CLK = 1;
Delay1us(FSCLK);
LCD_CLK = 0;
}
tem = 0;
for(i = 0; i < 8; i++)
{
LCD_CLK = 1;
Delay1us(FSCLK);
if(LCD_SID)
tem += (0x80 >> i);
Delay1us(FSCLK);
LCD_CLK = 0;
Delay1us(FSCLK);
}
readValue = tem & 0xF0;
tem = 0;
for(i = 0; i < 8; i++)
{
LCD_CLK = 1;
Delay1us(FSCLK);
if(LCD_SID)
tem += (0x80 >> i);
Delay1us(FSCLK);
LCD_CLK = 0;
Delay1us(FSCLK);
}
tem >>= 4;
readValue += (tem & 0x0F);
}
return readValue;
}
//End of LCD12864_RdData(BOOL bSerPort)
//****************************************************/
void LCD12864_ClearScreen(BOOL bSerPort, BOOL bGraph)
{
ui8 i,j;
if(!bGraph)
{
if(bSerPort)
LCD12864_WriteCom(0x01, 1); //clear screen
else
LCD12864_WriteCom(0x01, 0); //clear screen
}
else
{
LCD12864_WriteCom(0x34, bSerPort); //use extend command
for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次
{
LCD12864_WriteCom(0x80+i, bSerPort); //先写入纵坐标Y的值
LCD12864_WriteCom(0x80, bSerPort); //再写入横坐标X的值
for(j=0;j<32;j++) //横坐标有16位,每位写入两个字节的的数据,也
{ //就写入32次以为当写入两个字节之后横坐标会自
LCD12864_WriteData(0x00,bSerPort); //动加1,所以就不用再次写入地址了。
}
}
LCD12864_WriteCom(0x36, bSerPort); //0x36扩展指令里面打开绘图显示
LCD12864_WriteCom(0x30,bSerPort); //恢复基本指令集
}
}
//End of LCD12864_ClearScreen(BOOL bSerPort, BOOL bGraph)
//****************************************************/
void LCD12864_SetPos(ui8 x, ui8 y, BOOL bSerPort)
{
switch(y)
{
case 0:
y = 0x80; // 第1行的地址是80H
break;
case 1:
y = 0x90; //第2行的地址是90H
break;
case 2:
y = 0x88; //第3行的地址是88H
break;
case 3:
y = 0x98; //第4行的地址是98H
}
LCD12864_WriteCom(x+y, bSerPort);
}
//End of LCD12864_SetPos(ui8 x, ui8 y, BOOL bSerPort)
//****************************************************/
void LCD12864_DrawPoint(ui8 x, ui8 y, BOOL bSerPort)
{
BYTE bt = 0, readValue = 0;
BYTE x_adr, y_adr, h_bit, l_bit;
//--Y轴最大一共64,但是12864分为上半屏和下半屏,超过32就是下半屏了,--//
//--地址得又从零开始了。所以对32求余数,得到Y轴的坐标,然后加上80H的基地址--//
y_adr = 0x80 + y % 32; //计算Y轴的地址
//--当Y大于31时是下半屏,X(水平位置的地址)是从88H开始的,而且它是16位一--//
//--个地址,所以对16求模。而上半屏的地址是从80H开始的--//
if(y>31)
{
x_adr = 0x88 + x / 16; //计算X轴的地址
}
else
{
x_adr = 0x80 + x / 16;
}
//--求出X(水平位置),点亮的点是在16位数据里面的哪一个位--//
//--所以对这个数求余数--//
bt = 0x8000 >> (x % 16);
LCD12864_WriteCom(0x34, bSerPort); //进入拓展指令集
LCD12864_WriteCom(y_adr,bSerPort); //读取数据的时候要先写入所取数据的地址
LCD12864_WriteCom(x_adr, bSerPort);
LCD12864_RdData(bSerPort); //读取的第一个字节不要,
readValue = LCD12864_RdData(bSerPort); //从第二个字节开始接收。
readValue <<= 8;
readValue |= LCD12864_RdData(bSerPort);
bt = bt | readValue;
h_bit = bt >> 8;
l_bit = bt;
LCD12864_WriteCom(y_adr, bSerPort); //写入点的时候,重新写入地址,因为地址已经改变。
LCD12864_WriteCom(x_adr, bSerPort);
LCD12864_WriteData(h_bit, bSerPort);
LCD12864_WriteData(l_bit, bSerPort);
LCD12864_WriteCom(0x36,bSerPort); //开显示
LCD12864_WriteCom(0x30,bSerPort); //关闭绘图指令集
}
//End of LCD12864_DrawPoint(ui8 x, ui8 y, BOOL bSerPort)
//****************************************************/
void LCD12864_DrawGraph(ui8 graph[], BOOL bSerPort)
{
ui8 i,j;
LCD12864_ClearScreen(bSerPort, 1);
LCD12864_WriteCom(0x34, bSerPort); //开启扩展指令集,并关闭画图显示。
for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次
{
LCD12864_WriteCom(0x80+i, bSerPort); //先写入纵坐标Y的值
LCD12864_WriteCom(0x80, bSerPort); //再写入横坐标X的值
for(j=0; j<16; j++) //横坐标有16位,每位写入两个字节的的数据,也
{ //就写入32次以为当写入两个字节之后横坐标会自
LCD12864_WriteData(*graph, bSerPort); //动加1,所以就不用再次写入地址了。
graph++;
}
}
for(i=0; i<32; i++) //因为LCD有纵坐标32格所以写三十二次
{
LCD12864_WriteCom(0x80+i, bSerPort); //先写入纵坐标Y的值
LCD12864_WriteCom(0x88, bSerPort); //再写入横坐标X的值
for(j=0; j<16; j++) //横坐标有16位,每位写入两个字节的的数据,也
{ //就写入32次以为当写入两个字节之后横坐标会自
LCD12864_WriteData(*graph, bSerPort); //动加1,所以就不用再次写入地址了。
graph++; }
}
LCD12864_WriteCom(0x36, bSerPort); //开显示
LCD12864_WriteCom(0x30, bSerPort); //转回基本指令集
}
//End of LCD12864_DrawGraph(ui8 graph[], BOOL bSerPort)
//****************************************************/
void LCD12864_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL bSerPort)
{
ui8 i = 0;
LCD12864_SetPos(x, y, bSerPort);
while(mstr[i] !=0)
{
LCD12864_WriteData(mstr[i], bSerPort);
i++;
}
}
//End of LCD12864_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL bSerPort)
//****************************************************/
void LCD12864_DisplaynC(ui8 x, ui8 y, ui8 n, ui8* mstr, BOOL bSerPort)
{
ui8 i = 0;
LCD12864_SetPos(x, y, bSerPort);
for(i = 0; i < n ; i++)
{
LCD12864_WriteData(mstr[i], bSerPort);
}
}
//End of LCD12864_DisplayString(ui8 x, ui8 y, ui8* mstr, BOOL bSerPort)
三? ?函数调用示例?
? ? ?在main.h中加入如下代码:
/*main.h
Designed by Bill Liu
Version 0.0
Modified last by Bill Liu on 11/13/2021
*/
#ifndef __MAIN_H_
#define __MAIN_H_
#include "mtype.h"
#include "stc15w4k.h"
#include "stcio.h"
#include "lcd.h"
const FSYSCLOCK FSCLK = F30MHz;
ui8 mstr1[17]=" ";
ui8 mstr2[17] = "1234567890";
ui8 mstr3[17] = "ABCDEFGHIJKLMNOPQ";
#endif
? ? 在myport.h中加入如下代码:
/*myport.h
Designed by Bill Liu
Version 0.0
Modified last by Bill Liu on 11/11/2021
*/
#ifndef __MYPORT_H_
#define __MYPORT_H_
#include "stc15w4k.h"
#define LCD_DATAPINS P0
sbit LCD_RS = P4^1;
sbit LCD_RW = P4^2;
sbit LCD_EA = P4^4;
//sbit LCD12864_PSB = P3^7; //LCD12864_PSB = 1; //选择并行输入
//sbit LCD12864_RST = P3^6; //LCD12864_RST = 1; //复位
sbit LCD_CS = P4^1;
sbit LCD_SID = P4^2;
sbit LCD_CLK = P4^4;
#endif
? 在main.c中加入如下代码:
#include "main.h"
void main()
{
STCIO_InitPortsBits(P0|P1|P2|P3|P4, 0xFF, BI_IO);
LCD_Init(1);
LCD1602_DisplayString(0, 0, mstr2, 1);
LCD1602_DisplaynC(0, 1, 16, mstr3, 1);
while(1)
{
;
}
}
? ? 编译结果如下:
?没有错误,没有警告。下载到单片机,LCD1602的显示结果如下:
LCD1602,LCD2004,LCD12864的datasheet及本例程的源码已上传到CSDN。文件名分别为LCD Datasheet.rar,LCD Diver Code.rar。如需要参考可搜索下载。
?
|