4_12864液晶屏使用文档
文件网盘链接:https://pan.baidu.com/s/158e_RyHuAqLyWNqZZhgi2A?pwd=1111 提取码:1111
一、12864液晶屏的使用逻辑
二、12864液晶屏硬件说明
12864液晶屏的引脚说明如下表所示:
12864液晶屏内部使用ST7920芯片作为控制芯片,它内置了五种存储器如下表所示:
三、在液晶屏上显示字符
在液晶屏上显示字符的步骤:先给DDRAM写地址,然后给该地址写字符编码数据。液晶屏的DDRAM地址分布如下图所示
每个DDRAM地址可以存储2个字节编码数据(编码数据分为高8位和低8位),一个ASCII码字符要1个字节数据,一个汉字要2个字节数据。不能在同一个地址同时写入ASCII码和汉字,例如在地址0x81高8位写入一个ASCII码的1字节编码数据,在地址0x81低8位和0x82高8位写入一个汉字的2字节编码数据,此时会出错,DDRAM地址与字符编码数据关系如下表所示
显示汉字需要注意:
如果汉字编码以0xFD结尾,此时要在汉字后面手动加上\xfd,否则会显示乱码。因为KEIL的编译器会自动忽略0xFD这个数据。如汉字“三”的编码是0xC8FD,编译后会变成0xC8,为了显示正常,我们要在代码中手动写成三\xfd,如下图所示
四、在液晶屏上画图
在液晶屏上画图的步骤:使用扩展功能指令,关闭画图显示,给GDRAM写行地址,然后写列地址,然后给该地址写图形数据,最后打开画图显示。GDRAM地址如下表所示
五、12864液晶屏指令表
12864液晶屏常用指令如下表所示
六、12864液晶屏写码时序图
1、复位时序
2、8位并行模式写时序
3、8位并行模式读时序
4、4位并行模式时序
5、串行模式时序
七、原理图
本次例程以8位并行模式操作12864液晶屏。原理图如下图所示
八、代码
1、delay延时代码h文件
点击查看代码
#ifndef __DELAY_H__
#define __DELAY_H__
#define uint16 unsigned int
void delay1ms(uint16 z);
#endif
2、delay延时代码c文件
点击查看代码
#include "delay.h"
void delay1ms(uint16 z)
{
uint16 x,y;
for(x=z;x>0;x--)
for(y=114;y>0;y--);
}
3、12864驱动代码h文件
点击查看代码
#ifndef __LCD12864_H__
#define __LCD12864_H__
#define uint8 unsigned char
#define uint32 unsigned long
void Init_12864();
void ClearScreen_12864();
void CheckBusy_12864();
void write_order_12864(uint8 order_12864);
void write_data_12864(uint8 data_12864);
void Display_Number_12864(uint8 y_12864,uint8 x_12864,uint32 number);
void Display_String_12864(uint8 y_12864, uint8 x_12864, uint8 *p_str);
void Display_Picture_12864(uint8 *p_picture);
#endif
4、12864驱动代码c文件
点击查看代码
#include <reg52.h>
#include "delay.h"
#include "LCD12864.h"
sbit EA_12864=P2^4;
sbit RS_12864=P2^5;
sbit RW_12864=P2^6;
sbit PSB_12864=P1^3;
sbit RST_12864=P1^5;
#define LCD12864_DATA P0 //P0口传输LCD12864的8位数据
/**********************************************************
函数名:Init_12864()
函数功能:LCD12864初始化设置
参数列表:无
函数返回值:无
注意:初始化过程看具体厂家的规格书,不同厂家步骤可能不同
***********************************************************/
void Init_12864()
{
PSB_12864=1; //并行模式
RST_12864=0; //复位LCD12864
delay1ms(30);
RST_12864=1;
delay1ms(20);
write_order_12864(0x30); //8位数据口、基本指令集
//write_order_12864(0x30); //实测可以同时设置8位数据口和基本指令集
write_order_12864(0x08); //关液晶屏显示
write_order_12864(0x01); //清屏,地址计数器(AC)归0
write_order_12864(0x06); //DDRAM地址计数器(AC)自动加一、光标右移
write_order_12864(0x0c); //开液晶屏显示
}
/**********************************************************
函数名:void ClearScreen_12864()
函数功能:清屏
参数列表:无
函数返回值:无
***********************************************************/
void ClearScreen_12864()
{
write_order_12864(0x01); //清屏,地址计数器(AC)归0
}
/**********************************************************
函数名:CheckBusy_12864()
函数功能:判忙函数,检测液晶屏是否可以进行读/写操作
参数列表:无
函数返回值:无
***********************************************************/
void CheckBusy_12864()
{
uint8 Busy_data=0; //暂存IO口读的8位数据
LCD12864_DATA=0xff; //IO口读数据前手动置1释放总线
//读指令时序
//每次读指令都要改变一次时序,但不用每次都改变3个引脚的时序,只要改变其中一个脚的时序即可
RS_12864=0;
RW_12864=1;
do
{
EA_12864 = 1;
Busy_data = LCD12864_DATA; //暂存IO口读到的数据
EA_12864 = 0; //读完指令后将EA手动置0,等下一轮再用
} while (Busy_data & 0x80); //STA7为0时允许对液晶屏进行读/写,此时结束循环
LCD12864_DATA=0xff; //IO口读完数据后手动置1释放总线
}
/**********************************************************
函数名:write_order_12864(uint8 order_12864)
函数功能:给液晶屏写指令
参数列表:
order_12864,8位指令码
函数返回值:无
***********************************************************/
void write_order_12864(uint8 order_12864)
{
CheckBusy_12864(); //判忙,液晶屏空闲后才能写指令
//写指令时序
RW_12864=0;
RS_12864=0;
EA_12864=0;
LCD12864_DATA = order_12864; //把要发送的指令存入IO口准备发送
EA_12864=1; //发送指令
//发送后的时序
EA_12864=0;
RW_12864=1;
RS_12864 = 1;
LCD12864_DATA = 0xff; //释放总线
}
/**********************************************************
函数名:write_data_12864(uint8 data_12864)
函数功能:给液晶屏写数据
参数列表:
data_12864,8位数据
函数返回值:无
***********************************************************/
void write_data_12864(uint8 data_12864)
{
CheckBusy_12864(); //判忙,液晶屏空闲后才能写指令
//写数据时序
RW_12864=0;
RS_12864=1;
EA_12864=0;
LCD12864_DATA = data_12864; //把要发送的数据存入IO口准备发送
EA_12864=1; //发送数据
//发送后的时序
EA_12864=0;
RW_12864=1;
RS_12864 = 0;
LCD12864_DATA = 0xff; //释放总线
}
/***********************************************************
函数名:void Display_Number_12864(uint8 y_12864,uint8 x_12864,uint32 number,uint8 count_12864)
函数功能:在液晶屏上指定位置写一个十进制数
参数列表:
y_12864,行坐标(取值范围1~4)
x_12864,列坐标(取值范围1~8)
number,在液晶屏上显示的十进制数(不超过10位)(uint32是32位,取值范围0~4294967296)
函数返回值:无
***********************************************************/
void Display_Number_12864(uint8 y_12864,uint8 x_12864,uint32 number)
{
uint8 row; //液晶屏行地址
uint32 tmp=number; //暂存number的值
uint8 number_arr[10]={0}; //将tmp按位存入number_arr[]中
uint8 count_12864 = 0, i = 0; //count_12864记录本次要显示的十进制位数
do
{
number_arr[count_12864++]=tmp%10; //将tmp从低位到高位存入number_arr[]中
tmp/=10; //舍弃tmp的个位
}while(tmp!=0); //当tmp等于0时结束循环
write_order_12864(0x30); //选择基本指令
write_order_12864(0x06); //设置读/写数据后DDRAM地址计数器(AC)自动加一,光标右移
switch (y_12864) //根据行号选择行地址
{
case 1: row = 0x80; break; //DDRAM第一行首地址
case 2: row = 0x90; break; //DDRAM第二行首地址
case 3: row = 0x88; break; //DDRAM第三行首地址
case 4: row = 0x98; break; //DDRAM第四行首地址
default: ;
}
write_order_12864(row + x_12864 - 1); //写DDRAM列地址,x_12864从1开始,而地址下标从0开始,因此要手动减一
for (i; i < count_12864;i++)
{
//液晶屏显示的数字是ASCII码,而number_arr[]存储的是十进制数
//因此要将number_arr[]存储的十进制数加上0x30转换为ASCII码(0的ASCII码是0x30)
//前面使用了0x06指令,写完数据后DDRAM的AC会自动加一,因此每次写完数据不需要手动改DDRAM地址
write_data_12864(number_arr[count_12864 - 1 - i] + 0x30); //从高位到低位输出要显示的十进制数
}
}
/**********************************************************
函数名:void Display_String_12864(uint8 y_12864,uint8 x_12864,uint8 *p_str)
函数功能:在液晶屏上指定位置显示字符串(汉字和ASCII码字符)
参数列表:
y_12864,行坐标(取值范围1~4)
x_12864,列坐标(显示汉字,取值范围1~8。显示ASCII字符,取值范围1~16)
*p_str,指向要显示的字符串的指针
函数返回值:无
LCD12864显示规则:
(1)显示汉字:每行8个,可以显示4行,总共32个汉字,一个地址1个汉字
(2)显示ASCII码字符,每行16个,可以显示4行,总共64个字符,一个地址2个字符
***********************************************************/
void Display_String_12864(uint8 y_12864,uint8 x_12864,uint8 *p_str)
{
uint8 row,n=0;
write_order_12864(0x30); //选择基本指令
write_order_12864(0x06); //设置读/写数据后DDRAM地址计数器(AC)自动加一,光标右移
switch (y_12864) //根据行号选择行地址
{
case 1: row = 0x80; break; //DDRAM第一行首地址
case 2: row = 0x90; break; //DDRAM第二行首地址
case 3: row = 0x88; break; //DDRAM第三行首地址
case 4: row = 0x98; break; //DDRAM第四行首地址
default: ;
}
write_order_12864(row + x_12864 - 1); //写DDRAM列地址,x_12864从1开始,而地址下标从0开始,因此要手动减一
while(*p_str!='\0') //当指向字符串末尾空字符时结束循环
{
write_data_12864(*p_str++); //写数据,写完指针加一指向下一个要显示的字符
}
}
/**********************************************************
函数名:void Display_Picture_12864(uint8 *p_picture)
函数功能:显示128*64像素的图片
参数列表:
p_picture,指向存储图片数据数组的指针
函数返回值:无
LCD12864实际硬件是纵向32点*横向256点,一列有16个点(16位数据),即32行*16列
显示图片时把第1~8列看作上半屏,第9~16列看作下半屏,单片机要按相应位置将图片数据输出到液晶屏上
***********************************************************/
void Display_Picture_12864(uint8 *p_picture)
{
uint8 i,j;
write_order_12864(0x34); //8位数据口、使用扩展指令、关画图显示
//先显示上半屏
for (i = 0; i < 32;i++) //32行
{
write_order_12864(0x80 + i); //先写GDRAM行地址
write_order_12864(0x80); //再写上半屏GDRAM首列地址0x80
for (j = 0; j < 16;j++) //8列,每个列地址写2个字节图片数据,共16字节数据
{
//初始化设置了每次写完一个地址的数据后AC自动加一,因此不需要手动修改列地址
write_data_12864(*p_picture++); //写图片数据,写完当前数据后指针指向下一个数据
}
}
//再显示下半屏
for (i = 0; i < 32;i++)
{
write_order_12864(0x80 + i); //先写GDRAM行地址
write_order_12864(0x88); //再写下半屏GDRAM首列地址0x88
for (j = 0; j < 16;j++)
{
write_data_12864(*p_picture++);
}
}
write_order_12864(0x36); //开画图显示
write_order_12864(0x30); //画图结束恢复使用基本指令,关画图显示
}
5、图片数据h文件
点击查看代码
#ifndef __PICTURE_H__
#define __PICTURE_H__
#define uint8 unsigned char
//图片是这样的:O_O,图片尺寸纵向64*横向128(每个地址2个字节数据)
uint8 code picture[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x03,0xFF,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x06,0x00,0x00,0x00,0x00,0x06,0x00,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,0x00,0x0C,0x00,0x60,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x01,0x80,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x60,0x00,0xC0,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x60,0x00,0xC0,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x01,0x80,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x1E,0x0F,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x00,0x07,0x81,0xE0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif
6、示例main函数
点击查看代码
#include <reg52.h>
#include "delay.h"
#include "LCD12864.h"
#include "picture.h"
/*
12864显示字符注意事项
1、同一个地址只能写2个ASCII码或1个汉字,不能1个ASCII码加1个汉字
2、显示汉字时,如果汉字编码以0xFD结尾,要在这个汉字后面手动加上\xfd,否则显示乱码。因为KEIL编译器会自动忽略0xFD这个数据,导致乱码。
如汉字“三”的编码是0xC8FD,编译后会变成0xC8,为了显示正常,要写成三\xfd
*/
uint8 *str1="一二三四五六七八"; //错误,“三”和在“三”后面的字符都会乱码
uint8 *str2="一二三\xfd四五六七八"; //正确,手动加上\xfd后就不会乱码
uint8 *str3="abcd1二"; //错误,同一个地址不能写1个ASCII码加1个汉字
uint8 *str4="abcd12二"; //正确
void main()
{
//显示十进制数
Display_Number_12864(1,1,4294967295);
delay1ms(1000);
//显示字符串
Display_String_12864(1,1,str1); //显示字符串1,乱码
Display_String_12864(2,1,str2); //显示字符串2,正确
Display_String_12864(3,1,str3); //显示字符串3,最后的汉字错误
Display_String_12864(4,1,str4); //显示字符串4,正确
delay1ms(1000);
//显示图片
ClearScreen_12864(); //清屏
Display_Picture_12864(picture);
delay1ms(1000);
ClearScreen_12864(); //清屏
while(1)
{
}
}