#include <iom128v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#include "LCD12864.h"
//*****LCD起始行列页定义********************
#define LCD_START_ROM 0XC0 //起始行
#define LCD_PAGE 0XB8 //页指令
#define LCD_COL 0X40 //列指令
#define LCD_OFF 0x3E //关显示
#define LCD_ON 0x3F //开显示
//*****液晶控制引脚*************************
#define E PC0
#define RW PC1
#define RS PC2
#define RST PC3
#define CS2 PC4
#define CS1 PC5
//*****液晶端口*****************************
#define LCD_PORT PORTA
#define LCD_DDR DDRA
#define LCD_PIN PINA
#define LCD_CTRL_PORT PORTC
#define LCD_CTRL_DDR DDRC
#define LCD_CTRL_PIN PINC
//*****液晶引脚操作定义*********************
#define RW_1() LCD_CTRL_PORT|=BIT(RW)
#define RW_0() LCD_CTRL_PORT&=~BIT(RW)
#define RS_1() LCD_CTRL_PORT|=BIT(RS)
#define RS_0() LCD_CTRL_PORT&=~BIT(RS)
#define E_1() LCD_CTRL_PORT|=BIT(E)
#define E_0() LCD_CTRL_PORT&=~BIT(E)
#define CS1_1() LCD_CTRL_PORT|=BIT(CS1)
#define CS1_0() LCD_CTRL_PORT&=~BIT(CS1)
#define CS1X-PIN ((LCD_CTRL_PIN)&0X05)
#define CS2_1() LCD_CTRL_PORT|=BIT(CS2)
#define CS2_0() LCD_CTRL_PORT&=~BIT(CS2)
#define CS2X-PIN LCD_CTRL_PIN&0X04
#define RST_1() LCD_CTRL_PORT|=BIT(RST)
#define RST_0() LCD_CTRL_PORT&=~BIT(RST)
unsigned char tab[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//一个字节中的8个位,此处要控制点,因此要处理八位中的一位。
//*****带显示汉字矩阵****************************
const uchar word_dot_matrix[]=
{/*-- 文字: 中 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xFC,0x08,0x08,0x08,0x08,0xFF,0x08,0x08,0x08,0x08,0xFC,0x08,0x00,0x00,
0x00,0x00,0x07,0x02,0x02,0x02,0x02,0xFF,0x02,0x02,0x02,0x02,0x07,0x00,0x00,0x00,
/*-- 文字: 华 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x20,0x10,0x08,0xFC,0x03,0x02,0x10,0x10,0x7F,0x88,0x88,0x84,0x86,0xE4,0x00,0x00,
0x00,0x04,0x04,0x05,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,
/*-- 文字: 人 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x01,0x06,0x0C,0x18,0x30,0x60,0x20,0x00,
/*-- 文字: 民 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x9E,0x80,0x80,0x00,0x00,
0x00,0x00,0xFF,0x40,0x20,0x10,0x00,0x00,0x03,0x0C,0x10,0x20,0x40,0xF0,0x00,0x00,
/*-- 文字: 共 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x10,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x00,0x00,
0x02,0x02,0x82,0x42,0x32,0x1F,0x0A,0x02,0x02,0x06,0x0B,0x32,0xE2,0x42,0x02,0x00,
/*-- 文字: 和 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x24,0x24,0xA4,0xFC,0x22,0x22,0x22,0x00,0xF8,0x08,0x08,0x08,0xF8,0x00,0x00,
0x10,0x08,0x06,0x01,0xFF,0x01,0x0E,0x04,0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,
/*-- 文字: 国 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0xFE,0x02,0x0A,0x8A,0x8A,0x8A,0xFA,0x8A,0x8A,0x8A,0x0A,0x02,0xFE,0x00,0x00,
0x00,0xFF,0x40,0x48,0x48,0x48,0x48,0x4F,0x48,0x49,0x4E,0x48,0x40,0xFF,0x00,0x00,};
//*****是否反相显示(白底黑字/黑底白字)****
uchar Reverse_Display=0;
//*****等待液晶就绪*************************
void wait_lcd_ready(void)//读状态时CS1,CS0一定要置0,否则无法读取,这是必须读CS1,CS0的当前状态
{
uchar st,cs1,cs2;
cs1 = ((LCD_CTRL_PIN)&BIT(CS1));
cs2 = ((LCD_CTRL_PIN)&BIT(CS2));
CS1_0();CS2_0();
do
{
LCD_DDR=0X00;
LCD_PORT=0xff;
RW_1(); delay_us(1); RS_0();E_1();
st=LCD_PIN;
E_0();
}while(st>>7);
LCD_CTRL_PORT|=cs1;
LCD_CTRL_PORT|=cs2;
}
//*****向LCD发送命令************************
void lcd_write_cmd(uchar cmd)
{
wait_lcd_ready();
LCD_DDR=0xff;
LCD_PORT=0xff;
RW_0();delay_us(1);RS_0();
LCD_PORT=cmd;
E_1();delay_us(1); E_0();
}
//*****向LCD发送数据************************
void lcd_write_data(uchar dat)
{
wait_lcd_ready();
LCD_DDR=0xff;
LCD_PORT=0xff;
RW_0();delay_us(1);RS_1();
if(!Reverse_Display)LCD_PORT=dat;else LCD_PORT=~dat;
E_1();delay_us(1); E_0();
}
//*****读数据************************
uchar lcd_read_data(void)
{
uchar dat=0;
wait_lcd_ready();
LCD_DDR = 0X00;
LCD_PORT=0xff;
RW_1();RS_1();E_1();delay_us(2);
E_0();
RW_1();RS_1();E_1();
dat = LCD_PIN;
delay_us(2);
E_0();
return dat;
}
//*****初始化LCD****************************
void lcd_init()
{
LCD_CTRL_PORT=0xff;
LCD_CTRL_DDR=0XFF;
LCD_DDR =0XFF;
LCD_PORT = 0XFF;
lcdsel(0);
lcd_write_cmd(0x3f);
delay_ms(15);
}
void lcdsel(uchar sel)//选择屏幕
{
switch(sel)
{
case 0: CS1_0();CS2_0();break; //选择两个屏幕
case 1: CS1_0();CS2_1();break; //选择左半屏幕
case 2: CS1_1();CS2_0();break; //选择右半屏幕
default:break;
}
}
void setx(uchar x)//页选择0~7
{
lcd_write_cmd(LCD_PAGE+x);
}
//LCD_COL是0x40,列初始地址,Y地址自动加一
void sety(uchar y)
{
lcd_write_cmd(LCD_COL+y);
}
//LCD_START_ROM是0xC0,起始行地址
void setz(uchar z)
{
lcd_write_cmd(LCD_START_ROM+z);
}
//清屏
void clearlcd()
{
int i,j;
lcdsel(0);//选择两个屏幕
for(j=0;j<8;j++)
{
lcd_write_cmd(LCD_ON);//开显示
setx(j); //从0到7选择每一页
lcd_write_cmd(LCD_COL); //写入列的初始地址,列地址会自动加1
setz(0);//DDEAM和屏幕的对应关系是DDRAM中第0行对应屏幕的第1行。
for (i=0;i<64;i++)
{
lcd_write_data(0x00);//选中了两个半屏,向两个半屏相同列号处同时写入0x00,清屏。
}
}
}
//左上角第一个点为原点,向下Y为轴,向右为X轴
//x:0~63~127 列号 y:0~63行号
//由于是由页和列控制的,因此此处给出的x必须转化为页,即除以8即可,由于是处理一个点,还要得到这一页的第几行,即对8求余
//flag : 0:擦除某个点, 1:显示某个点 ,其本质就是赋值,赋值0是清除一个点,赋值1是显示一个点
void dot(uchar x,uchar y,uchar flag)
{
uchar dat=0;
if(x<64)//x属于0~63就是左半屏幕
{
lcdsel(1);//选择左半屏幕
setx(y>>3); //y是行号,y属于0~63,除以8就得到当前的页
sety(x); //由列号设置列地址
dat = lcd_read_data();//读数
if(flag)//flag为1显示某个点,点显示为黑色的,液晶中每个字体的显示都是黑色的
{
dat = dat|(tab[y&7]);
}
else
{
dat = dat&(~(tab[y&7]));
}
sety(x);
lcd_write_data(dat);
}
else if(x<128)//右半屏幕
{
lcdsel(2);//选择右半屏幕
setx(y>>3);//设置页地址
sety(x-64);//列地址,右屏幕的列号是从0到63
dat = lcd_read_data();//读数据
if(flag)
{
dat=dat|(tab[y&7]);
}
else
{
dat=dat&(~(tab[y&7]));
}
sety(x-64);//右半屏幕的列地址也是0~63
lcd_write_data(dat);//写数据
}
}
//*****************************************
//通用显示函数common_show
//从第P页第L列开始显示第W个数据数据在r所指向的缓冲
//每个字节8位是垂直显示的,高位在下,低位在上
//每个8*128举行区域是一页
//整个LCD由64*64左半页和64*64的右半页构成
//*****************************************
void common_show(uchar P,uchar L,uchar W,uchar *r)
{
uchar i;
//显示在左半屏或右半屏
if(L<64)
{
CS1_1();CS2_0();
lcd_write_cmd(LCD_PAGE + P );
lcd_write_cmd(LCD_COL+ L );
//全部显示在左半屏
if((L+W)<64)
{
for(i=0;i<W;i++)lcd_write_data(r[i]);
}
else
{
//左半屏显示
for(i=0;i<(64-L);i++)lcd_write_data(r[i]);
//右半屏显示
CS1_0();CS2_1();
lcd_write_cmd(LCD_PAGE + P );
lcd_write_cmd(LCD_COL );
for(i=64 -L;i<W;i++)lcd_write_data(r[i]);
}
}
else
//全部显示在右半屏
{
CS1_0();CS2_1();
lcd_write_cmd(LCD_PAGE + P );
lcd_write_cmd(LCD_COL + L -64);
for(i=0;i<W;i++)lcd_write_data(r[i]);
}
}
//*****显示8*16点阵字符**************************
void diaplay_a_char_8x16(uchar P,uchar L,uchar *M)
{
common_show( P, L,8, M);
common_show( P+1, L,8, M+8);
}
//*****显示一个16*16的点阵汉字*******************
void diaplay_a_word_16x16(uchar P,uchar L,uchar *M)
{
common_show( P, L,16, M);
common_show( P+1, L,16, M+16);
}
//*****显示一串16*16的点阵汉字*******************
void diaplay_word_string_16x16(uchar P,uchar L,uchar C,uchar *M)
{
uchar i;
for(i=0;i<C;i++)
{
diaplay_a_word_16x16(P,L+i*16,M+i*32);
}
}
头文件
#ifndef _LCD12864_H
#define _LCD12864_H
#define uchar unsigned char
void setx(uchar x);
void sety(uchar y);
void setz(uchar z);
void clearlcd();
void dot(uchar x,uchar y,uchar flag);
void lcdsel(uchar sel);//选择屏幕
void lcd_write_data(uchar dat);
uchar lcd_read_data(void);
void wait_lcd_ready(void);
void lcd_write_cmd(uchar cmd);
void lcd_write_data(uchar dat);
void lcd_init(void);
void diaplay_a_char_8x16(uchar P,uchar L,uchar *M);
void diaplay_a_word_16x16(uchar P,uchar L,uchar *M);
void common_show(uchar P,uchar L,uchar W,uchar *r);
void diaplay_word_string_16x16(uchar P,uchar L,uchar C,uchar *M);
#endif |