/*******************************************************************************
* 描述: *
* 12864标准字库液晶演示 数据p0,控制p2 *
********************************************************************************/
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/************* 12864LCD引脚定义 *************/
#define LCD_data P0 //数据口
sbit LCD_RS = P2^6; //寄存器选择输入
sbit LCD_RW = P2^5; //液晶读/写控制
sbit LCD_EN = P2^7; //液晶使能控制
sbit LCD_PSB = P3^2; //串/并方式控制
sbit LCD_RST = P3^7; //液晶复位端口
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar count=0;
unsigned char read_datah;
unsigned char read_datal;
/*******************************************************************/
/* */
/* 延时函数 */
/* */
/*******************************************************************/
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<150;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/*******************************************************************/
/* */
/* 延时函数 */
/* */
/*******************************************************************/
void delay1(int ms)
{
while(ms--)
{
uchar y;
for(y=0;y<100;y++) ;
}
}
/*******************************************************************/
/* */
/*检查LCD忙状态 */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */
/* */
/*******************************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*******************************************************************/
/* */
/*写指令数据到LCD */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */
/* */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*写显示数据到LCD */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */
/* */
/*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*读显示数据 */
/* */
/* */
/*******************************************************************/
uchar lcd_read_data()
{
uchar read_data;
LCD_data = 0xff;
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
read_data = P0;
LCD_EN = 0;
delayNOP();
return(read_data);
}
/*******************************************************************/
/* */
/* LCD初始化设定 */
/* */
/*******************************************************************/
void lcd_init()
{
LCD_PSB = 1; //并口方式
LCD_RST = 0; //液晶复位
delay(3);
LCD_RST = 1;
delay(3);
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //显示开,关光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
/*********************************************************
* *
* 清屏函数 *
* *
*********************************************************/
void clr_screen()
{
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x01); //清屏
delay(5);
}
/*********************************************************
* *
* 打点函数 *
* *
*********************************************************/
void lcd_set_dot(unsigned char x, unsigned char y)
{
unsigned char x_byte, x_bit; //在横坐标的哪一个字节,哪一个位
unsigned char y_byte, y_bit;
unsigned char tmph, tmpl; //定义两个临时变量,用于存放读出来的数据
x &= 0x7F; //防止横坐标x超过127
y &= 0x3F; //防止纵坐标y超过63
x_byte = x / 16; //算出它在哪一个字节(地址),注意一个地址是16位的
x_bit = x&0x0F; //算出它在哪一个位
y_byte = y /32; //y是没在哪个字节这个说法的,这里只是确定它在上半屏还是下半屏,0:上半屏 1:下半屏
y_bit = y&0x1F; //y_bit确定它是在第几行
lcd_wcmd(0x34); //扩展指令集
lcd_wcmd(0x34); //绘图显示关闭
lcd_wcmd(0x80 + y_bit); //先写垂直地址(最高位必须为1)
lcd_wcmd(0x80 + x_byte + 8 * y_byte); //水平坐标,下半屏的水平坐标起始地址为0x88,(+8*y_byte)就是用来确定在上半屏还是下半屏
lcd_read_data(); //先空读一次
tmph = lcd_read_data(); //读高位
tmpl = lcd_read_data(); //读低位
lcd_wcmd(0x80 + y_bit); //读操作会改变AC,所以重新设置一次
lcd_wcmd(0x80 + x_byte + 8 * y_byte);
if (x_bit < 8) //如果x_bit位数小于8
{
lcd_wdat(tmph | (0x01 << (7 - x_bit))); //写高字节。因为坐标是从左向右的,而GDRAM高位在左,低位在右
lcd_wdat(tmpl); //原数据送回
}
else
{
lcd_wdat(tmph); //原数据送回
lcd_wdat(tmpl | (0x01 << (15 - x_bit)));
}
lcd_wcmd(0x36); //打开绘图显示
lcd_wcmd(0x32); //回到基本指令集,毕竟ST7920是以字符为主的
return ;
}
/********************************************************************************************
//画两点(x1,y1),(x1,y2)所确定的垂直直线 Draw_vertical_line( unsigned char x1,unsigned char y1,
unsigned char y2);
/**************************************