📄 lcd12864使用练习.c
字号:
/****************************************************************
本函数功能:练习LCD12864F的使用,可以显示字符,汉字,图像
缺陷:数学函数图像无法显示,无法实现滚屏,应当继续改善
Author: CHANG MING
Create Time : 2009/3/10
注:本程序在已有程序基础上改进,并非原创,特此声明。
*****************************************************************/
#include<reg51.h>
#include<intrins.h>
#include <zm.h> //字模库:汉字,ASCLL码,图像
#include <math.h> //显示函数图像的图文件
//端口定义********************************************************
sbit LCD_WR = P3^0;
sbit LCD_RD = P3^1;
sbit LCD_CE = P3^2;
sbit LCD_CD = P3^3;
#define LCD_DATA P1
//全局变量声明*****************************************************
#define ulong unsigned long
#define uint unsigned int
#define uchar unsigned char
uchar CurCol,CurRow;
uchar uCol,uRow;//
uchar a,b;//文本指针
//T6963命令字******************************************************
#define LC_CUR_POS 0x21 // 光标位置设置
#define LC_CGR_POS 0x22 // CGRAM偏置地址设置
#define LC_ADD_POS 0x24 // 地址指针位置
#define LC_TXT_STP 0x40 // 文本区首址
#define LC_TXT_WID 0x41 // 文本区宽度
#define LC_GRH_STP 0x42 // 图形区首址
#define LC_GRH_WID 0x43 // 图形区宽度
#define LC_MOD_OR 0x80 // 显示方式:逻辑“或”
#define LC_MOD_XOR 0x81 // 显示方式:逻辑“异或”
#define LC_MOD_AND 0x82 // 显示方式:逻辑“与”
#define LC_MOD_TCH 0x83 // 显示方式:文本特征
#define LC_DIS_SW 0x9B // 显示开关:D0=1/0:光标闪烁启用/禁用;
// D1=1/0:光标显示启用/禁用;
// D2=1/0:文本显示启用/禁用;
// D3=1/0:图形显示启用/禁用;
#define LC_CUR_SHP 0xA0 // 光标形状选择:0xA0-0xA7 表示光标占的行数
#define LC_AUT_WR 0xB0 // 自动写设置
#define LC_AUT_RD 0xB1 // 自动读设置
#define LC_AUT_OVR 0xB2 // 自动读/写结束
#define LC_INC_WR 0xC0 // 数据一次写,地址加1
#define LC_INC_RD 0xC1 // 数据一次读,地址加1
#define LC_DEC_WR 0xC2 // 数据一次写,地址减1
#define LC_DEC_RD 0xC3 // 数据一次读,地址减1
#define LC_NOC_WR 0xC4 // 数据一次写,地址不变
#define LC_NOC_RD 0xC5 // 数据一次读,地址不变
#define LC_SCN_RD 0xE0 // 屏读
#define LC_SCN_CP 0xE8 // 屏拷贝
#define LC_BIT_OP 0xF0 // 位操作:D0-D2:定义D0-D7 位;D3:1 置位;0:清除
#define RowCharNum 8
#define ColCharNum 16
//1ms延时***********************************************
void delay(unsigned char i)
{ unsigned char j=0;
for(;i>0;i--)
for(j=0;j<124;j++)
;
}
//检查状态是否忙*****************************************
void CheckStatus(void)
{
LCD_WR = 1;
LCD_CE = 0; //片选信号
LCD_DATA= 0XFF;
LCD_CD = 1;
LCD_RD = 0;
_nop_();
_nop_();
while((LCD_DATA & 0x03)!=0x03);
LCD_RD = 1;
}
//检查自动写状态是否忙**********************************
void CheckAutoWrite(void)
{
LCD_WR = 1;
LCD_DATA= 0XFF;
LCD_CE = 0;
LCD_CD = 1;
LCD_RD = 0;
_nop_();
_nop_();
while((LCD_DATA & 0x08)==0x00); //低电平忙
LCD_RD = 1;
}
//写数据*************************************************
void WriteData(uchar dat)
{
CheckStatus();
LCD_RD = 1;
LCD_CE = 0;
LCD_CD = 0; //数据
LCD_WR = 0;
LCD_DATA= dat;
_nop_();
_nop_();
LCD_WR = 1;
delay(2);
}
//写指令*************************************************
void WriteCmd(uchar dat)
{
CheckStatus();
LCD_RD = 1;
LCD_CE = 0;
LCD_CD = 1; //指令
LCD_WR = 0;
LCD_DATA= dat;
_nop_();
_nop_();
LCD_WR = 1;
delay(5);
}
//先写数据,后写指令,只含一个参数的指令******************
void WriteOneData(uchar commd,uchar dat)
{
CheckStatus();
WriteData(dat);
CheckStatus();
WriteCmd(commd);
}
//含两个参数的指令*****************************************
void WriteTwoData(uchar commd,uchar dat1,uchar dat2)
{
CheckStatus();
WriteData(dat1);
CheckStatus();
WriteData(dat2);
CheckStatus();
WriteCmd(commd);
}
//清屏*****************************************************
void cls(uchar dat)
{
uint i;
WriteTwoData(LC_ADD_POS,0x00,0x00); // 置地址指针
//CheckAutoWrite(); //自动写忙判断 ,易进入死循环!!!!!!!!!!!!
WriteCmd(LC_AUT_WR); // 自动写
for(i=0;i<16*64;i++)
{
WriteData(dat); // 写数据
}
WriteCmd(LC_AUT_OVR); // 自动写结束
WriteTwoData(LC_ADD_POS,0x00,0x00); // 重置地址指针 ,很重要
CurRow = 0; // 置地址指针存储变量
CurCol = 0;
}
//端口初始化***********************************************
void LCMInit(void)
{
WriteTwoData(LC_TXT_STP,0xDF,0x01) ; // 文本显示区首地址
WriteTwoData(0x41,0x10,0x00); // 文本显示区宽度
WriteTwoData(LC_GRH_STP,0x00,0x00); // 图形显示区首地址
WriteTwoData(LC_GRH_WID,0x10,0x00); // 图形显示区宽度
//WriteCmd(0x90); // 光标形状
WriteTwoData(0x21,0x06,0x02);
WriteCmd(0x81); // 显示方式设置
WriteCmd(0x98); // 显示开关设置
cls(0x00);
}
//可以单独使用的模块函数1,row表示屏上第几行共4行,col表示列,可以分别显示16个8*16字符
//显示单个字符函数****************************************
void ShowChar(uchar row,uchar col,uchar ch)
{
uchar i;
uchar dat;
unsigned int StartAddr;
while(col>15)
{
col=col-16;
row=row+1;
}
if (row>3) return;
StartAddr=(row<<8)+col;
for (i=0;i<16;i++)
{
dat=ASCII86[(ch-32)*16+i];
WriteTwoData(0x24,(uchar)(StartAddr),(uchar)(StartAddr>>8));//将要送入的数据存放的位置
WriteOneData(0xc4,dat);
StartAddr=StartAddr+ColCharNum; //每行共进行16次编址,每8点一次
}
}
//可以单独使用的模块函数2,*puts表示一个字符串,i表示字符串中字符的个数
//显示多个字符******************************************************
void ShowLine(uchar row,uchar col,uchar *puts,uchar i)
{
uchar j,byte,k;
while(col>15)
{
col=col-16;
row=row+1;
}
if (row>3) return;//看首行是否超出屏幕
for (k=col,j=0;j<i;j++)
{
byte = puts[j];
ShowChar(row,k,byte);
k=k+1;
}
}
//可以单独使用的模块函数3,每行可显示8个16*16字符,扫描方式为行扫描
//n表示将要显示的字符在字符库HANZI[]中的位置
//显示汉字****************************************************
void ShowHZ(uchar row,uchar col,uint n)
{
unsigned char i;
unsigned int StartAddr;
while(col>14)
{
col=col-16;
row=row+1;
}
if (col<0) col=0;
if (row>3) return;
StartAddr=(row<<8)+col; //定位起始单元地址 ,好方法
for(i=0;i<16;i++)
{
WriteTwoData(0x24,(unsigned char)(StartAddr),(unsigned char)(StartAddr>>8));
WriteOneData(0xc0,HANZI[n*32+i*2]); //左半部 地址加一
WriteOneData(0xc4,HANZI[n*32+i*2+1]); //右半部 字模地址加一
StartAddr=StartAddr + ColCharNum; //下一行字符首地址
}
}
/*
//可以单独使用的模块函数4,用于显示图片
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -