1 LCD显示器相关背景
1.1 LCD简介
(1)显示器,常见显示器。
(2)LCD(Liquid Crystal Display),液晶显示器,原理介绍。
(3)LCD应用领域。
(4)LED OLED。
1.2 电子显示器的原理
(1)像素(分辨率)。
(2)显存,用来做显示的内存。
(3)字模。
(4)字库。
(5)控制器和驱动器。
(6)软件+硬件实现功能。
2 开始学习LCD1602
2.1 简介
(1)为什么叫1602(16x2,显示器显示2排,每排16个字符)。能显示的字符数是32,但是像素数不是32,因为一个字符是由多个像素组成的。有可能一个字符是由5*7=35个像素组成的,也有可能是由6*8=48个像素组成的。但是我们不用去管,因为LCD1602内置了字库了。
(2)带ASCII码字库,不能显示中文。当我们想让LCD1602显示某个ASCII码字符时,只需要将这个字符对应的ASCII码发给LCD1602内部的控制器,控制器就会去查字库得到字模,然后将字模发给内部的驱动器去驱动LCD做显示。
(3)用途:工业应用。
2.2 原理图和接线引脚
(1)引脚分为:数据接口(8)+控制接口(3)+VO(1)+电源地(4)。
(2)并行接口:串行就是数据线只有1根,同时只能传输1个bit位,如果要传送多个bit位必须分时传输;并行就是数据线有多根,每一根可以传输1个bit位,所以同时可以传输多个bit位。譬如LCD1602有8根数据线,所以一次同时传输8个bit位。
(3)背光亮度调节。
(4)接线确认。
2.3 数据手册
(1)概念:LCM和LCD,其实lcm就是lcd module(LCD模组)。
(2)主要技术参数解析。
(3)引脚定义(结合原理图来对照分析)。
(4)控制器接口说明(注意控制器型号)。
RS=1时,D0-D7上传输的是数据
RS=0时,D0-D7上传输的是命令
RW=1时,表示我们要读
RW=0时,表示我们要写
E=1时,表示使能 enable
E=0时,表示禁止(禁能) disable
3 LCD1602控制器的低层时序
3.1 关键点
(1)时序走控制接口引脚。
(2)指令码、状态字、数据,这三个走数据接口。
(3)注意是并行的。
3.2 读状态时序分析
(1)低层时序描述。
(2)官方示例程序。
(3)状态字的解析方法。
3.3 写指令时序分析
(1)低层时序描述。
(2)官方示例程序。
(3)指令码的解析方法。
3.4 读写数据
(1)读数据。
(2)写数据。
(3)RAM空间。RAM地址范围(芯片范围是0-39每行,但是实际只用了0-15每行),数据是什么数据:要显示的字符的ASCII码编码值。
3.5 指令说明
00001000 0x08 关闭显示
00001100 0x0C 打开显示不显示光标
00001111 0x0F 打开显示并且显示光标并且光标闪烁
00000110 0x06 地址指针自动加1,整体屏幕不移动
0x80+(0x00-0x0F) 第一行设置地址指针指令
0x80+(0x40-0x4F) 第二行设置地址指针指令
0x01 显示清屏
0x02 回车
4 代码实践
1602.h
#ifndef __1602_H__
#define __1602_H__
// 只需要声明高层时序即可,而低层时序是不需要声明的。
// 因为我们在头文件中声明这个函数,目的是为了让别的文件去包含这个头文件
// 从而可以调用这个头文件中声明的函数,所以我们只需要声明1602.c中将来
// 会被外部.c文件调用的那些函数即可。而1602.c中自己使用的内部函数将来也
// 不会被外部.c文件调用,因此就不用声明了
void InitLcd1602();
void LcdSetCursor(unsigned char x,unsigned char y);
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);
#endif
l602.c
#include <reg51.h>
// 对LCD1602的底层以及高层时序做封装
// IO接口定义
#define LCD1602_DB P0 //data bus 数据总线
// 控制总线
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P2^7;
/************ 低层时序 ********************************/
void Read_Busy() //忙检测函数,判断bit7是0,允许执行;1禁止
{
unsigned char sta; //
LCD1602_DB = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
do
{
LCD1602_EN = 1;
sta = LCD1602_DB;
LCD1602_EN = 0; //使能,用完就拉低,释放总线
}while(sta & 0x80);
}
void Lcd1602_Write_Cmd(unsigned char cmd) //写命令
{
Read_Busy();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
void Lcd1602_Write_Data(unsigned char dat) //写数据
{
Read_Busy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
/************* 高层时序 ******************************/
// 本函数用来设置当前光标位置,其实就是设置当前正在编辑的位置,
// 其实就是内部的数据地址指针,其实就是RAM显存的偏移量
// x范围是0-15,y=0表示上面一行,y=1表示下面一行
void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示
{
unsigned char addr;
if(y == 0)
addr = 0x00 + x;
else
addr = 0x40 + x;
Lcd1602_Write_Cmd(addr|0x80);
}
// 函数功能是:从坐标(x,y)开始显示字符串str
// 注意这个函数不能跨行显示,因为显存地址是不连续的
// 其实我们可以封装出一个能够折行显示的函数的
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串
{
LcdSetCursor(x,y); //当前字符的坐标
while(*str != '\0')
{
Lcd1602_Write_Data(*str++);
}
}
// 初始化LCD,使之能够开始正常工作
void InitLcd1602() //1602初始化
{
Lcd1602_Write_Cmd(0x38); //打开,5*8,8位数据
//Lcd1602_Write_Cmd(0x0c); // 打开显示并且无光标
Lcd1602_Write_Cmd(0x0f); // 打开显示并且光标闪烁
Lcd1602_Write_Cmd(0x06);
Lcd1602_Write_Cmd(0x01); //清屏
}
main.c
#include "1602.h"
void main(void)
{
InitLcd1602();
//LcdShowStr(0, 0, "www.zhulaoshi.org");
LcdShowStr(0, 0, "zhulaoshi");
//LcdShowStr(0, 1, "angdajiangtang");
}
5 LCD12864介绍
5.1 何为LCD12864
(1)128p*64p,注意不是字符而是pixel。
(2)没有内置字库,用户需要提供字模给LCD12864内部的控制器。
(3)常见外观有2类(网上找图看)。
(4)可以显示文字(英文、中文或其他文字)和图片(点阵图)。
5.2 原理图和数据手册和接线
(1)接线确认。
(2)原理图(开发板底板、屏幕转接板)。
(3)数据手册(LCD12864、ST7565)。
5.3 编程接口
(1)并行接口。
(2)控制总线+数据总线。
(3)控制总线的定义总结。
6 LCD12864低层时序分析
6.1 学习方法
(1)找准数据手册中关键信息点,用来查而不是挨个看。
(2)数据手册对照官方示例代码来参照对比。
(3)要结合各部分原理图、各部分数据手册、示例代码来综合分析。
(4)必要时要做笔记。
6.2 ST7565低层时序分析
(1)写指令。
/*******************************************************************************
* 函 数 名 : LCD12864_WriteCmd
* 函数功能 : 写入一个命令到12864
* 输 入 : cmd
* 输 出 : 无
*******************************************************************************/
void LcdSt7565_WriteCmd(cmd)
{
LCD12864_CS = 0; //chip select,打开片选
LCD12864_RD = 1; //disable read,读失能
LCD12864_RS = 0; //select command,选择命令
LCD12864_RW = 0; //select write,选择写模式
_nop_();
_nop_();
DATA_PORT = cmd; //put command,放置命令
_nop_();
_nop_();
LCD12864_RW = 1; //command writing ,写入命令
}
(2)写数据。
/*******************************************************************************
* 函 数 名 : LcdSt7565_WriteData
* 函数功能 : 写入一个数据到12864
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
void LcdSt7565_WriteData(dat)
{
LCD12864_CS = 0; //chip select,打开片选
LCD12864_RD = 1; //disable read,读失能
LCD12864_RS = 1; //select data,选择数据
LCD12864_RW = 0; //select write,选择写模式
_nop_();
_nop_();
DATA_PORT = dat; //put data,放置数据
_nop_();
_nop_();
LCD12864_RW = 1; //data writing,写数据
}
6.3 总结
(1)随着产品变复杂,资料也会变复杂。
(2)资料会有不完善,甚至错误的。
(3)思路要始终清晰,大脑必须有一定复杂度。
7 ST7565的指令集
7.1 高层时序分析
(1)指令式交互系统。
(2)指令表是关键。
7.2 指令系统学习方法
(1)沿着数据手册顺序分析。
(2)沿着示例代码按需分析。
7.3 逐个分析
(1)1号指令:Display ON/OFF,
10101111 0xAF on
10101110 0xAE off
(2)2号指令:显示行号设置
01000000+(0-63)
0x40+(0-63) 表示要将内容显示在第0-63行
(3)3号指令:设置page address
10110000+(0-7)
0xB0+(0-7) 表示设置page address到0-8
(4)4号指令:设置column address
一个完整指令是分为2条相连的指令合起来的。必须连发2个
指令1:00010000+高4位 0x10+高4位
指令2:00000000+低4位 0x00+低4位
(8)设置ADC:
0xA0 normal, columu address 从左往右的
0xA1 reverse, column address 从右往左的
7.4 LCD初始化函数
(1)第一类指令:时序需要的。
(2)第二类指令:硬件特性设置需要的(譬如屏幕亮度、对比度之类的)。
(3)第三类指令:显示参数相关的:A1/A0 C8/C0 0x40+(0-63)。
/*******************************************************************************
* 函 数 名 : LCD12864_Init
* 函数功能 : 初始化12864
* 输 入 : 无
* 输 出 : 无
* 说 明 : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
* * 的第51页的位置。
*******************************************************************************/
void Lcd12864_Init()
{
uchar i;
LCD12864_RSET = 0;
for (i=0; i<100; i++);
LCD12864_CS = 0;
LCD12864_RSET = 1;
//----------------Start Initial Sequence-------//
//------程序初始化设置,具体命令可以看文件夹下---//
//--软件初始化--//
LcdSt7565_WriteCmd(0xE2); //reset
for (i=0; i<100; i++); //延时一下
//--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//
// 0xA0对应0-127,0xA1对应4-131
LcdSt7565_WriteCmd(0xA0); //ADC select segment direction
//--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--//
LcdSt7565_WriteCmd(0xC8); //Common direction
//--表格第9个命令,0xA6为设置字体为黑色,背景为白色---//
//--0xA7为设置字体为白色,背景为黑色---//
LcdSt7565_WriteCmd(0xA6); //reverse display
//--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//
LcdSt7565_WriteCmd(0xA4); //normal display
//--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//
LcdSt7565_WriteCmd(0xA2); //bias set 1/9
//--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--//
//--0xF801,选择增压为5X,其实效果差不多--//
LcdSt7565_WriteCmd(0xF8); //Boost ratio set
LcdSt7565_WriteCmd(0x01); //x4
//--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--//
//--选择从0x00到0X3F。用来设置背景光对比度。---/
LcdSt7565_WriteCmd(0x81); //V0 a set
LcdSt7565_WriteCmd(0x23);
//--表格第17个命令,选择调节电阻率--//
LcdSt7565_WriteCmd(0x25); //Ra/Rb set
//--表格第16个命令,电源设置。--//
LcdSt7565_WriteCmd(0x2F);
for (i=0; i<100; i++);
//--表格第2个命令,设置显示开始位置--//
LcdSt7565_WriteCmd(0x40); //start line
//--表格第1个命令,开启显示--//
LcdSt7565_WriteCmd(0xAF); // display on
for (i=0; i<100; i++);
}
7.5 清屏操作
/*******************************************************************************
* 函 数 名 : LCD12864_ClearScreen
* 函数功能 : 清屏12864
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Lcd12864_ClearScreen(void)
{
uchar i, j;
for(i=0; i<8; i++)
{
//--表格第3个命令,设置Y的坐标--//
//--Y轴有64个,一个坐标8位,也就是有8个坐标--//
//所以一般我们使用的也就是从0xB0到0x07,就够了--//
LcdSt7565_WriteCmd(0xB0+i);
//--表格第4个命令,设置X坐标--//
//--当你的段初始化为0xA1时,X坐标从0x10,0x04到0x18,0x04,一共128位--//
//--当你的段初始化为0xA0时,X坐标从0x10,0x00到0x18,0x00,一共128位--//
//--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA0所以--//
//--我们的X坐标从0x10,0x00开始---//
LcdSt7565_WriteCmd(0x10);
LcdSt7565_WriteCmd(0x00);
//--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//
for(j=0; j<128; j++)
{
LcdSt7565_WriteData(0x00); //如果设置背景为白色时,清屏选择0XFF
}
}
}
8 LCD12864显示文字
8.1 文字显示的原理分析
(1)字模。
(2)像素&显存的对应关系。