#include "LCD.h"
// 加载字体库
#include "XKData.h" //行楷
#define Zx 16 //字宽
#define Zy 16 //字高
/* 宏定义 */
// ST7920 控制端口定义
// 端口设置
#define LCD_CTL_OUT P3OUT
#define LCD_CTL_IN P3IN
#define LCD_CTL_DIR P3DIR
// 引脚定义
#define LCD_RS BIT7
#define LCD_RW BIT6
#define LCD_E BIT5
#define LCD_PSB BIT4
#define LCD_RST BIT3
// 引脚动作定义
#define LCD_RS_HIGH (LCD_CTL_OUT |= LCD_RS)
#define LCD_RS_LOW (LCD_CTL_OUT &= ~LCD_RS)
#define LCD_RW_HIGH (LCD_CTL_OUT |= LCD_RW)
#define LCD_RW_LOW (LCD_CTL_OUT &= ~LCD_RW)
#define LCD_E_HIGH (LCD_CTL_OUT |= LCD_E)
#define LCD_E_LOW (LCD_CTL_OUT &= ~LCD_E)
#define LCD_PSB_HIGH (LCD_CTL_OUT |= LCD_PSB)
#define LCD_PSB_LOW (LCD_CTL_OUT &= ~LCD_PSB)
#define LCD_RST_HIGH (LCD_CTL_OUT |= LCD_RST)
#define LCD_RST_LOW (LCD_CTL_OUT &= ~LCD_RST)
// ST7920 数据端口定义
// 端口设置
#define LCD_DATA_OUT P5OUT
#define LCD_DATA_IN P5IN
#define LCD_DATA_DIR P5DIR
// 引脚动作定义
#define LCD_DATA_DOUT (LCD_DATA_DIR = 0xff)
#define LCD_DATA_DIN (LCD_DATA_DIR = 0x00)
// 时序延迟
#define LCD_DELAY (1)
/* 全局变量声明 ---------------------------------------------------- */
unsigned char LCD_Busy; // 总线忙标志
/* 底层时序函数 ---------------------------------------------------- */
// 延迟程序(产生略微的延迟)
void LCD_Delay(unsigned int time)
{
for(int i=0; i<time; i++) _NOP();
}
// 读寄存器状态(主要用于判忙)
// RS L
// RW H
unsigned char LCD_StatusRead(void)
{
unsigned char Status;
// 控制线
LCD_RS_LOW;
LCD_RW_HIGH;
// 判忙
LCD_E_HIGH;
LCD_Delay(LCD_DELAY);
Status = LCD_DATA_IN;
LCD_E_LOW;
return Status;
}
// 液晶读/写操作判忙
void LCD_BusyRead(void)
{
LCD_DATA_DIN;
unsigned char Status;
do
{
// 读取状态
Status = LCD_StatusRead();
// 判断标志
if (!(Status & 0x80) ) LCD_Busy = 0; /* !! 判忙语句 !! */
else LCD_Busy = 1;
}
while(LCD_Busy == 1);
}
// 伪造液晶读/写操作判忙(用延时替代)
void LCD_BusyRead_(void)
{
LCD_Delay(2*LCD_DELAY);
}
// 写数据到液晶
// RS H
// RW L
void LCD_WriteData(unsigned char Data)
{
LCD_BusyRead(); // 判忙
// 控制线
LCD_RW_LOW;
LCD_RS_HIGH;
// 数据方向
LCD_DATA_DOUT;
// 准备数据
LCD_DATA_OUT = Data;
LCD_Delay(LCD_DELAY);
// 写操作
LCD_E_HIGH;
LCD_Delay(LCD_DELAY);
LCD_E_LOW;
// 数据方向
LCD_DATA_DIN;
}
// 写命令到液晶
// RS L
// RW L
void LCD_WriteCommand(unsigned char Command)
{
LCD_BusyRead(); // 判忙
// 控制线
LCD_RW_LOW;
LCD_RS_LOW;
// 数据方向
LCD_DATA_DOUT;
// 准备数据
LCD_DATA_OUT = Command;
LCD_Delay(LCD_DELAY);
// 写操作
LCD_E_HIGH;
LCD_Delay(LCD_DELAY);
LCD_E_LOW;
// 数据方向
LCD_DATA_DIN;
}
// 读数据从液晶
// RS H
// RW H
unsigned char LCD_ReadData(void)
{
unsigned char Temp;
LCD_BusyRead(); // 判忙
// 控制线
LCD_RS_HIGH;
LCD_RW_HIGH;
// 读数据
LCD_E_HIGH;
LCD_Delay(LCD_DELAY);
Temp = LCD_DATA_IN;
LCD_E_LOW;
return (Temp);
}
/* 功能函数 --------------Ascii------------------------------------- */
// 将位置地址设置到(x, y)位置
extern void LCD_SetXYAsc(unsigned char x, unsigned char y)
{
unsigned char XY=0x80; // 计算坐标
if (y%2) XY += 0x10;
if (y<=1) XY += x;
else XY += (x+0x08);
LCD_WriteCommand(XY); // 设置地址
}
/* 上层函数 ---------------Ascii------------------------------------ */
/*说明: 下面函数是供外部文件调用的, 可以完成对液晶的常用操作*/
// 在指定的(x,y)位置写入一个数据
extern void LCD_LocateAsc(/*unsigned char x, unsigned char y, */unsigned char Data)
{
//LCD_SetXYAsc(x,y);
LCD_WriteData(Data);
}
// 初始化函数
extern void LCD_InitAsc(void)
{
// 引脚设置
LCD_CTL_OUT |= LCD_RS + LCD_RW + LCD_E + LCD_PSB + LCD_RST;
LCD_CTL_DIR |= LCD_RS + LCD_RW + LCD_E + LCD_PSB + LCD_RST;
LCD_PSB_HIGH; // 并口
LCD_DATA_DIN;
// 硬件复位液晶
LCD_RST_LOW;
LCD_Delay(200);
LCD_RST_HIGH;
LCD_Delay(10);
// 功能初始化
LCD_WriteCommand(0x30); // 8位传输,基本指令集命令
LCD_WriteCommand(0x01); // clear screen
LCD_WriteCommand(0x06); // 光标右移,AC自加,显示整体不移动
LCD_WriteCommand(0x0c); // 开整体显示,光标不显示、不闪烁
}
// 写一行字符
extern void LCD_LocateLineAsc(uchar y,uchar *Data)
{
LCD_SetXYAsc(0,y);
for(uchar i=0 ; i<16 && *(Data+i)!='\0' ; i++)
LCD_WriteData(*(Data+i));
}
extern void LCD_LocateClearAsc()
{
for(int i=0;i<4;i++)
LCD_LocateLineAsc(i," ");
}
extern uchar LCD_Read(uchar x,uchar y)
{
LCD_SetXYAsc(x,y);
return LCD_ReadData();
}
/* 功能函数 ---------------Pic-------------------------------------- */
// 将位置地址设置到(x, y)位置
extern void LCD_SetXYPic(unsigned char x, unsigned char y)
{
unsigned char XY=0x80; // 计算坐标
XY += y%32;
LCD_WriteCommand(XY); // Y设置地址
XY=0x80;
if (y<32) XY += x;
else XY += (x+0x08);
LCD_WriteCommand(XY); // X设置地址
}
/* 上层函数 ----------------Pic------------------------------------- */
/*说明: 下面函数是供外部文件调用的, 可以完成对液晶的常用操作*/
// 在指定的(x,y)位置写入一个数据
extern void LCD_LocatePic(/*unsigned char x, unsigned char y, */unsigned char Data)
{
//LCD_SetXYPic(x,y);
LCD_WriteData(Data);
}
extern void LCD_LocateBasic(uchar x,uchar y,uchar m,uchar n,uchar *Data)
{
uchar i,j;
for(i=0;i<n;i++)
{
j=0;
LCD_SetXYPic(x+j,y+i);
for(;j<(m/16);j++)
{
LCD_LocatePic(Data[i*(m/8)+2*j]);
LCD_LocatePic(Data[i*(m/8)+2*j+1]);
}
}
}
extern void LCD_LocateFull(uchar *Data)
{
LCD_LocateBasic(0,0,128,64,Data);
}
extern void LCD_LocateClearPic(uchar x,uchar y,uchar m,uchar n)
{
uchar i,j;
for(i=0;i<n;i++)
{
j=0;
LCD_SetXYPic(x+j,y+i);
for(;j<(m/16);j++)
{
LCD_LocatePic(0);
LCD_LocatePic(0);
}
}
}
/* -------------------------HZ---------------------------------- */
extern void LCD_LocateHZ(uchar x,uchar y,unsigned int Data)
{
uint i;
for(i=0;i<hzNum;i++)
if (Data/256==hzIndex[2*i]&&Data%256==hzIndex[2*i+1]) break;
i *= 32; //定位汉字点阵信息
y *= 16; //汉字位置转换为点阵位置
LCD_LocateBasic( x, y, Zx, Zy, hzdot+i);
}
// --------------------初始化函数---------------------
extern void LCD_InitPic(void)
{
// 引脚设置
LCD_CTL_OUT |= LCD_RS + LCD_RW + LCD_E + LCD_PSB + LCD_RST;
LCD_CTL_DIR |= LCD_RS + LCD_RW + LCD_E + LCD_PSB + LCD_RST;
LCD_PSB_HIGH; // 并口
LCD_DATA_DIN;
// 硬件复位液晶
LCD_RST_LOW;
LCD_Delay(200);
LCD_RST_HIGH;
LCD_Delay(10);
// 功能初始化
LCD_WriteCommand(0x36); // 8位传输,扩充指令集命令
}