/******************************************************************************
* LCD12864驱动程序
* 文 件 名:LCD12864
* 创建时间:2004年12月24日
* 创 建 人:胡勇刚
* Email: hygbeyond@163.com
******************************************************************************
* 这是根据我以前所做的C51的程序移值的,这个驱动已经在mega16L上运行成功了
* 这个驱动要注意的是:你用的mega系列的话,要注意和JTAG,ISP的冲突问题,如果
* 用的是C口作为数据口的话,就一定要关闭JTAG,记住如果要用JTAG作为仿真用的话
* 尽量的不要用这几个脚,否则就关闭JTAG(特别是作为I/O口)
* 我就是因为这个问题浪费了不少时间,主要的现象是插上LCD就不工作,
* 拔掉LCD就一切正常,好像应该是LCD触发了JTAG,从而使芯片进入仿真状态了
* 还有一点就是时钟频率,如果时钟频率高的话,需要修改DELAY_COUNT值
* 不然的话显示会有问题,这是因为12864本身的反应速度比较慢的原因
* 我现在所用的是mege16L 频率: 3.6864M
*
* 各位大虾如果有比这个驱动更优化的程序,请给我一份,就用上面的邮箱.谢谢了
*****************************************************************************/
/*
上述程序扩展 按(0-63,0-127)点定位的字符输出 ,画点,取反点,删除点。。。。
改进时间:2007年8月16日
作者:Mljda by ouravr.com
email:tigerxhy@vip.sina.com.cn
*/
/*
y0-----------127------->
x
0
|Byte0:0
|Byte0:1
|Byte0:2
|.
|.
|Byte0:8
|.
|.
|.
|.
|.
|Byte7
7
*/
/*2005-8-27 21:38 把以前的ICC下的LCD12864驱动重新写了一遍 又移植到GCC*/
#define __LCD_12864_H
#include "config.h"
#include <util\delay.h>
/***************************************************************************
#ifndef LCD_DI
#define LCD_DI PB0
#define LCD_RW PB1
#define LCD_EN PB2
#define LCD_CS1 PB3
#define LCD_CS2 PB4
#define LCD_DATA_IN PINC
#define LCD_DATA_OUT PORTC
#define LCD_DATA_DDR DDRC
#define LCD_CODE_OUT PORTB
#define LCD_DI_H LCD_CODE_OUT |= BIT(LCD_DI)
#define LCD_DI_L LCD_CODE_OUT &= ~BIT(LCD_DI)
#define LCD_RW_H LCD_CODE_OUT |= BIT(LCD_RW)
#define LCD_RW_L LCD_CODE_OUT &= ~BIT(LCD_RW)
#define LCD_EN_H LCD_CODE_OUT |= BIT(LCD_EN)
#define LCD_EN_L LCD_CODE_OUT &= ~BIT(LCD_EN)
#define LCD_CS1_H LCD_CODE_OUT |= BIT(LCD_CS1)
#define LCD_CS1_L LCD_CODE_OUT &= ~BIT(LCD_CS1)
#define LCD_CS2_H LCD_CODE_OUT |= BIT(LCD_CS2)
#define LCD_CS2_L LCD_CODE_OUT &= ~BIT(LCD_CS2)
#endif
***************************************************************************/
#define pre_page 0xb8
/*预设LCD页地址*/
#define pre_col 0x40
/*预设LCD列地址*/
#define DELAY_COUNT 200 /* 不连续动画显示只需要20左右就好了。如果要动画,要放慢每次显示,不然avr容易重启,可能是驱动不够 */
/*LCD延迟时间数*/
#define LCD_NOP() lcd_delay()
/*LCD延迟*/
#define LCD_STAY
#define _FLASH_SAMLL_
/*写入左屏的地址初始*/
#define addressL( page, col) wcodeL(pre_page+page);\
wcodeL(pre_col+col)
/*写入右屏的地址初始*/
#define addressR( page, col) wcodeR(pre_page+page);\
wcodeR(pre_col+col)
//#define lcd_Byte_clr(x,y) lcd_print(x,y,0) /* 字节清0 */
//#define lcd_Byte_clr(x,y) lcd_print(x,y,0xff) /* 字节填充 0xff*/
//*****************************************************************************
void lcd_delay(void); //延迟
void wcodeL(unsigned char left_code); //左屏写入命令
void wdataL(unsigned char left_data); //左屏写入数据
void wcodeR(unsigned char right_code); //右屏写入命令
void wdataR(unsigned char right_data); //右屏写入数据
void lcd_init(void); //LCD初始化
void lcd_clear_range(unsigned char range);
void Location_Pos(unsigned x,unsigned y);
void lcd_clear_left(void);
void lcd_print(unsigned char x,unsigned char y,unsigned char lcd_char);
void lcd_print88(unsigned char x,unsigned char y,const prog_uchar *lcd_char); //输出8*8的字符
void lcd_print1616(unsigned char x,unsigned char y,const prog_uchar *lcd_char); //输出16*16的汉字
void lcd_print816(unsigned char x,unsigned char y,const prog_uchar *lcd_char); //输出8*16的字符
void WriteData(unsigned char x,unsigned char y,unsigned char Wbyte);
unsigned char ReadData( unsigned char x, unsigned char y );/* 按字节读取液晶显示ram */
//***************************************************************************/
void wcodeL(unsigned char left_code)//左屏写指令
{
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |=((1<<LCD_EN) | (1<<LCD_RW) | (1<<LCD_CS2));
LCD_CODE_OUT &= ~((1<<LCD_DI) | (1<<LCD_CS1));
if(!(LCD_DATA_IN & 0x80))
{
break;
}
}
LCD_RW_L;
LCD_DATA_DDR = 0XFF;
LCD_DATA_OUT = left_code;
LCD_NOP();
LCD_EN_L;
LCD_DATA_OUT=0x00;/* 空闲时 输出0(关闭上拉)减少芯片输出电流 */
}
/******************************************************************************/
void wdataL(unsigned char left_data)//左屏写数据
{
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<LCD_EN) | (1<<LCD_RW) | (1<<LCD_CS2));
LCD_CODE_OUT &= ~((1<<LCD_DI) | (1<<LCD_CS1));
if(!(LCD_DATA_IN & 0x80))
{
break;
}
}
LCD_RW_L;
LCD_DI_H;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=left_data;
LCD_NOP();
LCD_EN_L;
LCD_DATA_OUT=0x00;/* 空闲时 输出0(关闭上拉)减少芯片输出电流 */
}
/******************************************************************************/
void wcodeR(unsigned char right_code)//右屏写指令
{
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<LCD_EN) | (1<<LCD_RW) | (1<<LCD_CS1));
LCD_CODE_OUT &= ~((1<<LCD_DI) | (1<<LCD_CS2));
if(!(LCD_DATA_IN & 0x80))
{
break;
}
}
LCD_RW_L;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=right_code;
LCD_NOP();
LCD_EN_L;
LCD_DATA_OUT=0x00;/* 空闲时 输出0(关闭上拉)减少芯片输出电流 */
}
/******************************************************************************/
void wdataR(unsigned char right_data)//写右屏数据
{
LCD_DATA_DDR=0X00;
while(1)
{
//如果液晶空闲开始写数据和命令
LCD_CODE_OUT |= ((1<<LCD_EN) | (1<<LCD_RW) | (1<<LCD_CS1));
LCD_CODE_OUT &= ~((1<<LCD_DI) | (1<<LCD_CS2));
if(!(LCD_DATA_IN & 0x80))
{
break;
}
}
LCD_RW_L;
LCD_DI_H;
LCD_DATA_DDR=0XFF;
LCD_DATA_OUT=right_data;
LCD_NOP();
LCD_EN_L;
LCD_DATA_OUT=0x00;/* 空闲时 输出0(关闭上拉)减少芯片输出电流 */
}
/******************************************************************************/
void lcd_init(void)
{
unsigned char x,y;
//设置显示起始行
wcodeL(0x0c0);
wcodeR(0x0c0);
//开显示
wcodeL(0x3f);
wcodeR(0x3f);
for(x=0;x<8;x++)
{
wcodeL(pre_page+x);
for(y=0;y<64;y++)
{
wcodeL(pre_col+y);
wdataL(0);
}
}
for(x=0;x<8;x++)
{
wcodeR(pre_page+x);
for(y=0;y<64;y++)
{
wcodeR(pre_col+y);
wdataR(0);
}
}
}
/******************************************************************************/
void lcd_clear_range(unsigned char range)
{
unsigned char x=0;
for(x=0;x<64;x++)
{
addressL(range,x);
wdataL(0);
}
}
/******************************************************************************/
void lcd_clear_left(void)
{
unsigned char x,y;
for(x=0;x<8;x++)
{
for(y=0;y<64;y++)
{
addressL(x,y);
wdataL(0);
}
}
}
/******************************************************************************/
void lcd_print(unsigned char x,unsigned char y,unsigned char lcd_char)
{
// if(x > 7)
//{
// x -= 8;
//}else
if(x < 8)/* 取值范围 0~7 */
{
if((128 > y) && (y > 63))/* 左屏 */
{
y -= 64;
addressL(x,y);
wdataL(lcd_char);
}else if(y>0 && y<64) /* 右屏 */
{
addressR(x,y);
wdataR(lcd_char);
}else if(y==0)
{ addressR(x,y);
wdataR(lcd_char);
}
}
}
/******************************************************************************/
void lcd_print88(unsigned char x,unsigned char y,const prog_uchar *lcd_char)//显示8*8字符
{
unsigned char i;
for(i=0;i<8;i++)
{
lcd_print(x,y+i,pgm_read_byte(lcd_char++));
}
}
/*********