📄 ocm12864.c
字号:
//OCM12864参考程序
#pragma code
#include <REG52.h>
//#include <math.h>
#include <absacc.h>
//#include <intrins.h>
#include <string.h>
#include "GSOPYJZM.H"
#define uint unsigned int
#define uchar unsigned char
#define disp_off 0x3e //关显示
#define disp_on 0x3f //开显示
#define disp_x 0xb8 //页面地址设置, 1 0 1 1 1 P2 P1 P0
#define disp_z 0xc0 //显示起始行设置, 1 1 L5 L4 L3 L2 L1 L0
#define disp_y 0x40 //列地址设置, 0 1 C5 C4 C3 C2 C1 C0
#define data_ora P0 //MCU P1<------> LCM
uchar volatile xdata LCD_LWC _at_ 0X0100; // W,液晶左屏写指令
uchar volatile xdata LCD_LWD _at_ 0X0500; // W,液晶左屏写数据
uchar volatile xdata LCD_LRS _at_ 0X0900; // R,液晶左屏读状态
uchar volatile xdata LCD_LRD _at_ 0X0D00; // R,液晶左屏读数据
uchar volatile xdata LCD_RWC _at_ 0X0200; // W,液晶右屏写指令
uchar volatile xdata LCD_RWD _at_ 0X0600; // W,液晶右屏写数据
uchar volatile xdata LCD_RRS _at_ 0X0A00; // R,液晶右屏读状态
uchar volatile xdata LCD_RRD _at_ 0X0E00; // R,液晶右屏读数据
void delay(unsigned char cc)
{
while(--cc);
}
// 液晶(LCD)写入命令字程序,
// e :左、右屏选择,取值范围:e = 1(左屏) 、2(右屏) ,
// com :送往 LCD 的指令代码。
void LcdCommW(unsigned char e,unsigned char com)
{
xdata unsigned char st;
if(e==1) // 左屏
{
do st=LCD_LRS; // Y2,R,液晶左屏读状态
while(st&0x80); // 判“忙”
LCD_LWC=com;
}
else // 右屏
{
if(e==2)
{
do st=LCD_RRS;// Y3,R,液晶右屏读状态
while(st&0x80); // 判“忙
LCD_RWC=com;
}
}
}
// 液晶(LCD)写入显示数据程序,
// e :左、右屏选择,取值范围:e = 1(左屏) 、2(右屏),
// dat :送往 LCD 的显示数据。
void LcdDataW(unsigned char e,unsigned char dat)
{
xdata unsigned char st;
if(e==1) // 左屏
{
do st=LCD_LRS; // Y2,R,液晶左屏读状态
while(st&0x80); // 判忙BUSY
LCD_LWD=dat; // Y2,W,液晶左屏写数据
}
else // 右屏
{
if(e==2)
{
do st=LCD_RRS; // Y3,R,液晶右屏读状态
while(st&0x80); // 判忙BUSY
LCD_RWD=dat; // Y3,W,液晶右屏写数据
}
}
}
// 液晶(LCD)初始化程序,
// 其中,调用:LcdCommW(),
void LcdInit(void)
{
LcdCommW(1,0xC0); // 左屏设置显示起始行为第一行
LcdCommW(2,0xC0); // 右屏设置显示起始行为第一行
LcdCommW(1,0x3f); // 左屏开显示设置
LcdCommW(2,0x3f); // 右屏开显示设置
}
// 清LCD显示子程序,
void LcdClean(void)
{
xdata unsigned char line,colu,ct;
for(line=0;line<8;line++)
{
ct=0xb8|line; //页面地址设置
LcdCommW(1,ct); // 设置'页'地址,即设置显示行
LcdCommW(2,ct); // 设置'页'地址,即设置显示行
LcdCommW(1,0x40); // 设置列地址
LcdCommW(2,0x40); // 设置列地址
for(colu=0;colu<64;colu++)
{
LcdDataW(1,0); // 写入数据
LcdDataW(2,0); // 写入数据
}
}
}
void delay1 (uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<1000;j++)
;
}
// zm16_16[c].dt[2][16]所包含的 16×16 点阵字符送往 LCD 显示,
// x :水平坐标,范围:0 - 15,字符位表示,取字符左边所在位置,
// y :竖直坐标,范围:1 - 7,字符位表示,取字符下方所在位置,
// 上述坐标零点对应于液晶显示屏的左上角,
// c :要写入的字符序号 c(对应于 zm16_16[c].dt[2][16]),
// color:显示颜色,1:反色;0:正常
void DisZm16_16(unsigned char x, unsigned char y, unsigned char c,bit color)
{
xdata unsigned char i,j,d;//定义的局部变量
xdata unsigned char screen;//左右屏幕
xdata unsigned char colu; //计算列数,x*8代表第几列
if(x<16 && y<8 && y>0)//是否位于128=16*8,8*8=64行范围内,不显示乱吗
{
y-=1;//y代表下半字所处的页地址,y-1代表上半字所在页位置
for(i=0;i<2;i++)//i=0写上半字,i=1写下半字
{
y+=i;//因为前面y已经变为上半字页地址了,当i=1时候就写下半字页地址了
y|=0xb8;//页地址设置,页地址在初始页地址基础上偏移
colu=x*8;//判断是否超出左屏幕,大于63意味在右屏幕写汉字
if(colu>63)//判断是否超出左屏幕
{
colu-=64;//超出左屏幕,colu-64取得相对的
screen=2;//选择右屏幕
}
else screen=1;//如果没超出就选择左屏幕
LcdCommW(screen,y); // 设置'页'地址,即设置显示行
LcdCommW(screen,(colu|0x40));//设置列地址,在初始列地址基础上加偏移量
for(j=0;j<16;j++)//引用数组,i=0第一行,i=1第二行,一个字符有两行,每行16列
{
d=zm16_16[c].dt[i][j];//引用结构体变量
if(color==1) d=~d;//"~"(按位取反),如果要反显示就取反,否则正常显示
LcdDataW(screen,d);//写入数据
if(++colu>63 && screen==1)//左屏幕放不下时候,写在右屏幕
{
colu-=64;
screen=2;
LcdCommW(screen,y); // 设置'页'地址,即设置显示行
LcdCommW(screen,(colu|0x40)); // 设置列地址
}
}
}
}
}
// zm8_16[c][2][8]所包含的 8×16 点阵字符送往 LCD 显示,
// x :水平坐标,范围:0 - 15,字符位表示,取字符左边所在位置,
// y :竖直坐标,范围:1 - 7,字符位表示,取字符下方所在位置,
// 上述坐标零点对应于液晶显示屏的左上角,
// c :要写入的字符序号 c(对应于 zm8_16[c][2][8]),
// color:显示颜色,1:反色;0:正常
void DisZm8_16(unsigned char x, unsigned char y, unsigned char c,bit color)//列,页,要显示字符,显示颜色
{
xdata unsigned char i,j,d;//分别对应二维数组的行列,从而选择上下半字,d代表要显示的字符,写入
xdata unsigned char screen;//选择左右屏幕
xdata unsigned char colu;//计算所处列位置,colu=x*8;
if(x<16 && y<8 && y>0)//判断是否位于128*64液晶显示屏幕内
{
y-=1;//计算上半列地址
for(i=0;i<2;i++)//选择要显示的字符,每个字符两行,每行8列,i为行选择
{
y+=i;//因为前面y已经变为上半字页地址了,当i=1时候就写下半字页地址了
y|=0xb8;//求页地址,页地址在初始页地址基础上偏移
colu=x*8;//求列地址
if(colu>63)//如果大于63,表示在右屏幕了
{
colu-=64;//处于右屏幕中,列地址相对位置
screen=2;//选择右屏幕
}
else screen=1;//否则选择左屏幕
LcdCommW(screen,y); // 设置'页'地址,即设置显示行
LcdCommW(screen,(colu|0x40)); // 写入列地址
for(j=0;j<8;j++)//写列数据,数组中共有两行,每行8列
{
d=zm8_16[c][i][j];//结构体变量引用
if(color==1) d=~d;//如果要反显示,数据取反
LcdDataW(screen,d);//数据写入LCD
if(++colu>63 && screen==1)//写数据的时候判断每列是否超出左屏幕
{
colu-=64;//如果超出,就在右屏幕显示
screen=2;
LcdCommW(screen,y); // 设置'页'地址,即设置显示行
LcdCommW(screen,(colu|0x40)); // 设置列地址
}
}
}
}
}
// 在液晶上从指定位置开始显示16点阵高字符串程序,
// x :水平坐标,范围:0 - 15,字符位表示,取字符串左边所在位置,
// y :竖直坐标,范围:1 - 7,字符位表示,取字符串下方所在位置,
// 若中英文混合,则中文及全角英文显示16*16点阵,半角英文显示8*16点阵,
// 字符串末尾应以0x00结尾,且超出可显示范围的字符将不显示,
// p:字符串首指针。
// color:显示颜色,1:反色;0:正常
void DisH16Str(unsigned char x, unsigned char y,unsigned char *p,bit color)//列,页,字符串,反色与否标志
{
xdata unsigned char c,d;//c,d
xdata unsigned int i;//
if(y<8 && y>0)//判断是否显示在这8页中,超出范围不显示
{
for(;x<16;x++)//判断是否在16*8列中
{
c=*p;//取字符
p++;//字符串地址加1,取下个字符
if(c==0) break;//判断字符串是否结束
if(c>0xA0)//判断是否为全角字符,<=0xa0是半角字符,>0xa0是全角字符
{
i=c;//取得字符,全角字符是两个字节组成一个字符,高位在前,低位在后
i*=256;//存到高8位上
i+=*p;//高8位加上低8位组成一个
p++;//指向下一个字符
d=sizeof(zm16_16)/34;//每个zm16_16变量占用34个字节,一个整型变量占2个字节,一个字符数组2行16列,2+32=34
for(c=0;c<d;c++)//d为计算得出有多少个字符,
{
if(i==zm16_16[c].cd) break;//与zm16_16结构中的各个值比较,选择相同的一个
}
if(c==d) c=0;
DisZm16_16(x,y,c,color);
x++;
}
else
{
if(c>'~' || c<' ') c=' ';//保证不显示乱码
c-=' ';
DisZm8_16(x,y,c,color);
}
}
}
}
void main(void)
{
//unsigned char c=0;
//do delay(0);
//while(--c); // 开机延时65536个机器周期
LcdInit(); // 液晶显示初始化
LcdClean(); // 液晶显示清屏
DisH16Str(4,1,"TYPE",0);
DisH16Str(6,4,"V 0.0",0);
DisH16Str(3,7,"2006/11/30",0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -