#include <16F877A.h>
#device adc=8
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD
#use delay(clock=11059200)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
struct lcd_con_bus {
int1 unused_0;
int1 unused_1;
int1 unused_2;
int1 wr;
int1 rd;
int1 cd;
int1 reset;
int1 unused_7;
} lcd;
#define set_tris_lcd(x) set_tris_c(x)
#byte lcd = 0x07
#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define BS 0x08
#define CR 0x0D
#define LF 0x0A
#define DLE 0x10
#define ETB 0x17
#define SPACE 0x20
#define COMMA 0x2C
// T6963C 命令定义
#define LC_CUR_POS 0x21 // 光标位置设置
#define LC_CGR_POS 0x22 // CGRAM偏置地址设置
#define LC_ADD_POS 0x24 // 地址指针位置
#define LC_TXT_STP 0x40 // 文本区首址
#define LC_TXT_WID 0x41 // 文本区宽度
#define LC_GRH_STP 0x42 // 图形区首址
#define LC_GRH_WID 0x43 // 图形区宽度
#define LC_MOD_OR 0x80 // 显示方式:逻辑“或”
#define LC_MOD_XOR0x81 // 显示方式:逻辑“异或”
#define LC_MOD_AND0x82 // 显示方式:逻辑“与”
#define LC_MOD_TCH 0x83 // 显示方式:文本特征
#define LC_DIS_SW 0x90 // 显示开关:D0=1/0:光标闪烁启用/禁用;
// D1=1/0:光标显示启用/禁用;
// D2=1/0:文本显示启用/禁用;
// D3=1/0:图形显示启用/禁用;
#define LC_CUR_SHP 0xA0 // 光标形状选择:0xA0-0xA7 表示光标占的行数
#define LC_AUT_WR 0xB0 // 自动写设置
#define LC_AUT_RD 0xB1 // 自动读设置
#define LC_AUT_OVR 0xB2 // 自动读/写结束
#define LC_INC_WR 0xC0 // 数据一次写,地址加 1
#define LC_INC_RD 0xC1 // 数据一次读,地址加 1
#define LC_DEC_WR 0xC2 // 数据一次写,地址减 1
#define LC_DEC_RD 0xC3 // 数据一次读,地址减 1
#define LC_NOC_WR 0xC4 // 数据一次写,地址不变
#define LC_NOC_RD 0xC5 // 数据一次读,地址不变
#define LC_SCN_RD 0xE0 // 屏读
#define LC_SCN_CP 0xE8 // 屏拷贝
#define LC_BIT_OP 0xF0 // 位操作:D0-D2:定义 D0-D7 位;D3:1 置位;0:清除
int8 CurRow,CurCol; // 当前行、列存储,行高 16 点,列宽 8 点
const int8 zifu[]={
0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xD6,0xD6, // -0-0
0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18, // -1-1
0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30, // -2-2
0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06, // -3-3
0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE, // -4-4
0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x0E, // -5-5
0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6, // -6-6
0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18, // -7-7
0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6, // -8-8
0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06, // -9-9
0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE, // -A-10
0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6, // -V-11
0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // -.-12
0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68, // -F-13
0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E, // -+-14
0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE, // ---15
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
const int8 tuxing[]={};
const int8 hanzi0[]={
0x01,0xF0,0x21,0x10,0x11,0x10,0x11,0x10,//0"设",
0x01,0x10,0x02,0x0E,0xF4,0x00,0x13,0xF8,
0x11,0x08,0x11,0x10,0x10,0x90,0x10,0xA0,
0x14,0x40,0x18,0xB0,0x13,0x0E,0x0C,0x04,
0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,//1"定",
0x80,0x24,0x1F,0xF0,0x01,0x00,0x01,0x00,
0x11,0x20,0x11,0xF0,0x11,0x00,0x11,0x00,
0x11,0x00,0x29,0x06,0x47,0xFC,0x80,0x00
0x02,0x00,0x01,0x00,0x7F,0xFE,0x48,0x02,//2"实",
0x86,0x84,0x02,0x80,0x10,0x80,0x0C,0x80,
0x04,0x84,0xFF,0xFE,0x01,0x00,0x01,0x40,
0x02,0x20,0x04,0x10,0x18,0x0C,0x60,0x04,
0x00,0x08,0x7D,0xFC,0x44,0x00,0x48,0x00,//3"际",
0x48,0x00,0x50,0x04,0x4B,0xFE,0x48,0x20,
0x44,0x20,0x44,0xA8,0x44,0xA4,0x69,0x22,
0x52,0x22,0x40,0x20,0x40,0xA0,0x40,0x40,
0x02,0x00,0x02,0x00,0x02,0x10,0x7F,0xF8,//4"电",
0x42,0x10,0x42,0x10,0x7F,0xF0,0x42,0x10,
0x42,0x10,0x7F,0xF0,0x42,0x10,0x02,0x00,
0x02,0x04,0x02,0x04,0x01,0xFC,0x00,0x00,
0x00,0x08,0x3F,0xFC,0x20,0x80,0x20,0x80,//5"压",
0x20,0x80,0x20,0x80,0x20,0x88,0x2F,0xFC,
0x20,0x80,0x20,0xA0,0x20,0x98,0x20,0x88,
0x40,0x80,0x40,0x84,0x9F,0xFE,0x00,0x00
0x00,0x80,0x40,0x48,0x37,0xFC,0x10,0x40,//6"流",
0x80,0x90,0x61,0x08,0x27,0xFC,0x08,0x04,
0x11,0x50,0x21,0x50,0xE1,0x50,0x21,0x50,
0x21,0x52,0x21,0x52,0x22,0x4E,0x24,0x40
};
const int8 hanzi1[]={
0x00,0x00,0x22,0x08,0x11,0x10,0x10,0xA0,//0"说",
0x03,0xF8,0x02,0x08,0xF2,0x08,0x12,0x08,
0x13,0xF8,0x12,0xA8,0x10,0xA0,0x10,0xA0,
0x15,0x22,0x19,0x22,0x12,0x1E,0x04,0x00,
0x00,0x04,0x04,0xFE,0x7E,0x84,0x44,0x84,//1"明",
0x44,0x84,0x44,0xFC,0x7C,0x84,0x44,0x84,
0x44,0x84,0x44,0xFC,0x7C,0x84,0x44,0x84,
0x01,0x04,0x01,0x04,0x02,0x14,0x04,0x08
0x10,0x40,0x10,0x20,0x10,0x00,0x13,0xFE,//2"按",
0xFA,0x02,0x14,0x44,0x10,0x40,0x3F,0xFE,
0xD0,0x88,0x10,0x88,0x11,0x08,0x10,0x90,
0x10,0x60,0x10,0x50,0x50,0x8C,0x23,0x04
0x20,0x10,0x27,0x10,0x39,0x7C,0x41,0x14,//3"键",
0x82,0xFE,0x7A,0x14,0x24,0x7C,0x27,0x10,
0xF9,0x7C,0x21,0x10,0x25,0x14,0x22,0xFE,
0x2A,0x10,0x35,0x10,0x28,0x96,0x00,0x7C
};
include "D:\GE LI HUI\16F877A\240X128LCD\main.h"
// 状态位判断忙否
void lcd_busy(int8 i)
{
int8 m=0x00;
set_tris_b(0xff);
lcd.cd=1;
lcd.rd=1;
lcd.wr=1;
lcd.rd=0;
while((m&i)==0)
{
m=input_b();
}
lcd.rd=1;
set_tris_b(0x00);
}
// 状态位 STA1,STA0 判断
void lcd_busy01()
{
lcd_busy(1);
lcd_busy(2);
}
// 写数据的函数
void lcd_wr_dat(int8 dat)
{
lcd_busy01();
lcd.cd=0;
output_b(dat);
lcd.wr=0;
delay_us(10);
lcd.wr=1;
}
// 写指令的函数
void lcd_wr_cmd(int8 cmd)
{
lcd_busy01();
output_b(cmd);
lcd.wr=0;
delay_us(10);
lcd.wr=1;
}
// 自动写数据
void lcd_auto_wr(int8 dat)
{
lcd_busy(8);
lcd.cd=0;
output_b(dat);
lcd.wr=0;
delay_us(10);
lcd.wr=1;
}
// 读数据的函数
int8 lcd_rd_dat()
{
int8 dat;
lcd_busy01();
lcd.cd=0;
lcd.rd=0;
delay_us(10);
dat=input_b();
lcd.rd=1;
return dat;
}
// 写双参数的函数
void lcd_set_2(int8 cmd,int8 da1,int8 da2)
{
lcd_wr_dat(da1);
lcd_wr_dat(da2);
lcd_wr_cmd(cmd);
}
// 写16位数据的函数
void lcd_set16(int8 cmd,int16 dat)
{
int dal,dah;
dal=dat;
dah=dat>>8;
lcd_wr_dat(dal);
lcd_wr_dat(dah);
lcd_wr_cmd(cmd);
}
// 写单参数的函数
void lcd_set_1(int8 cmd,int8 da1)
{
lcd_wr_dat(da1);
lcd_wr_cmd(cmd);
}
// 写无参数的函数
void lcd_set_0(int8 cmd)
{
lcd_wr_cmd(cmd);
}
// 设置当前地址
void lcd_setpos(int8 row,int8 col)
{
int8 ipos;
ipos=row*30+col;
lcd_set_2(LC_ADD_POS,ipos&0xff,ipos/256);
CurRow=row;
CurCol=col;
}
// 设置当前显示行、列
void cursor(int8 Row, int8 Col)
{
lcd_setpos(row*16,col);
}
// 清屏
void lcd_clr()
{
int16 i;
lcd_set_2(LC_ADD_POS,0x00,0x00);
lcd_set_0(LC_AUT_WR);
for(i=0;i<128*30;i++)
{
lcd_auto_wr(0x00);
}
lcd_set_0(LC_AUT_OVR);
lcd_set_2(LC_ADD_POS,0x00,0x00);
}
//划横线程序
void lcd_heng(int16 hang)
{
int8 i;
for(i=0;i<30;i++)
{
lcd_set16(LC_ADD_POS,hang*30+i);
lcd_set_1(LC_NOC_WR,0xff);
}
}
//显示8x16字符 x表示横 y表示纵
void lcd0_zifu8x16(int16 x,int16 y,int16 n)
{
int16 i;
int16 addr;
addr=x+(y*30*16)+(y+1)*90;
for(i=0;i<16;i++)
{
lcd_set16(LC_ADD_POS,addr+i*30+30);
lcd_set_1(LC_NOC_WR,zifu[i+n*16]);
}
}
void lcd1_zifu8x16(int16 x,int16 y,int16 n)
{
int16 i;
int16 addr;
addr=x+(y*30*16)+(y+1)*90;
for(i=0;i<16;i++)
{
lcd_set16(LC_ADD_POS,addr+i*30+210);
lcd_set_1(LC_NOC_WR,zifu[i+n*16]);
}
}
//显示16x16汉字
void lcd0_hanzi16x16(int16 x,int16 y,int16 n)
{
int16 i;
int16 addr;
addr=x+(y*30*16)+(y+1)*90;
// addr=x*2+y*570+90;
for(i=0;i<16;i++)
{
lcd_set16(LC_ADD_POS,addr+i*30);
lcd_set_1(LC_INC_WR,hanzi0[i*2+n*32]);
lcd_set_1(LC_INC_WR,hanzi0[i*2+n*32+1]);
}
}
void lcd1_hanzi16x16(int16 x,int16 y,int16 n)
{
int16 i;
int16 addr;
addr=x+(y*30*16)+(y+1)*90;
// addr=x*2+y*570+90;
for(i=0;i<16;i++)
{
lcd_set16(LC_ADD_POS,addr+i*30+150);
lcd_set_1(LC_INC_WR,hanzi1[i*2+n*32]);
lcd_set_1(LC_INC_WR,hanzi1[i*2+n*32+1]);
}
}
//显示24x24汉字
void lcd_hanzi24x24(int16 x,int16 y,int16 n)
{
int16 i;
int16 addr;
addr=x*3+(y*30*24);
for(i=0;i<24;i++)
{
lcd_set16(LC_ADD_POS,addr+i*30);
lcd_set_1(LC_INC_WR,hanzi0[i*3+n*72]);
lcd_set_1(LC_INC_WR,hanzi0[i*3+n*72+1]);
lcd_set_1(LC_INC_WR,hanzi0[i*3+n*72+2]);
}
}
//图形全屏显示240*128
void lcd_tu_fu()
{
int16 i;
int16 m=0x0f00;
lcd_set_2(LC_ADD_POS,0x00,0x00);
lcd_set_0(LC_AUT_WR);
for(i=0;i<m;i++)
{
lcd_auto_wr(tuxing);
}
lcd_set_0(LC_AUT_OVR);
lcd_set_2(LC_ADD_POS,0x00,0x00);
}
//第一行显示
void lcd_diyi()
{
lcd_heng(0);
lcd_heng(1);
lcd0_hanzi16x16(2,0,0);//设
lcd0_hanzi16x16(4,0,1);//定
lcd0_hanzi16x16(6,0,4);//电
lcd0_hanzi16x16(8,0,5);//压
lcd0_zifu8x16(19,0,11);//V
lcd_heng(20);
lcd0_hanzi16x16(2,1,2);//实
lcd0_hanzi16x16(4,1,3);//际
lcd0_hanzi16x16(6,1,4);//电
lcd0_hanzi16x16(8,1,5);//压
lcd0_zifu8x16(19,1,11);//V
lcd_heng(39);
lcd0_hanzi16x16(2,2,2);//实
lcd0_hanzi16x16(4,2,3);//际
lcd0_hanzi16x16(6,2,4);//电
lcd0_hanzi16x16(8,2,6);//流
lcd0_zifu8x16(19,2,10);//A
lcd_heng(58);
lcd_heng(59);
lcd_heng(60);
lcd_heng(125);
lcd_heng(126);
lcd_heng(127);
}
void shuoming()
{
lcd1_hanzi16x16(2,3,0);//说
lcd1_hanzi16x16(4,3,1);//明
lcd1_hanzi16x16(2,4,2);//按
lcd1_zifu8x16(4,4,13);//F
lcd1_zifu8x16(5,4,1);//1
lcd1_hanzi16x16(6,4,3);//键
lcd1_zifu8x16(8,4,14);//+
lcd1_zifu8x16(9,4,1);//1
lcd1_zifu8x16(10,4,0);//0
lcd1_zifu8x16(11,4,11);//V
lcd1_hanzi16x16(16,4,2);//按
lcd1_zifu8x16(18,4,13);//F
lcd1_zifu8x16(19,4,2);//2
lcd1_hanzi16x16(20,4,3);//键
lcd1_zifu8x16(22,4,15);//-
lcd1_zifu8x16(23,4,1);//1
lcd1_zifu8x16(24,4,0);//0
lcd1_zifu8x16(25,4,11);//V
lcd1_hanzi16x16(2,5,2);//按
lcd1_zifu8x16(4,5,13);//F
lcd1_zifu8x16(5,5,3);//3
lcd1_hanzi16x16(6,5,3);//键
lcd1_zifu8x16(8,5,14);//+
lcd1_zifu8x16(9,5,1);//1
lcd1_zifu8x16(10,5,0);//0
lcd1_zifu8x16(11,5,0);//0
lcd1_zifu8x16(12,5,11);//V
lcd1_hanzi16x16(16,5,2);//按
lcd1_zifu8x16(18,5,0);//0
lcd1_hanzi16x16(19,5,3);//键
lcd1_zifu8x16(21,5,15);//-
lcd1_zifu8x16(22,5,1);//1
lcd1_zifu8x16(23,5,0);//0
lcd1_zifu8x16(24,5,0);//0
lcd1_zifu8x16(25,5,11);//V
}
//在特定的位置显示电流
void shuzi_I(int16 dat,int8 hang)
{
int8 dian0=0,dian1=0,dian2=0,dian3=0;
dian0=dat/1000;
dian1=(dat%1000)/100;
dian2=(dat%100)/10;
dian3=(dat%10);
lcd0_zifu8x16(13,hang,dian0);
lcd0_zifu8x16(14,hang,12);
lcd0_zifu8x16(15,hang,dian1);
lcd0_zifu8x16(16,hang,dian2);
lcd0_zifu8x16(17,hang,dian3);
}
//在特定的位置显示电压
void shuzi_V(int16 dat,int8 hang)
{
int8 qia=0,bai=0,shi=0,gee=0;
qia=dat/1000;
bai=(dat%1000)/100;
shi=(dat%100)/10;
gee=(dat%10);
lcd0_zifu8x16(13,hang,0);
lcd0_zifu8x16(14,hang,qia);
lcd0_zifu8x16(15,hang,bai);
lcd0_zifu8x16(16,hang,shi);
lcd0_zifu8x16(17,hang,gee);
}
// LCM 初始化
void lcd_init()
{
lcd_set_2(LC_TXT_STP,0x00,0x00);
lcd_set_2(LC_TXT_WID,0x1e,0x00);
lcd_set_2(LC_GRH_STP,0x00,0x00);
lcd_set_2(LC_GRH_WID,0x1e,0x00);
lcd_set_0(LC_CUR_SHP|0x00);
lcd_set_0(LC_MOD_OR);
lcd_set_0(LC_DIS_SW|0x08);
}
void main()
{
int16 a=0;
set_tris_b(0x00);
set_tris_c(0x07);
lcd.reset=0;
lcd.reset=1;
lcd_init();
lcd_clr();
// lcd_zifu8x8(0,10,2);
//!// lcd_tu_fu();
lcd_diyi();
shuzi_V(2154,0);
shuzi_V(2154,1);
shuzi_I(1234,2);
shuoming();
// lcd_hanzi16x16(0,0,0);
// lcd_hanzi24x24(0,0,0);
while(1)
{
shuzi_V(a,0);
shuzi_V(a,1);
a++;
delay_ms(1);
}
}
80C196单片机与MGLS12864液晶显示模块的接口应用源程序
下面给出了显示8?6点阵字符和16?6点阵汉字所必须的一些基本子程序。其中要用到的一些寄存器有:
PAGADD EQU 30H ;页地址寄存器
ROW EQU 31H ;列地址寄存器
COMD EQU 32H ;指令寄存器
DREG EQU 33H ;数据寄存器
CWADD EQU 34H ;写指令代码地址
CRADDL EQU 35H ;读状态字地址(左)
DWADD EQU 36H ;写显示数据地址
DRADDL EQU 37H ;读显示数据地址(左)
CRADDR EQU 38H ;读状态字地址(右)
DRADDR EQU 39H ;读显示数据地址(右)
COUNT EQU 3AH ;写入字节计数寄存器
NUMBER EQU 3BH ;显示页数寄存器
TABLE EQU 3CH ;字模首地址寄存器
驱动子程序
写指令子程序(左)
WIL: LDB AL,0A002H[0] ;读LCD状态字
JBS AL,7,WIL ;判断BUSY状态
STB CWADD,0A000H[0] ;写命令字到LCD
RET
写数据子程序(左)
WDL: LDB AL,0A002H[0] ;读LCD状态字
JBS AL,7,WDL ;判断BUSY状态
STB DREG,0A001H[0] ;写数据到LCD
RET
写指令子程序(右)
WIR: LDB AL,0B002H[0] ;读LCD状态字
JBS AL,7,WIR ;判断BUSY状态
STB CWADD,0B000H[0] ;写命令字到LCD
RET
写数据子程序(右)
WDR: LDB AL,0B002H[0] ;读LCD状态字
JBS AL,7,WDR ;判断BUSY状态
STB DREG,0B001H[0] ;写数据到LCD
RET
清屏子程序
CLEAR: LDB NUMBER,#08H ;总共要清8页
LDB PAGADD,#0B8H ;页首地址
CLR1: LDB ROW,#40h ;行首地址
CLR2: LDB CWADD,PAGADD
LCALL WIL ;左区写指令
LCALL WIR ;右区写指令
LDB CWADD,ROW
LCALL WIL
LCALL WIR
LDB DREG,#00H
LCALL WDL ;左区写数据
LCALL WDR ;右区写数据
INCB ROW ;转下一列
JBC ROW,7,CLR2 ;该页未清完转CLEAR
INCB PAGADD ;清完该页转下一页
DJNZ NUMBER,CLR1 ;全部页清完否?
RET
初始化子程序
INITIATE:
LDB AL,#3FH ;开显示
STB AL,CWADD
LCALL WIL
LCALL WIR
LDB AL,#0C0H ;显示起始行为第0行
STB AL,CWADD
LCALL WIL
LCALL WIR
RET
写入8?6点阵字符和16?6汉字的子程序
在写入8?6点阵字符和16?6点阵汉字时,右区和左区写入方式完全一样,仅仅是写入地址不同而已,所以这里只给出左区的子程序。汉字字模的提取使用了北京清华篷远科贸公司提供的提取汉字软件PICKHZB.EXE。要注意的是,由于HD61202U显示存储器的特性,不能将计算机内的汉字库提出直接使用,需要将其旋转90昂笤傩慈搿?br/>写入8?6点阵字符子程序(左区)
WZIFUL: LDB COUNT,#00H
LOOP1: LDB CWADD,PAGADD
ORB CWADD,#0B8H
LCALL WIL ;写入页
LDB CWADD,ROW
ORB CWADD,#40H
ANDB CWADD,#7FH
LOOP2: LCALL WIL ;写入列
LDB DREG,0000H[TABLE] ;取字模
LCALL WDL ;写入数据
INCB COUNT
INC TABLE
INCB CWADD
CMPB COUNT,#10H ;写完16个字节?
JE LOOP3
CMPB COUNT,#0008H ;写完8个字节?
JNE LOOP2
INCB PAGADD
JMP LOOP1
LOOP3: RET
写入16?6点阵汉字子程序(左区)
WHANZIL: LDB COUNT,#00H
DO1: LDB CWADD,PAGADD
ORB CWADD,#0B8H
LCALL WIL ;写入页
LDB CWADD,ROW
ORB CWADD,#40H
ANDB CWADD,#7FH
DO2: LCALL WIL ;写入列
LDB DREG,0000H[TABLE] ;取字模
LCALL WDL ;写入数据
INCB COUNT
INC TABLE
INCB CWADD
CMPB COUNT,#0020H ;写完32个字节?
JE DO1
CMPB COUNT,#0010H ;写完16个字节?
JNE DO2
INCB PAGADD
JMP DO3
DO3: RET
经过实际调试证明,以上电路原理正确,程序运行可靠,MGLS12864液晶显示模块显示正确、清晰。
122x32液晶1520控制器驱动程序(C51) :
/*------------------------------------------------------------------------------------------
[文件名] 12232.c
[版本] V1.5
[作者] 鞠春阳
[最后修改时间] 2003年5月12日
[版权所有] 哈尔滨众邦龙科技开发有限公司 www.mcuzb.com
[12232资料] 请到www.mcuzb.com下载
[程序说明] .h文件请在本站内搜索如果没有的话 可以到论坛留言所取
===========================================================================================*/
#include "reg51.h"
#include "intrins.h"
#include "absacc.h"
#include ".\inc\ASCII816.h" //标准ASCII码库
#include ".\inc\HZTable.h" //自制的汉字库
#include ".\inc\menu.h"</P><> //自制的菜单库
sbit LCD12232_A0=P3^3;
sbit LCD12232_RW=P3^1; //读写
sbit LCD12232_E1=P3^5; //片选1(Master)
sbit LCD12232_E2=P3^4; //片选2(slave)
#define LCD12232_DATA P1 //数据口
void ClearScreen(void);
/*----------------------------------------------------------------------------
调用方式:void OutMI(unsigned char i)
函数说明:发指令i到主窗口。(内函数,私有,用户不直接调用)
------------------------------------------------------------------------------*/
void OutMI(unsigned char i)
{
LCD12232_E2=0; //确认
LCD12232_A0=0;
LCD12232_RW=1;
LCD12232_E1=1; _nop_();
LCD12232_DATA = i;
while( LCD12232_DATA & 0x80 ); //busy?
LCD12232_E1=0; _nop_();</P><>LCD12232_RW=0;
LCD12232_E1=1; _nop_();</P><>LCD12232_DATA=i;_nop_();
LCD12232_E1=0; _nop_();
}
/*------------------------------------------------------------------------------
调用方式:void OutMD(unsigned char i)
函数说明:发数据i到主窗口。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void OutMD(unsigned char i)
{
LCD12232_E2=0; //确
LCD12232_A0=0;
LCD12232_RW=1;
LCD12232_E1=1; _nop_();
LCD12232_DATA = i;
while( LCD12232_DATA & 0x80 );
LCD12232_E1=0; _nop_();LCD12232_A0=1;
LCD12232_RW=0;
LCD12232_E1=1; _nop_();
LCD12232_DATA=i; _nop_();
LCD12232_E1=0; _nop_();
}
*------------------------------------------------------------------------------
调用方式:void OutSI(unsigned char i)
函数说明:发指令i到从窗口。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void OutSI(unsigned char i)
{
LCD12232_E1=0; //确认
LCD12232_A0=0;
LCD12232_RW=1;
LCD12232_E2=1; _nop_();
LCD12232_DATA = i;
while( LCD12232_DATA & 0x80 );
LCD12232_E2=0; _nop_();
LCD12232_RW=0;
LCD12232_E2=1; _nop_();
LCD12232_DATA=i; _nop_();
LCD12232_E2=0; _nop_();
}
/*------------------------------------------------------------------------------
调用方式:void OutSD(unsigned char i)
函数说明:发数据i到从窗口。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void OutSD(unsigned char i)
{
LCD12232_E1=0; //确认
LCD12232_A0=0;
LCD12232_RW=1;
LCD12232_E2=1; _nop_();
LCD12232_DATA =i;
while( LCD12232_DATA & 0x80 );
LCD12232_E2=0; _nop_();
LCD12232_A0=1;
LCD12232_RW=0;
LCD12232_E2=1; _nop_();
LCD12232_DATA=i; _nop_();
LCD12232_E2=0; _nop_();
}</P><>/*--------------------------------------------------------------------------------------------------*/
//显示8*8点阵
//字模被竖着切分
//lin:行(0-3), column: 列(0-14)
//address : 字模区首地址
void Show88(unsigned char lin,unsigned char column,unsigned int address)
{
unsigned char i,j;</P><> if( column > 14) return;</P><></P><> if( column < 7 ) //8*8点阵都在左屏(Master)
{ OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //设置显示列
for(i=0; i<8 ; i++ ) { OutMD( CBYTE[address+i] ); }
}
if( column == 7) //8*8点阵,前6个在左屏(Master),后两个在右屏(Slave)
{ OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //左屏
for(i=0; i<6 ; i++ )
{ OutMD( CBYTE[address+i] ); }</P><> OutSI( 0xB8 | lin); //设置显示行
OutSI( 0 ); //右屏
for(i=0; i<3 ; i++ ) { OutSD( CBYTE[address+i+5] ); }
}
if( column > 7) //8*8点阵都在右屏(Slave)
{ OutSI( 0xB8 | lin); //设置显示行
OutSI( column*8-61 );
for(i=0; i<8 ; i++ ) { OutSD( CBYTE[address+i] ); }
}
}</P><>/*------------------------------------------------------------------------------------------------*/
//显示8*16字符
//旋转90度:字模被竖着切分
//lin:行(0-3), column: 列(0-15)
//character:字符代码(标准ASCII码)
void ShowChar(unsigned char lin,unsigned char column,unsigned char character)
{ lin=lin<<1;
Show88(lin ,column,ASCII816[character-0x20] );
Show88(lin+1,column,ASCII816[character-0x20]+8 );
}
/*----------------------------------------------------------------------------------------------*/
//显示一个汉字
//旋转90度:字模被竖着切分
//lin:行(0-3), column: 列(0-7)
//hzcode: 汉字代码(自定义的)
//uchar code HZtable
void ShowHZ(unsigned char lin,unsigned char column,unsigned int hzcode)
{
lin=lin<<1; //lin*2
Show88(lin,column,HZTable[hzcode]);
Show88(lin,column+1,HZTable[hzcode]+8);
Show88(lin+1,column,HZTable[hzcode]+16);
Show88(lin+1,column+1,HZTable[hzcode]+24);
}
////////////////////////////////////////////////////////////////////////</P><>
/*------------------------------------------------------------------------------
调用方式:void LcdIni(void)
函数说明:12232点阵液晶初始化,开机后仅调用一次。
------------------------------------------------------------------------------*/
void InitLCD(void)
{
OutMI(0XE2);OutSI(0XE2);//复位
OutMI(0XAE);OutSI(0XAE);//POWER SAVE
OutMI(0XA4);OutSI(0XA4);//动态驱动
OutMI(0XA9);OutSI(0XA9);//1/32占空比
OutMI(0XA0);OutSI(0XA0);//时钟线输出
OutMI(0XEE);OutSI(0XEE);//写模式
OutMI(0XC0);OutMI(0X00);//显示起始行为0,列地址为0
OutSI(0XC0);OutSI(0X00);//显示起始行为0,列地址为0
OutMI(0XAF);OutSI(0XAF); //开显示
ClearScreen();
}</P><P>/*------------------------------------------------------------------------------
调用方式:void clrscr(void)
函数说明:清屏
------------------------------------------------------------------------------*/
void clrscr(void)
{
unsigned char i;
unsigned char page;
for( page=0;page<2; page ++)
{
for(i=0;i<5;i++) ShowChar( page,i,' ');
}
}///////////////////////////////////////////////////////////////////////
/*------------------------------------------------------------------------------
调用方式:void SetPage(unsigned char page0,unsigned char page1)
函数说明:同时设置主从显示页为0-3页。(内函数,私有,用户不直接调用)
------------------------------------------------------------------------------*/
void SetPage(unsigned char page0,unsigned char page1)
{
OutMI(0xB8|page1);
OutSI(0xB8|page0);
}
/*------------------------------------------------------------------------------
调用方式:void SetAddress(unsigned char address0,unsigned char address1)
函数说明:同时设置主从列地址为0-121。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void SetAddress(unsigned char address0,unsigned char address1)
{
OutMI(address1&0x7F);
OutSI(address0&0x7F);
}
/*------------------------------------------------------------------------------
调用方式:void PutChar0(unsigned char ch)
函数说明:在左页当前地址画一个字节8个点。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void PutChar0(unsigned char ch)
{
OutSD(ch);
}
/*------------------------------------------------------------------------------
调用方式:void PutChar1(unsigned char ch)
函数说明:在右页当前地址画一个字节8个点。(内函数,私有,用户不直接调用)
-------------------------------------------------------------------------------*/
void PutChar1(unsigned char ch)
{
OutMD(ch);
}
/*------------------------------------------------------------------------------
调用方式:void DrawBmp(unsigned char x,bit layer,unsigned char width,unsigned char *bmp)
函数说明:画一个图,横坐标是x,layer表示上下层,width是图形的宽,高都是16,bmp是
图形指针
使用zimo21软件,采用纵向取模得到bmp数据。
------------------------------------------------------------------------------*/
void DrawBmp(unsigned char x0,bit layer,unsigned char width,unsigned char *bmp)
{
unsigned char x,address,i=0; //address表示显存的物理地址
unsigned char page=0;
bit window=0; //page表示上下两页,window表示左右两页
if (layer) page=2;
for (x=x0;x<x0+width;x++)
{
if (x>62) {window=1;address=x%62;}
else address=x;
SetPage(page,page);
SetAddress(address,address);
if (window)
{
PutChar0(bmp);
}
else
{
PutChar1(bmp);// Master ,画上层
}
SetPage(page+1,page+1);
SetAddress(address,address);
if (window)
{
PutChar0(bmp[i+width]);
}
else
{
PutChar1(bmp[i+width]);//画下层
}
i++;
}
}
void ClearScreen(void)
{
unsigned char i;
unsigned char page;
for (page=0;page<4;page++)
{
SetPage(page,page);
SetAddress(0,0);
for (i=0;i<62;i++)
{
PutChar1(0x0);
PutChar0(0x0);
}
}
}
//显示一行字符串(汉字,字母混排,一行16字节)
//lin:行
//lineheadaddr: 此行汉字代码区首地址
void ShowLine(unsigned char lin,unsigned char linehead[])
{ unsigned char i;
unsigned char byte;
unsigned int hzcode;
for( i=0; i<16; )
{ byte=linehead;
if(byte < 0x80) //字母
{
if(i>15) return; //!!编译器有问题,须强制退出
ShowChar(lin, i , byte);
i=i+1;
}
else // byte >= 0x80(汉字)
{
if(i>15) return; //!!编译器有问题,须强制退出
byte=byte & 0x7f; //最高位置0,即:减去0x8000
hzcode=(unsigned int)byte<<8; //?? //高8位
hzcode=hzcode+linehead[i+1]; //加低8位,组合成整型数地址
ShowHZ( lin,i,hzcode);
i=i+2;
}
}
}
//显示一屏汉字
//pageheadaddr:此屏汉字代码地址区首地址
void ShowPage(unsigned char pagehead[][16])
{ unsigned char i;
for(i=0;i<2;i++) ShowLine(i,pagehead); //1行8个汉字,16字节
}unsigned char ReadByte_1()
{
unsigned char dat;
LCD12232_E2=0; //确
LCD12232_A0=1;
LCD12232_RW=1;
LCD12232_E1=1; _nop_(); _nop_();
LCD12232_DATA=0xff;
dat=LCD12232_DATA; _nop_(); _nop_();
LCD12232_E1=0; _nop_(); _nop_();
return dat;
}unsigned char ReadByte_2()
{
unsigned char dat;
LCD12232_E1=0; //确
LCD12232_A0=1;
LCD12232_RW=1;
LCD12232_E2=1; _nop_(); _nop_();
LCD12232_DATA=0xff;
dat=LCD12232_DATA; _nop_(); _nop_();
LCD12232_E2=0; _nop_(); _nop_();
return dat;
}
//反显一个8*8字块
//lin:行(0-3), column: 列(0-7)
void ReverseShow88(unsigned char lin,unsigned char column)
{
unsigned char i,j,dat[8];
if( column > 14) return;</P><P> if( column < 7 ) //8*8点阵都在左屏(Master)
{ OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //设置显示列
dat=~ReadByte_1();
for(i=0;i<8;i++)
{
dat=~ReadByte_1();
}
OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //设置显示列
for(i=0; i<8 ; i++ ) { OutMD(dat); }
}
if( column == 7) //8*8点阵,前6个在左屏(Master),后两个在右屏(Slave)
{ OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //左屏
dat=~ReadByte_1();
for(i=0;i<6;i++)
{
dat=~ReadByte_1();
}
OutMI( 0xB8 | lin); //设置显示行
OutMI( column*8 ); //左屏
for(i=0; i<6 ; i++ )
{ OutMD(dat); }
OutSI( 0xB8 | lin); //设置显示行
OutSI( 0 ); //右屏
dat=~ReadByte_2();
for(i=0;i<2;i++)
{
dat=~ReadByte_2();
}
OutSI( 0xB8 | lin); //设置显示行
OutSI( 0 ); //右屏
for(i=0; i<2 ; i++ ) { OutSD(dat); }
}
if( column > 7) //8*8点阵都在右屏(Slave)
{ OutSI( 0xB8 | lin); //设置显示行
OutSI( column*8-62 );
dat=~ReadByte_2();
for(i=0;i<8;i++)
{
dat=~ReadByte_2();
}
OutSI( 0xB8 | lin); //设置显示行
OutSI( column*8-62 );
for(i=0; i<8 ; i++ ) { OutSD(dat); }
}
}
//反显一行
ReverseShow(unsigned char lin)
{
unsigned char i;
lin=lin*2;
for(i=0;i<15;i++)
{
ReverseShow88(lin,i);
ReverseShow88(lin+1,i);
}
}
//反显一个汉字
ReverseShowHZ(unsigned char lin,unsigned char col)
{
lin=lin*2;
ReverseShow88(lin,col);
ReverseShow88(lin+1,col);
ReverseShow88(lin,col+1);
ReverseShow88(lin+1,col+1);
}
//反显一个字符
ReverseShowChar(unsigned char lin,unsigned char col)
{
lin=lin*2;
ReverseShow88(lin,col);
ReverseShow88(lin+1,col);
}</P><P>void Reset() //液晶复位
{
_nop_(); _nop_();}
;TEST TO 12864-7 (C12864-1)
;控制器: KS0108
;尺寸: 128 X 64 DOTS
;DRAW: WHY
;DATE: 1999.5.24
;****************************************************************
;RS REG P3.0 ;DEFINE LCM DATA/INSTRUCTION PIN
;R/W REG P3.1 ;DEFINE LCM READ/WRITE PIN
;E REG P3.2 ;DEFINE LCM ENABLE PIN
;CS1 REG P3.3 ;DEFINE LCM CHIP 1 SELECT
;CS2 REG P3.4 ;DEFINE LCM CHIP 2 SELECT
;RSTB REG P3.5 ;DEFINE LCM RESET PIN
;DB0~DB7 REG P1.0~P1.7 ;DEFINE LCM DATA BUS
ORG 0000H
INIT: CLR P3.5 ;DISPLAY RESET
NOP
NOP
SETB P3.5
MOV P3,#038H ;ENBALE CHIP 1 AND CHIP 2
SETB P3.1 ;R/W=1
CLR P3.0 ;RS=0
INIT1: ORL P1,#0FFH 1 INKEYT MODE
SETB P3.2 ;E=1
MOV A,P1 ;READ BUSY SIGNAL
CLR P3.2 ;E=0
JB ACC.7,INIT1 ;BUSY END?
JB ACC.4,INIT1 ;RESET END?
MOV A,#0C0H ;DISPLAY START LINE
LCALL TRS0
MOV A,#03FH ;DISPLAY ON
LCALL TRS0
START:
LCALL CLEAR ;START TO TEST
LCALL ICON
LCALL KEY
LCALL TEST
LCALL BOX
LCALL KEY
JMP START
CLEAR: MOV P3,#038H ;CLEAR DISPLAY RAM
MOV R5,#0B8H
MOV A,#0C0H
LCALL TRS0
CLEAR2: MOV A,R5
LCALL TRS0
MOV A,#40H
LCALL TRS0
MOV R4,#40H
CLEAR1: MOV A,#00H
LCALL TRS1
DJNZ R4,CLEAR1
INC R5
CJNE R5,#0C0H,CLEAR2
RET
ICON: CLR P3.3 ;TEST ICON
SETB P3.4
MOV A,#0BFH
LCALL TRS0
MOV A,#07CH
LCALL TRS0
MOV R4,#04H
MOV A,#80H
ICON1: LCALL TRS1
DJNZ R4,ICON1
RET
TEST: MOV DPTR,#ADATA ;TEST 1
MOV 67H,DPH
MOV 68H,DPL
MOV R0,#07H
TEST5: MOV R5,#0B8H
MOV P3,#038H
TEST3: MOV A,R5
LCALL TRS0
MOV A,#40H
LCALL TRS0
MOV R4,#08H
TEST2: MOV DPH,67H
MOV DPL,68H
MOV R3,#08H
TEST1: MOV A,#00H
MOVC A,@A+DPTR
LCALL TRS1
INC DPTR
DJNZ R3,TEST1
DJNZ R4,TEST2
INC R5
CJNE R5,#0BFH,TEST3
SETB P3.3
CLR P3.4
MOV A,#0BFH
LCALL TRS0
MOV A,#40H
LCALL TRS0
LCALL TESTS
CLR P3.3
SETB P3.4
MOV A,#0BFH
LCALL TRS0
MOV A,#40H
LCALL TRS0
LCALL TESTT
SETB P3.3
SETB P3.4
LCALL KEY
CLR C
MOV A,68H
ADD A,#08H
MOV 68H,A
JNC TEST4
INC 67H
TEST4: DJNZ R0,TEST5
RET
TESTS: MOV R4,#08H ;SUB. OF TEST 1
TESTS2: MOV DPH,67H
MOV DPL,68H
MOV R3,#08H
TESTS1: MOV A,#00H
MOVC A,@A+DPTR
LCALL TRS1
INC DPTR
DJNZ R3,TESTS1
DJNZ R4,TESTS2
RET
TESTT: MOV R4,#07H ;SUB. OF TEST 1
TESTT2: MOV DPH,67H
MOV DPL,68H
MOV R3,#08H
TESTT1: MOV A,#00H
MOVC A,@A+DPTR
LCALL TRS1
INC DPTR
DJNZ R3,TESTT1
DJNZ R4,TESTT2
MOV DPH,67H
MOV DPL,68H
MOV R3,#04H
TESTT3: MOV A,#00H
MOVC A,@A+DPTR
LCALL TRS1
INC DPTR
DJNZ R3,TESTT3
MOV R3,#04H
TESTT4: MOV A,#00H
MOVC A,@A+DPTR
ANL A,#7FH
LCALL TRS1
INC DPTR
DJNZ R3,TESTT4
RET
BOX: LCALL CLEAR ;TEST 2
SETB P3.3
SETB P3.4
MOV A,#0B8H
LCALL TRS0
MOV A,#040H
LCALL TRS0
MOV R4,#40H
BOX1: MOV A,#01H
LCALL TRS1
DJNZ R4,BOX1
SETB P3.3
SETB P3.4
MOV A,#0BFH
LCALL TRS0
MOV A,#040H
LCALL TRS0
MOV R4,#40H
BOX2: MOV A,#80H
LCALL TRS1
DJNZ R4,BOX2
SETB P3.3
CLR P3.4
MOV R5,#0B8H
BOX3: MOV A,R5
LCALL TRS0
MOV A,#040H
LCALL TRS0
MOV A,#0FFH
LCALL TRS1
INC R5
CJNE R5,#0C0H,BOX3
CLR P3.3
SETB P3.4
MOV R5,#0B8H
BOX4: MOV A,R5
LCALL TRS0
MOV A,#7FH
LCALL TRS0
MOV A,#0FFH
LCALL TRS1
INC R5
CJNE R5,#0C0H,BOX4
CLR P3.3
SETB P3.4
MOV A,#0BFH
LCALL TRS0
MOV A,#7CH
LCALL TRS0
MOV R4,#03H
BOX5: MOV A,#00H
LCALL TRS1
DJNZ R4,BOX5
MOV A,#7FH
LCALL TRS1
RET
DELAY: MOV 40H,#1FH ;DELAY TIME
DELAY1: MOV 41H,#30H
DELAY2: DJNZ 41H,DELAY2
DJNZ 40H,DELAY1
RET
KEY: ORL P2,#0FFH ;SELECT KEY FOR TEST
KEY1: MOV C,P2.0
JC KEY1
CALL DELAY
CALL DELAY
MOV C,P2.0
JC KEY1
CALL DELAY
MOV R4,#20H
KEY2: CALL DELAY
DJNZ R4,KEY2
RET
TRS0: CALL BUSY ;SEND OUT INSTRUCTION
CLR P3.1
CLR P3.0
JMP WRITE
TRS1: CLR P3.1 ;SEND OUT DATA
SETB P3.0
WRITE: MOV P1,A
CLR P3.2
SETB P3.2
CLR P3.2
RET
BUSY: CLR P3.0 ;READ BUSY
SETB P3.1
SETB P3.2
MOV C,P1.7
CLR P3.2
JC BUSY
RET
TRS2: MOV P1,#0FFH
SETB P3.1
SETB P3.0 ;READ DATA
SETB P3.2
MOV A,P1
NOP
CLR P3.2
RET
ADATA:
DB 055H,055H,055H,055H,055H,055H,055H,055H
DB 0AAH,0AAH,0AAH,0AAH,0AAH,0AAH,0AAH,0AAH
DB 0FFH,000H,0FFH,000H,0FFH,000H,0FFH,000H
DB 000H,0FFH,000H,0FFH,000H,0FFH,000H,0FFH
DB 040H,03FH,015H,015H,07FH,000H,000H,000H
DB 000H,024H,02AH,07FH,02AH,012H,000H,000H
DB 000H,000H,032H,049H,079H,041H,03EH,000H
END ;END OF PROGRAM
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |