2006-6-17 14:28:00
LCD12864驱动程序
/******************************************************************************
/* LCD12864驱动程序
/* 文 件 名:LCD12864
/* 创建时间:2006年03月24日
/* 创 建 人:fox_futing
/* Email: ip67077@yahoo.com
//******************************************************************************
/* 这是根据我以前所做的C51的程序移值的,这个驱动已经在mega16L上运行成功了
/* 这个驱动要注意的是:你用的mega系列的话,要注意和JTAG,ISP的冲突问题,如果
/* 用的是C口作为数据口的话,就一定要关闭JTAG,记住如果要用JTAG作为仿真用的话
/* 尽量的不要用这几个脚,否则就关闭JTAG(特别是作为I/O口)
/* 我就是因为这个问题浪费了不少时间,主要的现象是插上LCD就不工作,
/* 拔掉LCD就一切正常,好像应该是LCD触发了JTAG,从而使芯片进入仿真状态了
/* 还有一点就是时钟频率,如果时钟频率高的话,需要修改DELAY_COUNT值
/* 不然的话显示会有问题,这是因为12864本身的反应速度比较慢的原因
/* 我现在所用的是mege16L 频率: 3.6864M
/*
/* 各位大虾如果有比这个驱动更优化的程序,请给我一份,就用上面的邮箱.谢谢了
//*****************************************************************************/
//#i nclude "config.h"
//#i nclude <iom16v.h>
//#i nclude <macros.h>
//****************************************************************************
#ifndef uchar
#define uchar unsigned char
#define uint unsigned int
#endif
//***************************************************************************/
//***************************************************************************
#ifndef DI
#define DI PD7
#define EN PD6
#define RW PD5
#define CS1 PD4
#define CS2 PD3
#define DI_H PORTD |= BIT(DI)
#define DI_L PORTD &=~BIT(DI)
#define RW_H PORTD |= BIT(RW)
#define RW_L PORTD &=~BIT(RW)
#define EN_H PORTD |= BIT(EN)
#define EN_L PORTD &=~BIT(EN)
#define CS1_H PORTD |= BIT(CS1)
#define CS1_L PORTD &=~BIT(CS1)
#define CS2_H PORTD |= BIT(CS2)
#define CS2_L PORTD &=~BIT(CS2)
#define LCD_DATA_IN PINC
#define LCD_DATA_OUT PORTC
#define LCD_DATA_DDR DDRC
#define LCD_CODE_OUT PORTD
#define LCD_CODE_DDR DDRD
#endif
//****************************************************************************/
#define pre_page 0xb8 //预设LCD页地址
#define pre_col 0x40 //预设LCD列地址
#define DELAY_COUNT 10 //LCD延迟时间数
#define LCD_NOP lcd_delay() //延迟
//*****************************************************************************
void lcd_delay(void); //延迟
void wcodeL(uchar left_code); //左屏写入命令
void wdataL(uchar left_data); //左屏写入数据
void wcodeR(uchar right_code); //右屏写入命令
void wdataR(uchar right_data); //右屏写入数据
void lcd_init(void); //LCD初始化
void clear(uchar symbol); //用symbol填充整屏
void addressL(uchar page,uchar col); //写入左屏的地址初始
void addressR(uchar page,uchar col); //写入右屏的地址初始
void lcd_print(uchar x,uchar y,const uchar *lcd_char); //输出8*8的字符
void hanzi_print(uchar x,uchar y,const uchar *lcd_char);//输出16*16的汉字
void lcd_write(uchar x,uchar y,const uchar *lcd_char); //输出8*16的字符
//***************************************************************************/
//--------------------------------------------------------------------------------
void wcodeL(uchar left_code)//左屏写指令
{
uchar status;
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |=((1<<EN) | (1<<RW) | (1<<CS2));
LCD_CODE_OUT &= ~((1<<DI) | (1<<CS1));
status=LCD_DATA_IN;
status&=0x80;
if(status==0)
{
break;
}
}
RW_L;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=left_code;
LCD_NOP;
EN_L;
}
//---------------------------------------------------------------------------------
void wdataL(uchar left_data)//左屏写数据
{
uchar status;
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<EN) | (1<<RW) | (1<<CS2));
LCD_CODE_OUT &= ~((1<<DI) | (1<<CS1));
status=LCD_DATA_IN;
status&=0x80;
if(status==0)
{
break;
}
}
RW_L;
DI_H;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=left_data;
LCD_NOP;
EN_L;
}
//----------------------------------------------------------------------------------
void wcodeR(uchar right_code)//右屏写指令
{
uchar status;
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<EN) | (1<<RW) | (1<<CS1));
LCD_CODE_OUT &= ~((1<<DI) | (1<<CS2));
status=LCD_DATA_IN;
status&=0x80;
if(status==0)
{
break;
}
}
RW_L;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=right_code;
LCD_NOP;
EN_L;
}
//-------------------------------------------------------------------------------
void wdataR(uchar right_data)//写右屏数据
{
uchar status;
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<EN) | (1<<RW) | (1<<CS1));
LCD_CODE_OUT &= ~((1<<DI) | (1<<CS2));
status=LCD_DATA_IN;
status&=0x80;
if(status==0)
{
break;
}
}
RW_L;
DI_H;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=right_data;
LCD_NOP;
EN_L;
}
//----------------------------------------------------------------------------------
void lcd_init(void)
{
//设置显示起始行
wcodeL(0x0c0);
wcodeR(0x0c0);
//开显示
wcodeL(0x3f);
wcodeR(0x3f);
}
//----------------------------------------------------------------------------------
void clear(uchar symbol)
{
uchar x=0;
uchar y=0;
for(x=0;x<8;x++)
{
wcodeL(pre_page+x);
for(y=0;y<64;y++)
{
wcodeL(pre_col+y);
wdataL(symbol);
}
}
for(x=0;x<8;x++)
{
wcodeR(pre_page+x);
for(y=0;y<64;y++)
{
wcodeR(pre_col+y);
wdataR(symbol);
}
}
}
//-------------------------------------------------------------------------------
void addressL(uchar page,uchar col)
{
wcodeL(pre_page+page);
wcodeL(pre_col+col);
}
//-------------------------------------------------------------------------------
void addressR(uchar page,uchar col)
{
wcodeR(pre_page+page);
wcodeR(pre_col+col);
}
//--------------------------------------------------------------------------------
void lcd_print(uchar x,uchar y,const uchar *lcd_char)//显示8*8字符
{
uchar i;
if(x>7)
{
x=7;
}
if(y>63)
{
y=y-64;
for(i=0;i<8;i++)
{
addressL(x,y+i);
wdataL(*lcd_char++);
}
}else if(y<56)
{
for(i=0;i<8;i++)
{
addressR(x,y+i);
wdataR(*lcd_char++);
}
}else
{
for(i=0;i<(64-y);i++)
{
addressR(x,y+i);
wdataR(*lcd_char++);
}
for(i=0;i<(y-56);i++)
{
addressL(x,i);
wdataL(*lcd_char++);
}
}
}
//--------------------------------------------------------------------------------
void hanzi_print(uchar x,uchar y,const uchar *lcd_char)//显示16*16的汉字
{
uchar i,j;
if(x>6)
x=6;
if(y>64)
{
y-=64;
for(i=0;i<2;i++)
{
for(j=0;j<16;j++)
{
addressL(x+i,y+j);
wdataL(*lcd_char++);
}
}
}else if(y<48)
{
for(i=0;i<2;i++)
{
for(j=0;j<16;j++)
{
addressR(x+i,y+j);
wdataR(*lcd_char++);
}
}
}else
{
for(i=0;i<2;i++)
{
for(j=0;j<(64-y);j++)
{
addressR(x+i,y+j);
wdataR(*lcd_char++);
}
for(j=0;j<(y-48);j++)
{
addressL(x+i,j);
wdataL(*lcd_char++);
}
}
}
}
//-----------------------------------------------------------------
void lcd_write(uchar x,uchar y,const uchar *lcd_char)//显示8*16字符
{
uchar i,j;
if(x>6)
{
x=6;
}
if(y>63)
{
y=y-64;
for(j=0;j<2;j++)
{
for(i=0;i<8;i++)
{
addressL(x+j,y+i);
wdataL(*lcd_char++);
}
}
}else
{
for(j=0;j<2;j++)
{
for(i=0;i<8;i++)
{
addressR(x+j,y+i);
wdataR(*lcd_char++);
}
}
}
}
//---------------------------------------------------------------------
void lcd_delay(void)
{
uchar i = DELAY_COUNT;
while(i--);
}