//LCD显示器端口定义
#define LCD_RS P21 // LCD数据/命令(H/L)选择端
#define LCD_RW P22 // LCD读/写(H/L)选择端
#define LCD_EN P23 // LCD使能信号高有效
#define LCD_DATA P0 // LCD并行数据线
#define LCD_BUSY P07 // LCD忙信号位
//12864特殊端口
//#define LCD_12864_CSA P24 // LCD12864左半屏选择端
//#define LCD_12864_CSB P25 // LCD12864右半屏选择端
//12864基本指令集********************************************************************
#define LCD_12864_CLR 0x01 //清屏,AC、光标归零,DDRAM填满0x20H
#define LCD_12864_GO_HOME 0x02 //AC、光标归零,DDRAM不改变
//输入方式设置
#define LCD_12864_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一
#define LCD_12864_AC_AUTO_DECREASE 0x04 //数据读、写操作后,AC自动减一
#define LCD_12864_MOVE_ENABLE 0x05 //数据读、写操作,画面平移
#define LCD_12864_MOVE_DISENABLE 0x04 //数据读、写操作,画面不动
//设置显示、光标及闪烁开、关
#define LCD_12864_DISPLAY_ON 0x0C //显示开
#define LCD_12864_DISPLAY_OFF 0x08 //显示关
#define LCD_12864_CURSOR_ON 0x0A //光标显示
#define LCD_12864_CURSOR_OFF 0x08 //光标不显示
#define LCD_12864_CURSOR_BLINK_ON 0x09 //光标闪烁
#define LCD_12864_CURSOR_BLINK_OFF 0x08 //光标不闪烁
//光标、画面移动,不影响DDRAM
#define LCD_12864_LEFT_MOVE 0x18 //LCD显示(整屏)左移一位 0x05
#define LCD_12864_RIGHT_MOVE 0x1C //LCD显示(整屏)右移一位 0x07
#define LCD_12864_CURSOR_LEFT_MOVE 0x10 //光标左移一位
#define LCD_12864_CURSOR_RIGHT_MOVE 0x14 //光标右移一位
//指令集设置
#define LCD_12864_BASIC_INSTRUCTION 0x30 //使用基本指令集
#define LCD_12864_EXPAND_INSTRUCTION 0x34 //使用扩充指令集
//地址设定
#define LCD_12864_BASIC_CGRAM 0x40 //设定CGRAM地址到地址计数器(AC)64X256 点阵显示RAM(GDRAM)。
#define LCD_12864_BASIC_DDRAM 0x80 //设定DDRAM地址到地址计数器(AC)
//12864扩充指令集********************************************************************
#define LCD_12864_ORDER 0x01 //待命模式将DDRAM 填满“ 20H ”, 并且设定DDRAM 的地址计数器(AC)到“00H”
#define LCD_12864_IRAM_ON 0x02 //允许输入IRAM地址
#define LCD_12864_VERTICAL_ADDRESS_ON 0x03 //允许输入垂直卷动地址
//反白显示
#define LCD_12864_UP_ONE 0x04 //第一行反白显示
#define LCD_12864_UP_TWO 0x05 //第二行反白显示
#define LCD_12864_UP_THREE 0x06 //第三行反白显示
#define LCD_12864_UP_FOUR 0x07 //第四行反白显示
//睡眠模式
#define LCD_12864_SLEEP_ON 0x08 //进入睡眠模式
#define LCD_12864_SLEEP_OFF 0x0c //脱离睡眠模式
//在扩充指令集时的指令选择
#define LCD_12864_BASIC_INSTRUCTION 0x30 //基本指令集
#define LCD_12864_EXPAND_INSTRUCTION 0x34 //扩充指令集
#define LCD_12864_DRAW_OFF 0x34 //绘图显示关
#define LCD_12864_DRAW_ON 0x36 //绘图显示开
//地址设定
#define LCD_12864_EXPAND_IRAM 0x40 //SR=1:AC5—AC0 为垂直卷动地址SR=0:AC3—AC0 为ICON IRAM 地址
#define LCD_12864_EXPAND_CGRAM 0x80 //设定CGRAM 地址到地址计数器(AC)
//LCD函数声明*************************************************************************
void LCD_Delay_us(unsigned int us); //LCD延时微秒级
unsigned char LCD_BUSY_Bit(void); //解决忙问题
void LCD_Write_Instruction(unsigned char byteData); //写指令
void LCD_Write_DATA(unsigned char byteData); //写数据
unsigned char LCD_Read_Data(); //从内部RAM读取数据
void LCD_12864_Initialization(void); //12864初始化
void LCD_12864_bitInitialization(void); //图形初始化
void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s);
void LCD_Read_dat_I(unsigned char *xp,unsigned char *yp);
void cls_lcd();
void xx_lcd(unsigned char xp,unsigned char yp);
//写入字符串到第x(1,2,3,4)行y(1,16)列 //中间可以有汉字,并自动插入空格
//void LCD_12864_DRAW_CGRAM(UCHAR x,UCHAR *ZOON_CHAR) ;/*CGRAM.x (0-15)的分区数据写入 */
/***************************************************************************************
** 函数名称: LCD_Delay_us(unsigned int us)
** 功能描述: 微秒延时
****************************************************************************************/
void LCD_Delay_us(unsigned int us)
{
while(us--);
}
/***************************************************************************************
** 函数名称: void LCD_12864_bitInitialization(void)
** 功能描述: 初始化函数
** 调用模块: LCD_Write_Instruction();
****************************************************************************************/
void LCD_12864_bitInitialization(void)
{
LCD_Write_Instruction(0x34);
LCD_Write_Instruction(0x03);
LCD_Write_Instruction(0x01);//清屏
LCD_Write_Instruction(0x36);
//LCD_Write_Instruction(0x3f);
//LCD_Write_Instruction(LCD_12864_AC_AUTO_INCREMENT); //数据读、写操作后,AC自动增一,画面不动
//LCD_Write_Instruction(LCD_12864_DISPLAY_ON|LCD_12864_CURSOR_OFF); //显示开光标不显示光标不闪烁
LCD_Write_Instruction(LCD_12864_CLR);//清屏
}
/***************************************************************************************
** 函数名称: void LCD_12864_Initialization(void)
** 功能描述: 初始化函数
** 调用模块: LCD_Write_Instruction();
****************************************************************************************/
void LCD_12864_Initialization(void)
{
LCD_Write_Instruction(LCD_12864_BASIC_INSTRUCTION); //使用基本指令集
LCD_Write_Instruction(LCD_12864_AC_AUTO_INCREMENT); //数据读、写操作后,AC自动增一,画面不动
LCD_Write_Instruction(LCD_12864_DISPLAY_ON|LCD_12864_CURSOR_OFF); //显示开光标不显示光标不闪烁
LCD_Write_Instruction(LCD_12864_ORDER);//清屏
}
/***************************************************************************************
** 函数名称: unsigned char LCD_BUSY_Bit(void)
** 功能描述: 解决忙问题,等待DB07为空
** 说 明:返回当前AC地址
****************************************************************************************/
unsigned char LCD_BUSY_Bit(void)
{
bit byteData;
do
{ //循环开始
LCD_EN = 0; //使能关
LCD_RS = 0; //1数据0指令
LCD_RW = 1; //1读0写
LCD_DATA = 0xff; //拉高数据口电位
LCD_EN = 1; //使能开
byteData = LCD_BUSY; //取状态字DB07的结果
}while(byteData); //循环终点 读到 忙位为0退出,否则继续读忙。
return((LCD_DATA&0x7F)+0x80); //返回AC的值
LCD_EN = 0; //使能关
}
/***************************************************************************************
** 函数名称: void LCD_Write_Instruction(unsigned char byteData)
** 功能描述: 写指令
** 输 入: unsigned char byteData 写指令
** 调用模块: LCD_BUSY_Bit();
****************************************************************************************/
void LCD_Write_Instruction(unsigned char byteData)
{
LCD_BUSY_Bit(); //读忙
LCD_EN = 0; //使能关
LCD_RS = 0; //指令方式
LCD_RW = 0; //写LCD
LCD_DATA = byteData; //指令写入数据口
LCD_EN = 1; //使能开
LCD_Delay_us(4); //微秒延时
LCD_EN = 0; //使能关
}
/***************************************************************************************
** 函数名称: void LCD_Write_DATA(unsigned char byteData)
** 功能描述: 写数据
** 输 入: unsigned char byteData 写数据
** 调用模块: LCD_BUSY_Bit(); LCD_Delay_us();
****************************************************************************************/
void LCD_Write_DATA(unsigned char byteData)
{
LCD_BUSY_Bit(); //读忙
LCD_EN = 0; //使能关
LCD_RS = 1; //数据方式
LCD_RW = 0; //写LCD
LCD_DATA = byteData; //数据写入数据口
LCD_EN = 1; //使能开
LCD_Delay_us(4); //微秒延时
LCD_EN = 0; //使能关
}
/***************************************************************************************
** 函数名称: unsigned char LCD_Read_Data()
** 功能描述: 读取并返回AC指向的数据
** 说 明: 函数外设定AC地址,第一次试读读出高位,第二次会再次读出高位,第三次读出低位,
** 然后AC自动加一,在接下来的读取中,只要不再次指定AC,可按AC顺序读取
****************************************************************************************/
unsigned char LCD_Read_Data()
{
LCD_BUSY_Bit();
LCD_EN = 0; //使能关
LCD_RS = 1; //数据方式
LCD_RW = 1; //读LCD
LCD_DATA = 0xFF; //数据写入数据口
LCD_EN = 1; //使能开
LCD_Delay_us(4); //微秒延时
return(LCD_DATA); //返回AC地址数据
}
/***************************************************************************************
** 函数名称: void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s)
** 功能描述: 写入字符串到第x(1,2,3,4)行y(1,16)列
** 输 入: unsigned char x,unsigned char y,unsigned char *s
** 输 出: 无
** 全局变量: 无
** 调用模块: LCD_BUSY_Bit();LCD_Read_DATA();LCD_Write_Instruction();LCD_Write_DATA();
**设定起始行列数和字符数组,将在12864中顺序显示,在遇到汉字时如果是在地址低位,将在地址低位插入
**一个空格
****************************************************************************************/
void LCD12864_WH_String(unsigned char x,unsigned char y,unsigned char *s)
{
unsigned char Tempi=0; //循环行计次变量
unsigned char TempAC=0; //返回的DDRAM地址变量
unsigned char TempData=0; //返回的DDRAM高字节数据
bit test0=1; //判断是否在第一行
bit test1=0; //标准ASCII码数量的奇偶标记
--y; //输入y下标为1,统一运算y最低为0
for(Tempi=x;Tempi<5;Tempi++)
{ //行扫描循环
switch(Tempi)
{ //强制指定正确的行地址起点
case 1:x=0x80;break; //第一行光标位置
case 2:x=0x90;break; //第二行光标位置
case 3:x=0x88;break; //第三行光标位置
case 4:x=0x98;break; //第四行光标位置
default: break;
}
if(test0)
{ //如果这是第一行
LCD_Write_Instruction(x+(y>>1)); //写入坐标位置
if(y%2)
{ //如果y起点在AC地址低位
TempAC=LCD_BUSY_Bit(); //取当前AC地址
LCD_Write_Instruction(TempAC); //重置当前AC地址
LCD_Read_Data(); //读AC地址高位数据
TempData= LCD_Read_Data(); //读AC地址高位数据
LCD_Write_Instruction(TempAC); //再次重置当前AC地址
LCD_Write_DATA(TempData); //重写地址高位数据(只有重写地址原来高位数据,才能在此地址顺利写入低位数据)
if(*s>127)
{ //如果首字是汉字且起点占据了奇数位
test1=1; //告诉下面的程序在首字插入一个空格
}
else
{ //如果首字是标准ASCII码(这行可以不写)
test1=0;
}
}
test0=0; //首行定位完成,告诉下轮循环从新的地址开始,4轮循环下3次循环都不需要再计算首行起点
}
else
{ //这是4轮循环中的后3轮循环
y=0; //列地址始终从0开始
LCD_Write_Instruction(x); //写入新行首列AC地址
}
for(y;y<16;y++)
{ //列循环扫描
if(*s)
{ //如果字符数组没有到最后一位空数据
if(*s<128)
{ //如果当前字符数组数据是标准ASCII码
test1=~test1; //奇偶翻转
LCD_Write_DATA(*s++); //向LCD写入当前字符后,指针自加1
}
else
{ //如果当前字符数组数据是扩展ASCII码
if(test1)
{ //如果已经写入了奇数个标准ASCII码
LCD_Write_DATA(' '); //插入一个空格,凑齐偶数个标准ASCII码
test1=0; //清空奇偶判断位成偶数标记
}
else
{ //如果先前已经凑齐偶数个标准ASCII码
LCD_Write_DATA(*s++); //写入扩展ASCII码
}
}
}
}
}
}
/***************************************************************************************
** 函数名称: void LCD_12864_DRAW_CGRAM(UCHAR x,UCHAR *ZOON_CHAR)
** 功能描述: CGRAM.x (0-15)的分区数据写入
** 输 入: UCHAR x,UCHAR *ZOON_CHAR
** 输 出: 无
** 全局变量: 无
** 调用模块: 无
****************************************************************************************/
/*
void LCD_12864_DRAW_CGRAM(UCHAR x,UCHAR *ZOON_CHAR)
{
UCHAR i;
LCD_Write_Instruction(LCD_12864_EXPAND_INSTRUCTION | LCD_12864_DRAW_OFF| LCD_12864_BASIC_INSTRUCTION); //扩充指令集开
LCD_Write_Instruction(LCD_12864_DRAW_OFF); //图形显示关
LCD_Write_Instruction(x+0x80); //输入X的坐标
LCD_Write_Instruction(0x80); //输入Y的坐标
for(i=0;i<32;i++) //写了一块分区
{
LCD_Write_DATA(ZOON_CHAR[i*2+1]); //数据的格式为将D15——D8 ,D7——D0 写入到RAM 中
LCD_Write_DATA(ZOON_CHAR[i*2 ]);
} 4
LCD_Write_Instruction(LCD_12864_DRAW_ON); //图形显示开
LCD_Write_Instruction(LCD_12864_BASIC_INSTRUCTION | LCD_12864_DRAW_ON); //设置为基本指令集
}
*/
void cls_lcd()
{
unsigned char i,j,k;
LCD_Write_Instruction(0x34);
LCD_Write_Instruction(0x36);
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
LCD_Write_Instruction(0x80+j);
if(i==0)
{
LCD_Write_Instruction(0x80);
}
else
{
LCD_Write_Instruction(0x88);
}
for(k=0;k<16;k++)
{
LCD_Write_DATA(0x00);
}
}
}
}
void xx_lcd(unsigned char xp,unsigned char yp)
{
unsigned char xd,rx,ry;
xd=xp/0x10; //计算横坐标
xp%=0x10; //计算位地址偏移
if(yp>31)
{//选下半屏
yp-=32;
yp+=128;
xd+=8;
xd+=128;
}
else
{//选上半屏
yp+=128;
xd+=128;
}
rx=xd;ry=yp;
LCD_Write_Instruction(ry);
LCD_Write_Instruction(rx);
LCD_Read_dat_I(&rx,&ry);
LCD_Write_Instruction(yp);
LCD_Write_Instruction(xd);
if(xp>8)
{
LCD_Write_DATA(rx);
LCD_Write_DATA(ry|(0x01<<(15-xp)));
}
else
{
LCD_Write_DATA(rx|(0x01<<(7-xp)));
LCD_Write_DATA(ry);
}
}
void LCD_Read_dat_I(unsigned char *xp,unsigned char *yp)
{
LCD_Write_Instruction(*yp); //竖坐标(0x80-0x9f)
LCD_Write_Instruction(*xp); //横坐标 上半屏(0x80-0x87) 下半屏(0x88-0x90)
LCD_Read_Data();
*xp=LCD_Read_Data();
*yp=LCD_Read_Data();
}
|