LCD12864怎么实现任意位置显示字符或汉字

LCD12864怎么实现任意位置显示字符或汉字,第1张

1大小可调

字库里的字符大小应该是固定的,你要是实现大小可调就要用到字模提取软件,把字符转换为像素点。

2 任意位置显示

#include<reg52h> //包含单片机寄存器的头文件

sbit RS=P2^2; //寄存器选择位,将RS位定义为P22引脚

sbit RW=P2^3; //读写选择位,将RW位定义为P23引脚

sbit EN=P2^4; //使能信号位,将E位定义为P24引脚

unsigned char table[]=" 你好 ";

unsigned char code digit[ ]={"0123456789"}; //定义字符数组显示数字

void read_busy() //读忙标志

{

RS=0;

RW=1;

EN=1;

while(P0 & 0x80);

EN=0;

}

void delay(unsigned int i) //延时函数

{

while(--i);

}

void Write_LCD_command(unsigned char value) //写命令函数

{

read_busy(); //每次读写前都要惊醒“忙”判断

RS=0;

RW=0;

delay(200);

EN=1; //EN从1---0锁存有效数据

P0=value;

delay(200);

EN=0;

}

void Write_LCD_data(unsigned char value)//写数据函数

{

read_busy(); //每次读写前都要惊醒“忙”判断

RS=1;

RW=0;

delay(200);

EN=1; //EN从1---0锁存有效数据

P0=value;

delay(200);

EN=0;

}

void init_LCD() //LCD12864初始化

{

delay(4000);

Write_LCD_command(0x30);//8位数据格式,基本指令显示

delay(100); //延时时间

Write_LCD_command(0x30);//8位数据格式,基本指令显示

delay(37);

Write_LCD_command(0x0C);//开显示、关闭光标

delay(100);

Write_LCD_command(0x01);//清屏指令

delay(10000); //延时

Write_LCD_command(0x06);//设置显示点:指针自加1

}

//

//以上是我测温程序的显示驱动部分,下面给你实现任意位置显示的程序

//

void main()

{

unsigned int num;

init_LCD() //LCD12864初始化

while(1)

{

for(num=0;num<4;num++)//2个汉字

{

Write_LCD_command(0x90);//根据需要改变数值从而实现不同位置显示,看看12864的手册就知道了

Write_LCD_data(table[num]);

delay(10000);

}

}

}

//LCD12864字库系列(控制器ST7920A),单片机:89S52,晶振:12M,

//串口连接 与 并口连接 ( 串口时 屏蔽 并行模块)

//并行连接方式,P20-RS,P21-RW,P22-E

#include<reg52h>

#include <intrinsh>

sbit RS=P3^2; //串口时为CS

sbit RW=P3^1; //串口为SID

sbit E=P3^0; //串口为时钟SCLK

sbit stop=P2^2;

sbit PSB=P3^4;

sbit REST=P3^3;

//以下是用<at89x51h>头文件的定义

/

#define RS P2_0

#define RW P2_1 //定义引脚

#define E P2_2

#define PSB P2_3

#define REST P2_4

#define Data P1

#include<at89x51h>

/

#define BF 0x80 //用于检测LCM状态字中的Busy标识

typedef unsigned int Uint;

typedef unsigned char Uchar;

//字符串例子

//"F1--English",也可以往里面写入汉字码,一个汉字由两个码组成

const Uchar F1English[]={0x46,0x31,0x2d,0x2d,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68,0x00};

const Uchar lengthF1=6; //字符串长度

//汉字,直接可以写入字形

unsigned char code uctech[] = {"有限公司"};

const Uchar lengthCF3=8;

Uchar code TAB1[]={

/-- 调入了一幅图像:D:\公司的文件\程序\未命名11bmp --/

/-- 宽度x高度=128x64 --/

0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x05,0xAE,0x90,0x00,0x00,0x00,0x00,0x00,

0x95,0x55,0x48,0x80,0x00,0x00,0x00,0x00,

0x2B,0x55,0x00,0x00,0x00,0x00,0x00,0x00,

0xA8,0x00,0x22,0x15,0x20,0x00,0x00,0x00,

0x97,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,

0x45,0x55,0x08,0xA0,0x00,0x00,0x00,0x0A,

0x6F,0xF4,0x00,0x00,0x00,0x00,0x00,0x00,

0xB2,0x80,0x40,0x00,0x04,0x40,0x00,0x00,

0xBA,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,

0x4D,0x55,0x15,0x15,0x20,0x00,0x00,0x95,

0xD5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xFF,0xE8,0x40,0x40,0x00,0x00,0x00,0x4A,

0xAA,0x80,0x00,0x00,0x00,0x00,0x00,0x00,

0xFF,0xFF,0x2A,0x00,0x40,0x00,0x00,0x15,

0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xFF,0xFD,0xD0,0xAA,0x01,0x00,0x00,0x25,

0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,

0xFF,0xFF,0xB6,0x00,0x10,0x00,0x01,0x4A,

0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xFF,0xFF,0xFD,0xE8,0x40,0x00,0x00,0x11,

0x00,0x24,0x84,0x00,0x00,0x00,0x00,0x00,

0xAB,0xFF,0xFF,0x55,0x00,0x00,0x00,0x24,

0x02,0x49,0x5E,0xA0,0x00,0x00,0x00,0x00,

0x84,0xBF,0xFF,0xF4,0x88,0x00,0x00,0x00,

0x10,0x05,0xFF,0xF4,0x00,0x00,0x00,0x00,

0x29,0x0B,0xFF,0xFA,0x20,0x00,0x00,0x00,

0x02,0xBF,0xFF,0xFC,0x00,0x00,0x00,0x00,

0x44,0xA0,0x57,0xFD,0x80,0x00,0x00,0x00,

0x08,0x5F,0xFF,0xFF,0x80,0x00,0x00,0x00,

0x91,0x0A,0xAA,0xF6,0x50,0x00,0x00,0x00,

0x41,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,

0x44,0xA0,0x01,0x1B,0x84,0x00,0x00,0x00,

0x26,0xFF,0xFF,0xFF,0x90,0x00,0x00,0x00,

0x11,0x0A,0xAA,0x6D,0x68,0x00,0x00,0x00,

0x0B,0xFB,0xFF,0xEF,0xE0,0x00,0x00,0x00,

0xC4,0xA0,0x01,0x02,0x80,0x00,0x00,0x00,

0x43,0xF1,0xFE,0x63,0xF0,0x00,0x00,0x00,

0x15,0x55,0x54,0x55,0x6A,0x00,0x00,0x00,

0x9F,0xE3,0xFC,0x87,0x38,0x00,0x00,0x00,

0xCA,0xAB,0x91,0x00,0x90,0x00,0x00,0x00,

0x07,0xC1,0xFA,0x2A,0x80,0x00,0x00,0x00,

0x25,0xFF,0xFE,0x95,0x2A,0x00,0x00,0x00,

0x2F,0x13,0xFE,0xFC,0x10,0x00,0x00,0x00,

0x95,0xFF,0xFF,0xC0,0x50,0x00,0x00,0x00,

0x0F,0x41,0xFF,0xF3,0x80,0x00,0x00,0x00,

0x4F,0xFF,0xFF,0xF9,0x2A,0x00,0x00,0x00,

0x9F,0x08,0xFF,0xD4,0x00,0x00,0x00,0x00,

0xB3,0xFF,0xFF,0xFE,0x54,0x80,0x00,0x00,

0x1E,0xA0,0x7F,0xA0,0x00,0x00,0x00,0x00,

0x5F,0xFE,0x7F,0xFE,0xAA,0x00,0x00,0x00,

0x5F,0x57,0xFE,0x00,0x00,0x00,0x00,0x00,

0xAF,0xFD,0x7F,0xFF,0x94,0x80,0x00,0x00,

0x1F,0xFE,0xE8,0x00,0x00,0x00,0x00,0x00,

0x7F,0xFA,0x7F,0x5F,0xCA,0x00,0x00,0x00,

0x3F,0x55,0x00,0x00,0x00,0x00,0x00,0x00,

0xAF,0xF1,0x7F,0xDE,0xF5,0x40,0x00,0x00,

0x1A,0xA0,0x80,0x00,0x00,0x00,0x00,0x00,

0xDF,0xF2,0x3F,0xFC,0xC2,0x00,0x00,0x00,

0x50,0x08,0x00,0x00,0x00,0x00,0x00,0x00,

0x2F,0xFA,0xBF,0xFF,0xF4,0xA0,0x00,0x00,

0x05,0x42,0x00,0x00,0x00,0x00,0x00,0x00,

0x97,0xFE,0x3F,0xFF,0xE3,0x00,0x00,0x00,

0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x68,0xFF,0xDF,0xD5,0x78,0x40,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x07,0x5F,0xFF,0x48,0x02,0x80,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xD0,0xAA,0xF4,0xA0,0xAA,0x40,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x0A,0x45,0x09,0x05,0x11,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xA1,0x28,0xA0,0x00,0x44,0x40,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x08,0x42,0x04,0x52,0x12,0x80,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xA5,0x09,0x51,0x00,0x48,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x50,0x04,0x4A,0x12,0x80,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xAA,0x05,0x50,0x21,0x48,0x20,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x90,0x02,0x84,0x12,0x80,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xD4,0x05,0x48,0x10,0x48,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x81,0x20,0x00,0x02,0x02,0x80,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0xA4,0x84,0x92,0x48,0x94,0x40,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x48,0x10,0x00,0x00,0x21,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

};

//这个是在串口时指令和数据之间的延时

/

void delay10US(Uchar x)

{

Uchar k;

for(k=0;k<x;k++);

}

/

const Uchar delay=250; //延时时间常数

static void Wait1ms(void)//延迟1 ms

{

Uchar cnt=0;

while (cnt<delay) cnt++;

}

//延迟n ms

void WaitNms(int n)

{

Uchar i;

for(i=1;i<=n;i++)

Wait1ms();

}

void stopint(void)//中断程序

{

if(stop==0)

while(1);

}

////

//以下是并口时才开的

//读忙标志,

void RDBF(void)

{

Uchar temp;

RS=0; // RS=0

RW=1; // RW=1

while(1)

{

P1=0xFF; //数据线为输入

E=1;

temp=P1;

E=0; // E=0

if ((temp&0x80)==0) break;

}

}

//写数据到指令寄存器

void WRCommand(Uchar comm)

{

RDBF();

RW=0;

P1=comm;

E=1;

E=0;

}

//写数据到数据寄存器

void WRData(Uchar TEMP)

{

RDBF();

RS=1;

RW=0;

P1=TEMP;

E=1;

E=0;

stopint();

}

/////////////////////////////////////////////////////////////////////////////////

//以下是串口时开的读写时序

/void SendByteLCD(Uchar WLCDData)

{

Uchar i;

for(i=0;i<8;i++)

{

if((WLCDData<<i)&0x80)RW=1;

else RW=0;

E=0;

E=1 ;

}

}

SPIWR(Uchar Wdata,Uchar WRS)

{

SendByteLCD(0xf8+(WRS<<1));

SendByteLCD(Wdata&0xf0);

SendByteLCD((Wdata<<4)&0xf0);

}

void WRCommand(Uchar CMD)

{

RS=0;

RS=1;

SPIWR(CMD,0);

delay10US(90);//89S52来模拟串行通信,所以,加上89S52的延时,

}

void WRData(Uchar Data)

{

RS=0;

RS=1;

SPIWR(Data,1);

}

/

//

//初始化LCD-8位接口

void LCDInit(void)

{ // PSB=0; //串口

PSB=1;//并口时选这个,上一行取消

REST=1;

REST=0;

REST=1;

WRCommand(0x30); //基本指令集,8位并行

WRCommand(0x06); //启始点设定:光标右移

WRCommand(0x01); //清除显示DDRAM

WRCommand(0x0C); //显示状态开关:整体显示开,光标显示关,光标显示反白关

WRCommand(0x02); //地址归零

}

//显示数组字符串(显示半宽字型168点阵)

void ShowQQChar(Uchar addr,Uchar english,Uchar count)

{

Uchar i;

WRCommand(addr); //设定DDRAM地址

for(i=0;i<count;)

{

WRData(english[i2]);

WRData(english[i2+1]);

i++;

}

}

//显示连续字串(半宽字符)

void ShowNUMChar(Uchar addr,Uchar i,Uchar count)

{

Uchar j;

for(j=0;j<count;)

{

WRCommand(addr); //设定DDRAM地址

WRData(i+j);

j++;

WRData(i+j);

addr++;

j++;

}

}

//自定义字符写入CGRAM

void WRCGRAM(Uchar data1,Uchar data2,Uchar addr)

{

Uchar i;

for(i=0;i<16;)

{

WRCommand(addr+i); //设定CGRAM地址

WRData(data1);

WRData(data1);

i++;

WRCommand(addr+i); //设定CGRAM地址

WRData(data2);

WRData(data2);

i++;

}

}

//显示自定义的字符,并把这个字符填满全屏1616

void ShowCGChar(Uchar addr,Uchar i)

{

Uchar j;

for(j=0;j<0x20;)

{

WRCommand(addr+j); //设定DDRAM地址

WRData(0x00);

WRData(i);

j++;

}

}

void CLEARGDRAM(void)

{

Uchar j;

Uchar i;

WRCommand(0x34);

WRCommand(0x36);

for(j=0;j<32;j++)

{

WRCommand(0x80+j);

WRCommand(0x80);//X坐标

for(i=0;i<32;i++)//

{

WRData(0x00);

}

}

}

//写入GDRAM 绘图,Y是Y绘图坐标,2个字节一行,CLONG是图形长度,以字节

//为单位;HIGHT是图形高度,TAB是图形数据表12864M的图形显示是相当于25632点阵

//由两屏12832上下两屏组成,同一行的下屏的头地址紧接上屏的未地址。

//绘图在串口输入时,会比在并口下的输入要慢一些

void WRGDRAM(Uchar Y1,Uchar clong,Uchar hight,Uchar TAB1)

{

Uint k;

Uchar j;

Uchar i;

WRCommand(0x34);

WRCommand(0x36);

for(j=0;j<hight;j++)//32

{ //先上半屏

WRCommand(Y1+j); //Y总坐标,即第几行

WRCommand(0x80);//X坐标,即横数第几个字节开始写起

for(i=0;i<clong;i++)//

{

WRData(TAB1[clongj+i]);

}

//后下半屏

for(k=0;k<clong;k++)//

{

WRData(TAB1[clong(j+hight)+k]);

}

}

}

void menu(void)

{

LCDInit();

ShowNUMChar(0x80,0x01,0x0f);//显示半宽特殊符号

ShowNUMChar(0x90,0x30,0x0f);//显示半宽0~数字标点

ShowNUMChar(0x88,0x41,0x0f);//显示半宽A~P大写

ShowNUMChar(0x98,0x61,0x0f);//显示半宽a~p小写

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

WRCGRAM(0xff,0x00,0x40);//写入横

WRCGRAM(0x00,0xff,0x50);//写入横2

WRCGRAM(0xaa,0xaa,0x60);//写入竖

WRCGRAM(0x55,0x55,0x70);//写入竖2

ShowCGChar(0x80,0x00);//显示横并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

ShowCGChar(0x80,02);//显示横2并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

ShowCGChar(0x80,04);//显示竖并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

ShowCGChar(0x80,06);//显示竖2并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

WRCGRAM(0x00,0x00,0x40);//清CGRAM1

WRCGRAM(0x00,0x00,0x50);//清CGRAM2

WRCGRAM(0xaa,0x55,0x40);//写入点

WRCGRAM(0x55,0xaa,0x50);//写入点2

ShowCGChar(0x80,00);//显示点并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

ShowCGChar(0x80,02);//显示点2并填满

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

ShowQQChar(0x80,uctech,lengthCF3);//显示'有限公司',以下共四行

ShowQQChar(0x90,uctech,lengthCF3);

ShowQQChar(0x88,uctech,lengthCF3);

ShowQQChar(0x98,uctech,lengthCF3);

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

WRCommand(0x01); //清除显示DDRAM

}

void menu2(void)

{ CLEARGDRAM();

WRGDRAM(0x80,16,32,TAB1);

WaitNms(250); //等待时间

WaitNms(250); //等待时间

stopint();

}

//主函数

void main(void)

{

menu();//初始化及半宽字符和点横竖汉字扫描

menu2();//绘图显示

for(;;)

{;}

}

你设计的程序有问题:

1:每次执行while(1)时,v都会被重新定义一次,这样很不好,应该将变量定义放到while(1)外面。

2:case里面的 while(v==0x) v=keyscan();有问题,例如第一个case里面的while(v==0x41) v=keyscan(); ,你的意思是按一次键就加1,防止被加多次,但是你这个while语句退出的条件是下一个按键必须与当前按键不同,这与现实情况相符吗?主队不能连续得分吗?这个你自己考虑一下,也许你设置的比赛规则是这样的。

3:还是 while(v==0x) v=keyscan();这句,你的意思就是case语句退出的条件是检测到下一个按键必须与当前按键不同,但是你的while(1)循环第一句也是扫面键盘,这样就有可能出错。

建议你如下修改:

1:v的定义放到while(1)外面。

2:删除每一个case语句中的while(v==0x) v=keyscan();,在执行完case语句后,将v的值赋成0x00,或者一个不可能的键盘值即可,然后直接退出case语句。

case 0x41:

{

hpoint++; //主队加分

point_lcd(0x00,hpoint);

v = 0x00; 把v的值置成一个初值或者一个不可能的键盘值。

} //分数显示更新

break;

case 0x81:

{

hpoint--;

point_lcd(0x00,hpoint);

v = 0x00; 把v的值置成一个初值或者一个不可能的键盘值。

}

break;

case 0x12:

{

rpoint++; //客队加分

point_lcd(0x03,rpoint); //分数显示更新

v = 0x00; 把v的值置成一个初值或者一个不可能的键盘值。

}

break;

case 0x22:

{

rpoint--;

point_lcd(0x03,rpoint);

v = 0x00; 把v的值置成一个初值或者一个不可能的键盘值。

}

break;

下面是带中文字库的LCD12864

#include<reg52h>

#include <mathh>

void lcd_init(void);

void clr_lcd(void);

void send_com(unsigned char cmd);

void send_data(unsigned char dat);

void chek_busy(void);

void set_xy(unsigned char xpos,unsigned char ypos);

void print(unsigned char x,unsigned char y,char str);

void printstr(unsigned char xpos,unsigned char ypos,unsigned char str[],unsigned char k);

unsigned char code buf[4] ={0xbb,0xb6,0xd3,0xad};//欢迎

#define DATA P2

#define CONTROL P0

#define E 7 //并行的使能信号 sbit E = P0^7

#define RW 6 //并行的读写信号 sbit RW = P0^6

#define RS 5 //并行的指令数据选择信号 sbit RS = P0^5

#define PSB 4 //并/串行接口选择 sbit PSB = P0^4

#define RST 3 //复位 低电平有效 sbit RST = P0^3

#define SETB(x,y) (x|=(1<<y))

#define CLRB(x,y) (x&=(~(1<<y)))

#define CHKB(x,y) (x&(1<<y))

/测忙碌/

//测忙碌子程序

//RS=0,RW=1,E=H,D0-D7=状态字

//

void chek_busy(void)

{ unsigned char temp1;//状态信息(判断是否忙)

CLRB(CONTROL,RS); // RS = 0;

SETB(CONTROL,RW); // RW = 1;

SETB(CONTROL,E); // E = 1;

do{temp1 = DATA;DATA=0xFF;} while(temp1&0x80);

SETB(CONTROL,E); // E = 1;

DATA=0xFF;

}

/写命令/

//写命令子程序

//

//

void send_com(unsigned char cmd)/写命令/

{

chek_busy();

CLRB(CONTROL,RS); //RS = 0;

CLRB(CONTROL,RW); //RW = 0;

DATA = cmd;

SETB(CONTROL,E); //E = 1;

CLRB(CONTROL,E); //E = 0;

}

/写数据/

//写数据子程序

//

//

void send_data(unsigned char dat)

{

chek_busy();

SETB(CONTROL,RS); //RS = 1;

CLRB(CONTROL,RW); //RW = 0;

DATA = dat;

SETB(CONTROL,E); //E = 1;

CLRB(CONTROL,E); //E = 0;

}

/初始化/

//复位、通讯方式选择

//

void lcd_init(void)

{

SETB(CONTROL,RST);//复位RST=1

SETB(CONTROL,PSB); //通讯方式为并口PSB = 1

//send_com(0x34);//34H--扩充指令 *** 作

send_com(0x30);//功能设置,一次送8位数据,基本指令集

send_com(0x0C);//0000,1100 整体显示,游标off,游标位置off

send_com(0x01);//0000,0001 清DDRAM

send_com(0x02);//0000,0010 DDRAM地址归位

send_com(0x80);//1000,0000 设定DDRAM 7位地址000,0000到地址计数器AC

}

//

// 设置显示位置 xpos(1~16),tpos(1~4)

//

void set_xy(unsigned char xpos,unsigned char ypos)

{

switch(ypos)

{

case 1:

send_com(0X80|xpos);break;

case 2:

send_com(0X90|xpos);break;

case 3:

send_com(0X88|xpos);break;

case 4:

send_com(0X98|xpos);break;

default:break;

}

}

//

// 在指定位置显示字符串

//

void print(unsigned char x,unsigned char y,char str)

{

unsigned char lcd_temp;

set_xy(x,y);

lcd_temp=str;

while(lcd_temp != 0x00)

{

send_data(lcd_temp);

lcd_temp=(++str);

}

}

/写字符串/

//写字符串子程序

//xpos1取0~7共八列,ypos1取0~3共四行。

//

void printstr(unsigned char xpos,unsigned char ypos,unsigned char str[],unsigned char k)

{ unsigned char n;

switch (ypos)

{ case 1: xpos |= 0x80;break; //第一行

case 2: xpos |= 0x90;break; //第二行

case 3: xpos |= 0x88;break; //第三行

case 4: xpos |= 0x98;break; //第四行

default: break;

}

send_com(xpos); //此处的Xpos已转换为LCM的显示寄存器实际地址

for(n=0;n < k;n++)

{

send_data(str[n]);//显示汉字时注意码值,连续两个码表示一个汉字

}

}

/清屏/

//清屏

//

void clr_lcd(void)

{

send_com(0x01);

//send_com(0x34);

//send_com(0x30);

}

/主函数/

void main ()

{

lcd_init(); //设定液晶工作方式

printstr(1,1,buf,4);

print(5,1,"光临");

print(0,3," SEEGU百度空间");

while(1) { }

}

//-----------------------------------------------------------------下面这个是不带字库的,以前使用的液晶就是用这个驱动小改的

128x64液晶KS0108驱动程序(C51)

/------------------------------------------------------------------------------------------

[文件名] 12864c

[功能] 128X64驱动程序

[版本] 20

[作者] 鞠春阳

[最后修改时间] 2003年5月12日

[版权所有] wwwmcuzbcom

[资料] 请到wwwmcuzbcom下载

===========================================================================================/

#include "absacch"

#include "intrinsh"

//自定义库 在"C:\comp51\UserLib\"文件夹中

#include "\inc\ASCII816h" //标准ASCII库

#include "\inc\HZTableh" //汉字点阵库(自做)

#include "\inc\Menuh" //菜单库(自做)

// LCD12864 数据线

#define LCD12864DataPort P1

// LCD12864 I/O 信号管脚

sbit di =P3^1; // 数据\指令 选择

sbit rw =P3^3; // 读\写 选择

sbit en =P3^2; // 读\写使能

sbit cs1 =P3^4; // 片选1,低有效(前64列)

sbit cs2 =P3^5; // 片选2,低有效(后64列)

sbit reset=P0^7; // 复位

/----------------------------------------------------------------------------------------------------/

/ 函数列表

//开关显示

void SetOnOff(unsigned char onoff)

//选择屏幕

//screen: 0-全屏,1-左屏,2-右

void SelectScreen(unsigned char screen)

//清屏

//screen: 0-全屏,1-左屏,2-右

void ClearScreen(unsigned char screen)

//显示88点阵

//旋转90度:字模被竖着切分

//lin:行(0-7), column: 列(0-15)

//address : 字模区首地址

void Show88(unsigned char lin,unsigned char column,unsigned int address)

//显示816字符

//旋转90度:字模被竖着切分

//lin:行(0-3), column: 列(0-15)

//character:字符代码(标准ASCII码)

void ShowChar(unsigned char lin,unsigned char column,unsigned char character)

//显示816字符串

//!!!只能显示在一行上即: 串长+column <=15

//旋转90度:字模被竖着切分

//lin:行(0-3), column: 列(0-15)

//address : 字模区首地址

void ShowString(unsigned char lin,unsigned char column, unsigned char string)

//显示一个汉字

//旋转90度:字模被竖着切分

//lin:行(0-3), column: 列(0-15)

//hzcode: 汉字代码(自定义的)

void ShowHZ(unsigned char lin,unsigned char column,unsigned int hzcode)

//显示

//旋转90度 :字模被竖着切分

//startline :开始行

//startcolumn:开始列

//linechar :行点除8(以88点阵为单位)

//columnchar :列点除8(以88点阵为单位)

//address : 字模区首地址

void ShowPicture(unsigned char startline,unsigned char startcolumn,unsigned char linechar,unsigned char columnchar,unsigned int address)

//!!问题大户

//显示一行汉字

//lin:行

//lineheadaddr: 此行汉字代码区首地址

void ShowLine(unsigned char lin,unsigned int lineheadaddr)

//显示一屏汉字

//pageheadaddr:此屏汉字代码地址区首地址

void ShowPage(unsigned int pageheadaddr)

//反显一个88字块

//lin:行(0-3), column: 列(0-7)

void ReverseShow88(unsigned char lin,unsigned char column)

//反显一个字符

//lin:行(0-4), column: 列(0-15)

void ReverseShowChar(unsigned char lin,unsigned char column)

//反显一个汉字

//lin:行(0-3), column: 列(0-7)

ReverseShowHZ(unsigned char lin,unsigned char column)

//反显一行汉字

//lin:行

ReverseShow(unsigned char lin)

//初始化LCD

void InitLCD()

函数列表结束 /

/----------------------------------------------------------------------------------------------------/

/--基本函数源程序------------------------------------------------------------------------------------/

//延时

Lcd12864delay()

{

unsigned int i=500;

while(i--) {;}

}

/----------------------------------------------------------------------------------------------------/

//状态检查

void CheckState()

{

unsigned char dat;

di=0;

rw=1;

do{

LCD12864DataPort=0xff;

en=1; dat=LCD12864DataPort; en=0;

dat=0x90 & dat; //仅当第4,7位为0时才可 *** 作

}while(!(dat==0x00));

}

/----------------------------------------------------------------------------------------------------/

//写显示数据

//dat:显示数据

void WriteByte(unsigned char dat)

{

CheckState();

di=1; rw=0;

LCD12864DataPort=dat;

en=1; en=0;

}

/-----------------------------------------------------------------------------------------------------/

//向LCD发送命令

//command :命令

SendCommandToLCD(unsigned char command)

{

CheckState();

rw=0;

LCD12864DataPort=command;

en=1; en=0;

}

/----------------------------------------------------------------------------------------------------/

//设定行地址(页)--X 0-7

void SetLine(unsigned char line)

{

line=line & 0x07; // 0<=line<=7

line=line 0xb8; //1011 1xxx

SendCommandToLCD(line);

}

//设定列地址--Y 0-63

void SetColumn(unsigned char column)

{

column=column &0x3f; // 0=<column<=63

column=column 0x40; //01xx xxxx

SendCommandToLCD(column);

}

//设定显示开始行--XX

void SetStartLine(unsigned char startline) //0--63

{

startline=startline & 0x07;

startline=startline 0xc0; //1100 0000

SendCommandToLCD(startline);

}

//开关显示

void SetOnOff(unsigned char onoff)

{

onoff=0x3e onoff; //0011 111x

SendCommandToLCD(onoff);

}

/---------------------------------------------------------------------------------------------------/

//选择屏幕

//screen: 0-全屏,1-左屏,2-右屏

void SelectScreen(unsigned char screen)

{ //北京显示器:负有效 cs1: 0--右; cs2: 0--左

switch(screen)

{ case 0: cs1=0;//全屏

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

cs2=0;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

break;

case 1: cs1=1;//左屏

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

cs2=0;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

break;

case 2: cs1=0;//右屏

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

cs2=1;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

break;

}

}

/---------------------------------------------------------------------------------------------------/

//清屏

//screen: 0-全屏,1-左屏,2-右

void ClearScreen(unsigned char screen)

{ unsigned char i,j;

SelectScreen(screen);

for(i=0;i<8;i++)

{ SetLine(i);

for(j=0;j<64;j++)

{

WriteByte(0x00);

}

}

}

/--------------------------------------------------------------------------------------------------/

//显示88点阵

//旋转90度:字模被竖着切分

//lin:行(0-7), column: 列(0-15)

//address : 字模区首地址

void Show88(unsigned char lin,unsigned char column,unsigned int address)

{ unsigned char i;

if(column>16) {return;}

if(column<8) SelectScreen(1); //如果列数<8(0,1,2,3,4,5,6,7)则写在第一屏上

else {

SelectScreen(2); //否则 (8,9,10,11,12,13,14,15)写在第二屏上

column=column & 0x07; //防止越界

}

SetLine(lin);

SetColumn(column<<3);

for(i=0;i<8;i++) WriteByte( CBYTE[address+i] );

}

/------------------------------------------------------------------------------------------------/

//显示816字符

//旋转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 );

}

/-----------------------------------------------------------------------------------------------/

/

//显示816字符串

//!!!只能显示在一行上即: 串长+column <=15

//旋转90度:字模被竖着切分

//lin:行(0-3), column: 列(0-15)

//address : 字模区首地址

void ShowString(unsigned char lin,unsigned char column, unsigned char string)

{ unsigned char ch;

unsigned char i=0;

while(string!=''\0'')

{

ch=string;

if(i+column >15) break; //(只能显示在一行上即: 串长+column <=15)

ShowChar(lin,i+column,ch);

string++; i++;

}

}

/

/----------------------------------------------------------------------------------------------/

//显示一个汉字

//旋转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; //lin2

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);

}

/----------------------------------------------------------------------------------------------/

//显示

//旋转90度 :字模被竖着切分

//startline :开始行

//startcolumn:开始列

//linechar :行点除8(以88点阵为单位)

//columnchar :列点除8(以88点阵为单位)

//address : 字模区首地址

void ShowPicture(unsigned char startline,unsigned char startcolumn,unsigned char linechar,unsigned char columnchar,unsigned int address)

{ unsigned char i,j;

for(i=0;i<columnchar;i++)

for(j=0;j<linechar;j++)

Show88(startline+i , startcolumn+j , address+(ilinechar+j)8 );

}

/----------------------------------------------------------------------------------------------/

//显示一行字符串(汉字,字母混排,一行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[i];

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<4;i++) ShowLine(i,pagehead[i]); //1行8个汉字,16字节

}

/----------------------------------------------------------------------------------------------------/

//读显示数据

unsigned char ReadByte()

{

unsigned char dat;

CheckState();

di=1; rw=1;

LCD12864DataPort=0xff;

en=1; dat=LCD12864DataPort; en=0;

return(dat);

}

/----------------------------------------------------------------------------------------------------/

//反显一个88字块

//lin:行(0-3), column: 列(0-7)

void ReverseShow88(unsigned char lin,unsigned char column)

{ unsigned char i;

unsigned char tab[8];

if(column<8) SelectScreen(1); //如果列数<4(0,1,2,3),则写在第一屏上

else SelectScreen(2); //否则 (4,5,6,7), 写在第二屏上

//读上部8列

column=column<<3; //每个方块88大小

SetLine(lin);

SetColumn(column);

tab[0]=ReadByte(); //空读!!!!! //

for(i=0;i<8;i++) tab[i]=~ReadByte();

//写回

SetLine(lin);

SetColumn(column);

for(i=0;i<8;i++) WriteByte(tab[i]);

}

/----------------------------------------------------------------------------------------------------/

/----------------------------------------------------------------------------------------------------/

//反显一个字符

//lin:行(0-4), column: 列(0-15)

void ReverseShowChar(unsigned char lin,unsigned char column)

{ lin=lin<<1;

ReverseShow88(lin ,column);

ReverseShow88(lin+1,column);

}

/----------------------------------------------------------------------------------------------------/

//反显一个汉字

//lin:行(0-3), column: 列(0-7)

ReverseShowHZ(unsigned char lin,unsigned char column)

{

lin=lin<<1;

column=column<<1;

ReverseShow88(lin ,column );

ReverseShow88(lin ,column+1);

ReverseShow88(lin+1,column );

ReverseShow88(lin+1,column+1);

}

/----------------------------------------------------------------------------------------------------/

//反显一行汉字

//lin:行

ReverseShow(unsigned char lin)

{ unsigned char i;

for(i=0;i<8;i++) ReverseShowHZ(lin,i);

}

/----------------------------------------------------------------------------------------------------/

void InitLCD() //初始化LCD

{ unsigned char i=250; //延时

while(i--);

//reset=0;//复位

//reset=1;

SelectScreen(0);

SetOnOff(0); //关显示

ClearScreen(1);//清屏

ClearScreen(2);

SelectScreen(0);

SetOnOff(1); //开显示

SelectScreen(0);

SetStartLine(0); //开始行:0

}

/----------------------------------------------------------------------------------------------------/

void Reset() //液晶复位

{

//reset 低复位 _ -

reset=0;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

reset=1;

//全屏

cs1=0;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

cs2=0;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

SendCommandToLCD(0x3F);

}

我怀疑你根本就没开显示。12864你用命令开了显示了吗?如果不是,看我下面所写的。

 

Proteus里的12864是个无字库纯点阵的液晶屏。我给你几个函数,因为这里不能全贴上,字数有限。只能给你几个关键的基础函数,给你太多反而看不懂,因此只给你3个。你在看懂这些函数的情况下在修改自己的函数。

proteus里的12864不需要像实际的液晶那样的有各自不同厂商的个性设置,只需要使用基本指令就够了。因此它其实初始化是很简单的,开显示就行。而实际的12864使用都是有字库的,初始化复杂。而无字库12864一般用的不多。

 

 

void _L12864Init(void)   

{

LcdWriteComOrData(0,0x3f); //显示开

 

//这个函数是应用函数,是在基础函数上构造的,意义不大,只是举个例子。

//内容是左右半屏方式,显示图像

static void ShowPicture(uchar (p)[64])//显示一张,因为是没有字符那样的局部空间,一个整体

{            //显示一页就是64列,这里64是二维数组的第二维是64

uchar i,j;

  CS1=0;CS2=1;                         //显示左半屏

  for(i=0;i<8;i++)

  {

    LcdWriteComOrData(0,AddressX|i);   //确定要显示的页 

    LcdWriteComOrData(0,AddressY);    //确定要显示的初始列,不能丢,很重要    

    for(j=0;j<64;j++) 

       LcdWriteComOrData(1, p[i<<1][j] ); //把i2变成i<<1,乘法变成移位                                            

  }

  CS1=1;CS2=0;          //换右半屏显示

  for(i=0;i<8;i++)

  {                                  

 LcdWriteComOrData(0,AddressX|i);   //page还从第0行开始

 LcdWriteComOrData(0,AddressY);

 for(j=0;j<64;j++)

    LcdWriteComOrData(1, p[(i<<1)+1][j]);

  };    

}

 

 

//下面两个是重要的基础函数,如果不显示主要是这里有问题,看懂我的看看自己的程序哪里有问题。

static void LcdWriteComOrData(uchar x,uchar content)   

{

LcdReadComBusy();     //检测忙标志

P0Data=content;

E=0;      //按照HD44780/KS0066控制器的脉冲时序走

if(x==0){RS=0;RW=0; } //如果是0,选址程序寄存器写;这种程序结构来自于金鹏LCD

else    {RS=1;RW=0; } //如果是1,选择数据寄存器写

E=1;       

Delay1ms(1);       //写程寄存器需要一段延时,执行也有延时。因为控制字写入之后,查书发现,执行至少需要40us,如果在E=1和0之间没有延时,程序不执行

E=0;      //这行和上一行Delay1ms(1)交换后,发现检测不到了,原因就是以上的延时问题。

}

//

static void LcdReadComBusy(void)  //这种程序结构来自于网友大海橡树的程序

{  

P0Data=0;    //准备读忙标志,用的是P0口,所以可以直接放低就可以了,如果用其他口,Px不能直接写0,必须先写1才能读入外部信息

RS=0;      //选择程序寄存器

RW=1;      //读

E=1;         //使能打开

while( P0Data & 0x80 ) ;    //如果是忙P0data与0x80就不等于0,所以while语句总是执行。

E=0;      //使能关闭

}

//

下面这个图是告诉你我是成功的,所以你不用怀疑我函数的正确性。

括号里的cmd是形参,数据类型与传递的参数一致,要看调用该函数的是什么函数,他所传递的数据是什么数据。

还有一种可能:

函数声明时,只需写出形参类型;

函数定义时,必须写出形参类型和变量名;

这个函数可能分开写的。注意上下文查找

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/13495924.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-09-01
下一篇2025-09-01

发表评论

登录后才能评论

评论列表(0条)

    保存