IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 51 单片机实战教程(五 LCD 模组驱动程序) -> 正文阅读

[嵌入式]51 单片机实战教程(五 LCD 模组驱动程序)

? ? ?一? 模组简介?? ?常用的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。如需要参考可搜索下载。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 16:02:04  更:2021-11-15 16:02:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:40:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码