12864各种画图程序(带字库)
- 格式:doc
- 大小:131.00 KB
- 文档页数:24
带中文字库的液晶12864的C程序(C12864ZB-1)带中文字库的液晶12864的C程序(C12864ZB-1)!并口连接液晶!ftinc1ude<reg52.h>#inc1ude<math.h>void1cd_init(void);voidc1r1cd(void);voidsendcom(unsignedcharcmd);voidsenddata(unsignedchardat);voidchekbusy(void);voidsetxy(unsignedcharxpos,unsignedcharypos);voidprint(unsignedcharx,unsignedchary,char*str);voidprintstr(unsignedcharxpos,unsignedcharypos,unsignedcharstr[],unsignedcha:unsignedcharcodebuf[4]={0xbb,0xb6,0xd3,0xad};〃欢迎/********************测忙碌**********************/〃测忙碌子程序/∕RS=O,RW=I,E=H,DO-D7二状态字voidchekbusy(void){unsignedchartempi;〃状态信息(判断是否忙)C1RB(CONTRO1,RS); 〃RS=0;SETB(CONTRO1,RW); //RW=1;SETB(CONTRO1,E); //E=1;do{tempi=DATA;DATA=O X FF;}whi1e(temp1&0x80);//SETB(CONTRO1,E); //E=1;DATA=O X FF;) 口〃写命令子程序//voidsend_com(unsignedcharCmd)/*写命令*/{chek_busyO;C1R B 7C ONTRO1,RS);//RS=0;C1RB(CONTRO1,RW);//RW=0;DATA=cmd;SETB(CONTRO1,E);//E=1;C1RB(CONTRO1,E);//E=0;voidsend_data(unsignedchardat){chek_busyO;SETBteONTRO1,RS);//RS=1;C1RB(CONTRO1,RW);//RW=0;DATA=dat;SETB(CONTRO1,E);//E=1;C1RB(CONTRO1,E);//E=0;}〃复位、通讯方式选择void1cd_init(void)SETB(CONTRO1,RST);〃复位RST=I?SETB(CONTRO1,PSB); 〃通讯方式为并口PSB=1//send_com(0x34);//34H 一扩充指令操作一次送8位数据,基本指令集整体显示,游标。
#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define LCDdata P0//采用并行模式sbit E = P2^7;sbit RW = P2^6;sbit RS = P2^5;sbit RST = P2^4;sbit key1 = P2^0; //时、分、秒选择键sbit key2 = P2^1; //加一键sbit key3 = P2^2; //减一键void init();//void check_busy();void delayms(uint x);void write_com(uchar com);void write_data(uchar date);//void delay(uchar y);void t_bcd();void disp_time();void t_time();uchar code string[]={"00时00分00秒"}; uchar code tab[] ={"长春工业大学"}; uchar code tab1[]={"人文信息学院"}; uchar code tab2[]={"electronic 沈琦"};uchar time[6];//显示缓冲区uchar count;char sec,min,hour;//--------------主函数-----------------void main(){init();while(1){if(count == 200){count = 0;sec++;if(sec == 60){sec = 0;min++;if(min == 60){min = 0;hour++;if(hour == 24){hour = 0;}}}t_bcd();disp_time();}t_time();}}//-------------初始化----------------void init(){uchar i;// RST = 0;// delayms(1);// RST = 1;// delayms(40);write_com(0x30);write_com(0x0f);write_com(0x01);write_com(0x81);for(i=0;i<12;i++){write_data(string[i]);delayms(5);}write_com(0x90);for(i=0;i<16;i++){write_data(tab[i]);delayms(5);}write_com(0x8a);for(i=0;i<12;i++){write_data(tab1[i]);delayms(5);}write_com(0x98);for(i=0;i<16;i++){write_data(tab2[i]);delayms(5);}TMOD = 0x01;TH0 = (65536-5000)/256;TL0 = (65536-5000)%256;EA = 1;ET0 = 1;TR0 = 1;write_com(0x0c);}//------------毫秒延时--------------- void delayms(uint x){uchar i;while(x--){for(i=0;i<120;i++);}}/*//--------------判忙程序--------------- void check_busy(){// LCDdata = 0xff;RS = 0;RW = 1;// E = 0;E = 1;LCDdata = 0xff;while(LCDdata&0x80);E = 0;}*///------------写命令----------------- void write_com(uchar com){// check_busy();RS = 0;RW = 0;E = 0;LCDdata = com;// delayms(5);E = 1;delayms(5);E = 0;}//-------------写数据------------------ void write_data(uchar date){// check_busy();RS = 1;RW = 0;E = 0;LCDdata = date;// delayms(5);E = 1;delayms(5);E = 0;}//-----------定时中断0------------- void timer0() interrupt 1{TH0 = (65536-5000)/256;TL0 = (65536-5000)%256;count++;}void t_bcd(){time[0] = sec%10;time[1] = sec/10;time[2] = min%10;time[3] = min/10;time[4] = hour%10;time[5] = hour/10;}//--------------时钟时间显示----------------- void disp_time(){write_com(0x85);write_data(0x30+time[1]);write_data(0x30+time[0]);write_com(0x83);write_data(0x30+time[3]);write_data(0x30+time[2]);write_com(0x81);write_data(0x30+time[5]);write_data(0x30+time[4]);}//------------调整时间程序--------------- void t_time(){static uchar num;if(key1 == 0){delayms(5);while(!key1);TR0 = 0;num++;}//-----------------调时-----------------if(num == 1){write_com(0x81);write_com(0x0f);if(key2 == 0){delayms(5);if(key2 == 0){while(!key2);hour++;if(hour == 24){hour = 0;}t_bcd();write_data(0x30+time[5]);write_data(0x30+time[4]);}}if(key3 == 0){delayms(5);if(key3 == 0){while(!key3);hour--;if(hour == -1){hour = 23;}t_bcd();write_data(0x30+time[5]);write_data(0x30+time[4]);}}}//-----------------调分----------------------if(num == 2){write_com(0x83);if(key2 == 0){delayms(5);if(key2 == 0){while(!key2);min++;if(min == 60){min = 0;}t_bcd();write_data(0x30+time[3]);write_data(0x30+time[2]);}}if(key3 == 0){delayms(5);if(key3 == 0){while(!key3);min--;if(min == -1){min = 59;}t_bcd();write_data(0x30+time[3]);write_data(0x30+time[2]);}}}//---------------调秒------------------if(num == 3){write_com(0x85);if(key2 == 0){delayms(5);if(key2 == 0){while(!key2);sec++;if(sec == 60){sec = 0;}t_bcd();write_data(0x30+time[1]);write_data(0x30+time[0]);}}if(key3 == 0){delayms(5);if(key3 == 0){while(!key3);sec--;if(sec == -1){sec = 59;}t_bcd();write_data(0x30+time[1]);write_data(0x30+time[0]);}}}//---------------退出调整时间----------------- if(num == 4){num = 0;write_com(0x0c);TR0 = 1;}}。
带字库的LCD12864自定义图片、汉字显示
一、将图片修改成128*64像素
1、打开win7自带的画图软件,载入图片(图片不满足128*64)
2、点击重新调整大小(或者图片处右击鼠标),如下设置,保持纵横比不勾选。
3、图片另存为,选择单色位图。
二、LCD12864用ZIMO21软件取模(BMP图片)
1、基本设置里面设置LCD的大小(如果图片像素就是128*64就不需要设置,直接打开)
2、打开BMP图片(黑白)
3、发现图片偏小,不足128*64,此时生成的数据就缺少128*64个点,显示会照成错误,需要修改一下图片大小。
改成128*64
3、直接调入128*64图片
4、设置参数,如下
5、取模选择C51格式
6、显示效果
三、PCtoLCD2002图片取模设置
四、PCtoLCD2002汉字取模设置(根据程序而定)
1、汉字取模参数设置
2、显示效果如下。
/****************************************屏幕显示驱动*****************************************/#include "GT23L24T3Y.h"#include "print.h"#include <stdio.h>#include <string.h>#include "bmp_picture.h"#include "lcd_12864.h"#include "..\user\rtc.h"u8 comTable[]={4,5,6,7,3,2,1,0};extern void Setlcd_Addr ( u8 row,u8 column );//外部函数调用声明extern u8 Num_Code[];//字库获得函数extern u8 Big_Num_Code[];//字库获得函数extern u8 Picture_Code[];//字库获得函数extern u8 arrow1[];extern u8 arrow2[];u8 testlcd[]="测试数据";/************************************************************************//显示中文输出//函数名:print_16//功能:显示16x16点阵字符串。
// 函数名:print_16// 功能:显示16点阵字符串// 形参:// row:x轴// column:y轴// *lcd:显示字符串// logic:显示取反// wei.显示位值// len长度*************************************************************************/void _print_15 ( u8 row,u8 column,const char *lcd,u8 logic ,u8 wei,u8 len){u8 w=0,x=0,y=0,l=0,read_data=0;u8 Length=0;GT_cs1;//字库片选至高for ( l=len; l>0; l=l-2 ) //总字节{w=*lcd;if ( w&0x80 ) //为1则为汉字,为0则为ASCII码{GT_cs0; //字库片选选定GT23_Write ( GT23_write_15 ( lcd ) ); //写入字库指令以及文字地址for ( x=0; x<2; x++ ){Setlcd_Addr (row,column);for(y=0;y<16;y++){read_data=GT23_Read();if(logic == true){// read_data = ~read_data;}WriteData(read_data );}row++;}GT_cs1;//字库片选至高row-=2;column+=16;if(column>=128){row+=2;column=0;}lcd=lcd+2;}}}/************************************************************************//描述:显示中文输出//使用:顶层函数调用参数:row 行column 列*lcd 字符串logic 反白*************************************************************************/ void print_15 ( u8 row,u8 column,const char *lcd,u8 logic ){u8 c=strlen ( lcd );_print_15(row,column,lcd,logic,0,c);}/************************************************************************ //描述:显示图片输出//使用:顶层函数调用参数:row 行column 列*lcd 字符串logic 反白*************************************************************************/ void print_array(u16 row,u16 column,u16 size_x,u16 size_y,const u8 *ptr, u8 logic){u8 w=0,x=0,y=0,l=0,read_data=0;u8 Length=0;for( x=0;x<size_x/8;x++){Setlcd_Addr (row,column);for(y=0;y<size_y;y++){read_data=*( ptr + (y+x*size_y) );if(logic == true){read_data = ~read_data;}WriteData1(read_data);// WriteData1(0XFF);}row++;}}u8 OpMgsCode[][10] ={"病人信息","循环播放","房号与床号","从机音量","对比度","广播""恢复","音乐","主机音量","时间"};u8 DayCode[][7]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};void PrintMainFace(time mytime,u8 PeopleNum){//待机界面函数u8 Hrd,Ten,One;Lcd_Clr();//清屏print_15 ( 0,16, "月",false );print_15 ( 0,48, "日",false );print_15 ( 0,70, &DayCode[mytime.day][0],false );//显示星期//日期显示Ten=mytime.month/10;One=mytime.month%10;print_array(0 , 0, 16 , 7 , &Num_Code[Ten*14], false);print_array(0 , 8, 16 , 7 , &Num_Code[One*14], false);Ten=mytime.date/10;One=mytime.date%10;print_array(0 , 32, 16 , 7 , &Num_Code[Ten*14], false);print_array(0 , 40, 16 , 7 , &Num_Code[One*14], false);//时间显示Ten=mytime.hour/10;One=mytime.hour%10;print_array(2 , 20, 32 , 21 , &Big_Num_Code[Ten*84], false);print_array(2 , 42, 32 , 21 , &Big_Num_Code[One*84], false);Ten=mytime.minute/10;One=mytime.minute%10;print_array(2 , 68, 32 , 21 , &Big_Num_Code[Ten*84], false);print_array(2 , 90, 32 , 21 , &Big_Num_Code[One*84], false);//住院人数显示print_15 ( 6,32, "住院人数",false );Hrd=PeopleNum/100;PeopleNum=PeopleNum%100;Ten=PeopleNum/10;One=PeopleNum%10;if(Hrd ){print_array(6 , 96, 16 , 7 , &Num_Code[Hrd*14], false);}print_array(6 , 102, 16 , 7 , &Num_Code[Ten*14], false);print_array(6 , 110, 16 , 7 , &Num_Code[One*14], false);}void PrintPictureFace(u8 Index){time mytime;Lcd_Clr();//清屏mytime.month = 10;mytime.date = 16;mytime.hour = 12;mytime.minute = 15;mytime.day =3;PrintMainFace(mytime,96);//print_array(0 , 10, 48 , 8 , arrow1, false);//左箭头显示// print_array(0,38 ,48 ,48 , &Picture_Code[288*Index], false);//图片显示// print_array(0,108, 48 , 8 , arrow2, false); //右箭头显示//print_15 ( 6,33, &OpMgsCode[0][Index],false );//提示信息显示}。
FYD12864液晶中文显示模块(一) (一)概述 (3)(二)(二)外形尺寸1 方框图 (3)2 外型尺寸图 (4)(三)(三)模块的接口 (4)(四)(四)硬件说明 (5)(五) 指令说明 (7)(五)(五)读写操作时序 (8)(六)(六)交流参数 (11)(七)(七)软件初始化过程 (12)(八)(八)应用举例 (13)(九)(九)附录1半宽字符表 (20)2 汉字字符表 (21)一、概述FYD12864-0402B是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。
可以显示8×4行16×16点阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。
由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
基本特性:●●低电源电压(VDD:+3.0--+5.5V)●●显示分辨率:128×64点●●内置汉字字库,提供8192个16×16点阵汉字(简繁体可选)●●内置 128个16×8点阵字符●●2MHZ时钟频率●●显示方式:STN、半透、正显●●驱动方式:1/32DUTY,1/5BIAS●●视角方向:6点●●背光方式:侧部高亮白色LED,功耗仅为普通LED的1/5—1/10 ●●通讯方式:串行、并口可选●●内置DC-DC转换电路,无需外加负压●●无需片选信号,简化软件设计●●工作温度: 0℃ - +55℃ ,存储温度: -20℃ - +60℃二、方框图3、外形尺寸图三、模块接口说明*注释1:如在实际应用中仅使用串口通讯模式,可将PSB接固定低电平,也可以将模块上的J8和“GND”用焊锡短接。
在此指出,这一篇文章出至网络上zhaoshan413之手,感谢他的无私贡献,让大家轻松玩转带字库12864!~~[p=30, 2, left]之前说学完12864字库液晶后和大家交流一下心得,一直没有时间,今天整理一下发上来,希望对想学习的朋友能有点帮助…首先说明一点,本人也是初学者,自感水平不高,若有不足及不对之处,望情指正…以下以并行口传输为例,别的还不会,呵呵![/p][p=30, 2, left]先传一下ST7920的芯片说明书:[/p][p=30, 2, left]/bbs/redirect.php?tid=7676&goto=lastpo st#lastpost[/p][p=30, 2, left]ST7920(字库)12864.pdf(2010-12-01 10:46:58, Size: 1.65 MB, Downloads: 1689)[/p][p=30, 2, left]一、首先说一下关于驱动函数的书写,这些是液晶显示的基础一般包括四个函数:1、写命令函数;2、写数据函数;3、读状态函数;4、读数据函数;这四个函数并不是必须全部写的,具体要看你实现的功能,如果只是单纯的显示汉字和字符,写命令、写数据、读状态这三个函数就够了,如过你还需要进行一些绘图的操作,那读数据函数也必须书写。
另外关于读状态函数,其实也就是用于判忙操作,我看郭天祥的书里面是这样说的:原则上每次对控制器进行读写操作之前,都必须进行读写检测,由于单片机的操作速度慢于液晶控制器的反应速度,因此可不进行读写检测,或者只进行简短的延时即可。
因此,读状态函数也可以不写,只用简短的延时函数替换即可。
1、写操作的编写:首先看一下时序图[/p][p=30, 2, left]时序.JPG[/p][p=30, 2, left]由图可见操作很简单:1>RS=1(写数据操作);或者RS=0(写命令操作);2>RW=0;//指明为写操作3>E=1;4>DB=data;//data为你要写入的命令或数据值5>E=0;[/p][p=30, 2, left]以下是我的驱动函数,仅供参考:[/p][p=30, 2, left]CODE:/********************************液晶端口定义**************************/#define lcd_data P0 //数据口sbit RS = P2^4; //选择寄存器(并行) 0:指令寄存器1:数据寄存器;sbit RW = P2^5; //读写控制脚(并行) 0:写入 1:读出sbit E = P2^6; //读写数据启始脚(并行)sbit PSB = P2^1; //串并方式选择引脚,0为串行模式,1为8/4位数据口模式sbit RST = P2^3; //复位引脚//******************************************************* *//延时函数//******************************************************* *void delay(unsigned int k){unsigned int i;unsigned char j;for(i=0;i<k;i++){for(j=0;j<10;j++);}}//******************************************************* *//延时1ms函数//******************************************************* *void delay_ms(unsigned int k)//延时0.994us,晶振12M{unsigned int x,y;for(x=k;x>0;x--)for(y=121;y>0;y--);}//******************************************************* *//写命令函数//******************************************************* *void LcdWcom(unsigned char WCom){delay(1);RS=0; //指明操作对象为指令寄存器RW=0; //指明为写操作E=1;lcd_data=WCom; //将命令写入总线E=0;}//******************************************************* *//写数据函数//******************************************************* *void LcdWdata(unsigned char WData){delay(1);RS=1; //指明操作对象为数据寄存器RW=0; //指明为写操作E=1;lcd_data=WData; //将数据写入总线E=0;}[/p][p=30, 2, left]二、初始化操作[/p][p=30, 2, left]以8位并行操作为例,操作流程图如下:[/p][p=30, 2, left]初始化.JPG[/p][p=30, 2, left]初始化操作如下:[/p][p=30, 2, left]1>芯片上电;[/p][p=30, 2, left]2>延时40ms以上;[/p][p=30, 2, left]3>复位操作:RST出现一个上升沿(RST=1;RST=0;RST=1;);[/p][p=30, 2, left]4>功能设定;[/p][p=30, 2, left]5>延时100us以上;[/p][p=30, 2, left]6>再次进行功能设定;[/p][p=30, 2, left]7>延时37us;[/p][p=30, 2, left]8>显示开关控制;[/p][p=30, 2, left]9>延时100us 以上;[/p][p=30, 2, left]10>清除显示;[/p][p=30, 2, left]11>延时10ms以上;[/p][p=30, 2, left]12>进入点设置;[/p][p=30, 2, left]13>初始化结束;[/p][p=30, 2, left]这里我遇到了一个小问题,我的液晶按照这个顺序进行初始化结果不正确,无法显示,最后我把调整了一下就可以了,调整后的顺序为:清除显示进入点设置显示开关控制,不知道是什么原因,知道的告诉我一声…[/p][p=30, 2, left]CODE://******************************************************* *//显示初始化函数//******************************************************* *void Display_Init(void){delay_ms(45); //延时45msPSB=1; //8位并行口//复位操作RST=1;delay(1);RST=0;delay(1);RST=1;delay(1);//功能设定LcdWcom(0x30); //设置为8位并行口,基本指令集delay(10);LcdWcom(0x30); //再次设置为8位并行口,基本指令集delay(5);// //显示开关控制// LcdWcom(0x0c); //游标显示关,正常显示,整体显示开// delay(10);//清除显示LcdWcom(0x01);delay_ms(12); //延时12ms//进入点设置LcdWcom(0x06); //设置为游标右移,DDRAM位地址加1,画面不移动delay(5);LcdWcom(0x0C); //开显示}[/p][p=30, 2, left]三、显示基本的字符和汉字[/p][p=30, 2, left]1、要想显示汉字或字符,首先要确定显示的位置,看看芯片说明书上关于屏幕地址的分配:[/p][p=30, 2, left]DDRAM位址.JPG[/p][p=30, 2, left]由于此液晶为128*64,即是横向128个点,竖向64个点,由于该液晶控制器支持的字符为8*16,汉字为16*16,因此只能显示四行,如果是汉字,为每行显示8个,如果是字符,每行显示16个。
#include <reg51.h>#include <intrins.h>#include <ADC0808.c>sbit DI=P2^2; // 数据\指令选择sbit RW=P2^1; // 读\写选择sbit E=P2^0; // 读\写使能sbit CS1=P2^4; // 片选1sbit CS2=P2^3; // 片选2sbit busy=P1^7;sbit jia=P3^7;sbit jian=P3^3;sbit jia1=P3^0;sbit jian1=P3^1;unsigned int i;unsigned char ye,lei,shu; unsigned char a[94];char code t[]={0x00,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x40,0x60,0x80,0x00,0x7F,0xFF, //小0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x80,0x01,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x82,0x00,0x82,0x00,0x82,0x40,0x82,0x80,0x82,0x7F,0xE2, //子0x00,0xA2,0x00,0x92,0x00,0x8A,0x00,0x86,0x00,0x80,0x00,0xC0,0x00,0x80,0x00,0x00,0x00,0x40,0x00,0x60,0x3F,0x5E,0x01,0x48,0x01,0x48,0xFF,0xFF,0x11,0x48,0x21,0x4C, //制0x1F,0x68,0x00,0x40,0x07,0xF8,0x40,0x00,0x80,0x00,0x7F,0xFF,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x20,0xFF,0xF8,0x00,0x87,0x00,0x40,0x00,0x30,0x00,0x0F, //作0xFF,0xF8,0x08,0x88,0x08,0x88,0x08,0xC8,0x0C,0x88,0x08,0x0C,0x00,0x08,0x00,0x00,};void checkstate(){//bit dat;DI=0;RW=1;//P1=0x00;do{E=1;E=0;//仅当第7位为0时才可操作(判别busy信号)}while(busy==1);}void writecommand(unsigned char command) //写命令{checkstate();DI=0;RW=0;P1=command;E=1;E=0;}void writedate(unsigned char date) //写数据{checkstate();DI=1;RW=0;P1=date;E=1;E=0;}void pianxuan(unsigned int i){if(i==1)CS1=0,CS2=1;if(i==2)CS1=1,CS2=0;if(i==3)CS1=0,CS2=0;}void cleanscreen() //清屏{unsigned char page,i;for(page=0xb8;page<0xc0;page++){writecommand(page);writecommand(0x40);for(i=0;i<64;i++)writedate(0x00);}}void init(void) //开显示,起始行0行{writecommand(0xc0);writecommand(0x3f);}void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}void shuju(){pianxuan(i); writecommand(ye); writecommand(lei); writedate(shu);}void qing(){uchar i;for(i=0xb8;i<=0xbf;i++) {ye=i;shu=0x00;shuju();}}void main(){uint r,j,g=0,q,dianya=1,k,p;uchar U,m,l;pianxuan(3);cleanscreen();init();pianxuan(2);l=0xb8;for(k=0;k<4;k++,l=l+0x02){ye=l;lei=0x70;for(r=0;r<16;r++){shu=t[2*r+1+32*k];shuju();lei++;}ye=l+0x01;lei=0x70;for(r=0;r<16;r++){shu=t[2*r+32*k];shuju();lei++;}}while(1){uchar d1,d2,d3,d4,d5;aaa:do{adc();}while((AD!=128)&&(AD!=129)&&(AD!=130));U=AD;adc();if(U>AD)goto aaa;while(jia==0){while(jia==0);g=g+1;}while(jian==0){while(jian==0);if(g!=0) g=g-1;}while(jia1==0){while(jia1==0);dianya=dianya+1;}while(jian1==0){while(jian1==0);if(dianya!=1) dianya=dianya-1;}for(j=0;j<94;j++) //AD采样{adc();a[j]=AD;delay_50us(g);}lei=0x40;for(r=0,j=0;r<94;r++,j++){if(j<64) i=1;if(j==64) lei=0x40;if(j>=64)i=2;qing(); //清掉之前的内容AD=a[j]*0.196/dianya; //计算在12864的电压值if(AD<=7) ye=0xbf,shu=(0x80>>AD); else if(AD<=15) ye=0xbe,shu=0x80>>(AD-8); else if(AD<=23) ye=0xbd,shu=0x80>>(AD-16); else if(AD<=31) ye=0xbc,shu=0x80>>(AD-24); else if(AD<=39) ye=0xbb,shu=0x80>>(AD-32); else if(AD<=47) ye=0xba,shu=0x80>>(AD-40); else if(AD<=55) ye=0xb9,shu=0x80>>(AD-48); else if(AD<=63) ye=0xb8,shu=0x80>>(AD-56);if(r==0){d1=shu;d2=ye;}if(r!=0){d3=shu;d4=ye;if(ye==d2){if(shu>d1){d5=shu;d5=d5>>1;while(d5!=d1){d5=d5>>1;shu=shu|(shu>>1);}}if(shu<d1){d5=shu;d5=d5<<1;while(d5!=d1){d5=d5<<1;shu=shu|(shu<<1);}}if(ye<d2){for(q=0;q<7;q++){shu=shu|(shu<<1);}shuju();ye++;while(ye<d2) {shu=0xff,shuju(),ye++;}if(ye==d2){shu=0x01;if(shu<d1){d5=shu;d5=d5<<1;while(d5!=d1){d5=d5<<1;shu=shu|(shu<<1);}}}}if(ye>d2){for(q=0;q<7;q++){shu=shu|(shu>>1);}shuju();ye--;while(ye>d2) {shu=0xff,shuju(),ye--;}if(ye==d2){shu=0x80;if(shu>d1){d5=shu;d5=d5>>1;while(d5!=d1){d5=d5>>1;shu=shu|(shu>>1);}}}}}if(r!=0)d1=d3;d2=d4;}shuju();if(lei!=0x7f) lei++; }}}。
金鹏科技有限公司Golden Palm Science Technology Co.,Ltd目录一、OCM4X8C液晶显示模块概述 (1)二、模块引脚说明 (1)1)表—1:OCM2X8C(128X32)、OCM2X10C(160X32)模块引脚说明 (1)2)表—2:OCM2X8C-2(128X32)模块引脚说明 (1)3)表—3:OCM4X8C(128X64)引脚说明 (1)4)表—4:OCM4X16A(256X64)引脚说明 (2)三、OCM4X8C液晶硬件接口 (2)1、8位并行连接时序图 (2)2、串行连接时序图 (3)3、AC电气特性(TA=25℃V CC=5V) (3)四、用户指令集 (4)五、显示坐标关系 (7)1、图形显示坐标 (7)2、汉字显示坐标 (8)3、字符表 (8)六、显示步骤 (9)七、显示示例程序 (9)1、发送子程序 (9)2、读子程序 (10)八、模块尺寸图 (12)附:汉字字符集三、OCM4X8C液晶硬件接口1、逻辑工作电压(VDD):4.5~5.5V2、电源地(GND):0V3、LCD驱动电压(V0):0~-10V4、工作温度(Ta):0~55℃(常温) / -20~70℃(宽温)保存温度(Tstg):-10~65℃(常温)5、电气特性见附图1 外部连接图(参考附图2)模块有并行和串行两种连接方法(时序如下):1、8位并行连接时序图MPU写资料到模块备注:六、显示步骤1、显示资料RAM(DDRAM)显示资料RAM提供64×2个位元组的空间,最多可以控制4行16字(64个字)的中文字型显示,当写入显示资料RAM时,可以分别显示CGROM、HCGROM与CGRAM 的字型;ST7920A可以显示三种字型,分别是半宽的HCGROM字型、CGRAM字型及中文CGROM字型,三种字型的选择,由在DDRAM中写入的编码选择,在0000H—0006 H的编码中将自动的结合下一个位元组,组成两个位元组的编码达成中文字型的编码(A140—D75F),各种字型详细编码如下:1、显示半宽字型:将8位元资料写入DDRAM中,范围为02H—7FH的编码。
带字库12864绘图说明一、用带字库12864LCD屏绘图首先要对其绘图寄存器GDRAM地址了解清楚。
如图所示绘图寄存器GDRAM地址由水平地址(LCD_X)和垂直地址(LCD_Y)组成;如上图所示,水平地址共有16个(0x80~0x8f),其中上半屏起始地址为0X80,下半屏起始地址为0X88每个水平地址对应16列,上下半屏各有8个水平地址,所以一屏总共有128列.垂直地址共有32个(0x80~0x9f),因为上下半屏的垂直地址一样所以实际上一屏总共有64行。
特别注意:虽然一屏有128列,但并不是每列都有它的地址。
其实,从左往右每16列为一“大列”,有一个水平地址。
送数据时只要将该“大列”的水平地址和垂直地址送入12864,然后紧接这写如两个字节的内容,就可将这两个字节的内容显示在这一“大列”的16位上(先送高位,再送低位;显示时左面8位为高位)。
二、写入绘图RAM的步骤按照上面的步骤写了一个绘图地址的函数void wr_address( void)//送地址函数{write_com(0x34);//附加功能使能write_com(LCD_Y);//送入垂直地址write_com(LCD_X);//送入水平地址write_com(0x30);//禁止附加功能}下面是一个清屏函数(注意:绘图的清屏与显示汉字的清屏不同,手册中的清屏指令只能清楚DDRAM的内容,但无法清楚GDRAM的内容。
绘图清屏其实就是向GDRAM中写如0x00)void show3(void)//绘图清屏{uchar i,j,k;LCD_X=0X80;for(i=0;i<2;i++){LCD_Y=0X80;for(j=0;j<32;j++){wr_address();//写入起始地址for(k=0;k<16;k++)//连续写入16个字节(一行写满),每写入两个字节LCD_X会自动加1write_data(0x00);LCD_Y++;//垂直地址不会自动加1,写完一行后要程序换行}LCD_X=0X88;}write_com(0x36);write_com(0x30);}三、用带字库的LCD屏显示波形实例A、大致步骤1、绘图清屏2、AD转换器对波形采样,并将采样值定义在0~63之间,依次存入容量为128字节的一个数组中3、从数组中依次取出数据,送入GDRAMB、设计难点1、如何在屏上显示高低不同的点2、如何将不规则、无规律的点用字节的形式送显示3、怎样用AD转换的结果来控制显示的波形C、解决方案1、本次设计的核心思想就是将LCD屏看作一个128*64的点阵屏,从左往右循环送入uint code tab2[]={0x8000,0x4000,0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0008,0x0004,0x0002,0x000 1};的内容,这些点的高低由它们的垂直坐标LCD_Y决定;我们用AD 转换结果的128个字节的内容与128列一一对应,这写结果作为它们对应列上点的垂直坐标(注意,这些结果还要少做处理后才能作为垂直坐标,具体见下面程序)2、上面的做法会出现一个问题,那就是在一个“大列”中(一个水平坐标内)的16个点如果在同一行上出现两个以上的点,那么前面的点将不会显示(例如,在水平地址为0x80的这一“大列”中,第一列和第三列同在第三行,那么在显示第一列的点时地址为(0x80,0x82)的GDRAM中送入的数据是0x8000,而在显示第三列时,该GDRAM要送入的数据为0x2000;最终该GDRAM为0x2000,所以第一列的点在屏上就显示不出来了)。
LCD12864带中文字库图形显示-单片机程序(多图)代码:#include ;#define uchar unsigned charsbit rs=P2^2;//写指令/数据sbit rw=P2^3;//读状态/写sbit e=P2^4;//使能端sbit psb=P2^5;//串/并输入//校徽unsigned char code image[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x07,0xF4,0xFC,0x7E,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x0D,0xF0,0xFC,0xFF,0x80,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x13,0xF0,0x78,0x7F,0xC0,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x75,0xF7,0xFF,0xFC,0xE0,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xF8,0xF8,0x00,0xF9,0x78,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x01,0xFD,0xCF,0xFF,0x1E,0xFC,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFA,0x3F,0xFF,0x66,0xFE,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x07,0xFD,0xFF,0xFD,0x79,0xFF,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x0E,0xF3,0xFF,0xFA,0xFE,0xF0,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x18,0x2F,0xFF,0xF0,0xFF,0x69,0x80,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x3E,0xBF,0xFF,0x93,0xFF,0xDF,0xE0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x7F,0x7F,0xFF,0x9F,0xFF,0xEF,0xE0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x7F,0x7E,0x07,0x9F,0x07,0xF7,0xF0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFE,0xFF,0x00,0x00,0x0F,0xF3,0xF0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFD,0xFF,0x80,0x00,0x1F,0xFB,0xF8,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFD,0xFF,0xE0,0x00,0x3F,0xFD,0xF8,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFB,0xF9,0xE0,0x00,0x79,0xFD,0xFC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFB,0xFC,0x10,0x00,0x81,0xFD,0xFC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xFB,0xFE,0x00,0x02,0x03,0xFE,0xFC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xF7,0xFE,0x00,0x00,0x07,0xFE,0xFC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xF7,0xF0,0x40,0xF8,0x10,0x7E,0xFE,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xF7,0xF0,0x00,0x00,0x00,0xFF,0x7E,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xF7,0xFC,0x00,0x00,0x01,0xFF,0x7E,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x37,0xFE,0x00,0x00,0x07,0xFF,0x72,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x77,0xFF,0x80,0x00,0x0F,0xFF,0x5E,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xF7,0xF3,0xE0,0x00,0x7D,0xFF,0x7E,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x06,0x37,0xFC,0x7F,0x07,0xE1,0xFF,0x5E,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x02,0xF7,0xFE,0xBF,0x07,0xCB,0xFF,0xC6,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xF7,0xFC,0x1E,0x06,0x1F,0xFE,0xFE,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x02,0x37,0xFD,0x0F,0xD9,0x1F,0xFE,0xC4,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x1B,0xFE,0x80,0x00,0x3F,0xFE,0xEC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFB,0xFF,0xC0,0x00,0xFF,0xFD,0xFC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xD9,0xFF,0xA8,0x0B,0xFF,0xFD,0xBC,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xED,0xFF,0xFC,0x0B,0xFF,0xFB,0xE8,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xEC,0xFF,0xFE,0x8F,0xFF,0xFB,0x28,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xCE,0xFF,0xFF,0xDF,0xFF,0xF7,0xD0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x73,0x7F,0xFF,0xDF,0xFF,0xE7,0x30,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x6F,0xBF,0xFE,0x8B,0x23,0xEE,0xE0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x37,0x9F,0xED,0xFF,0xFF,0xDD,0xC0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xCF,0xBF,0xFF,0xFD,0xBA,0xC0,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x1E,0xE5,0x7F,0xFF,0xFE,0x79,0x80,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x0D,0x7B,0xFE,0x63,0xFC,0xDB,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x06,0x3C,0xFE,0x27,0xF3,0xFE,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0x5F,0x1F,0xFF,0xCF,0x5C,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x01,0xEB,0xE3,0xFC,0x3C,0x78,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xDB,0xFC,0x03,0xFB,0x30,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x3E,0xDF,0xFF,0x9D,0xE0,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x1F,0xBB,0xFC,0xFD,0xC0,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0xAA,0xBE,0xBF,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x03,0xEE,0xBE,0xBC,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x7E,0x9F,0xF0,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF ,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,};void delay(int i){uchar j;while(i--)for(j=110;j>;0;j--);}//读状态,检测忙void check_busy(){rs=0;rw=1;e=1;P0=0xff;while((P0&0x80)==0x80);e=0;}//写指令void write_com(uchar com) {check_busy();rs=0;rw=0;e=1;P0=com;delay(5);e=0;delay(5);}//写数据void write_data(uchar _data) {check_busy();rs=1;rw=0;e=1;P0=_data;delay(5);e=0;delay(5);}//初始化lcdvoid init(){rw=0;psb=1;//选择为并行输入delay(50);write_com(0x30);//基本指令操作delay(5);write_com(0x0c);//显示开,关光标delay(5);write_com(0x06);//写入一个字符,地址加1 delay(5);write_com(0x01);delay(5);}void wstring(uchar *str){while(*str){write_data(*str);delay(5);str++;}}void lcd_draw(unsigned char code *pic) {unsigned i,j,k;write_com(0x34);//扩充指令集for(i=0;i绘图更好的一个算法:(可以绘分块,也可绘全屏)void lcd_block(char num,char flag){//x1:列数,yl:行数,x:列坐标,//sx:该图形距离第一幅图的距离//此函数也可以用来画全屏图unsigned i,j,k,xl,yl,x,y,sx;unsigned char code *pic;switch(num){case 0: j=0;pic=image0;xl=5;yl=12;sx=3;x=0x80|sx;break;case 1:j=13;pic=image4;xl=4;yl=37;sx=0;x=0x80|sx;break; case 2:j=13;pic=image4;xl=4;yl=37;sx=3;x=0x80|sx;break; case 3:j=13;pic=image4;xl=4;yl=12;sx=6;x=0x80|sx;break; case 4: j=7;pic=image4;xl=4;yl=31;sx=0;x=0x88|sx;break;case 5: j=7;pic=image5;xl=4;yl=31;sx=3;x=0x88|sx;break;case 6: j=7;pic=image5;xl=4;yl=31;sx=6;x=0x88|sx;break;case 7: j=0;pic=image7;xl=16;yl=64;sx=0;x=0x80|sx;break;}write_com(0x34);for(j;j;31) {y=j-32;x=0x88|sx;} else y=j;write_com(0x80+y);write_com(x);for(k=0;k<xl;k++){if(flag)write_data(*pic++);else write_data(~(*pic++));}}/*for(j;j<yl;j++){write_com(0x80+j);write_com(x);for(k=0;k<xl;k++){if(flag)write_data(*pic++);else write_data(~(*pic++));}}*/write_com(0x36);//显示图形write_com(0x30);//基本指令集}。
#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charsbit rs=P2^4; //1为数据选择,0为指令选择sbit rw=P2^5; //控制读与写sbit lcden=P2^6; //使能端sbit PSB=P2^1; //串并接口方式选择,1为并方式,0为串方式uchar table[]={"筱路fighting go!"};uchar i;void delay(uint z) //延时公式Z ms{ uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delay_us(uchar t) //延时公式大约50t us{ uchar i,j;for(i=t;i>0;i--)for(j=5;j>0;j--);}void read_lcdbf(){ uchar temp;P0=0xff;do{ lcden=0;rs=0;rw=1;_nop_();lcden=1;_nop_();temp=P0; //读数据须在下降沿读出,读时,要在使能端为高电平时间lcden=0;}while(temp&0x80);}void write_com(uchar com) //写指令{rs=0;rw=0;lcden=0;P0=com;lcden=1;delay_us(1);lcden=0;read_lcdbf();}void write_date(uchar date) //写数据,都是并口的{rs=1;rw=0;lcden=0;P0=date;lcden=1;lcden=0;read_lcdbf();}void init() //八位软件初始化{ delay(100);PSB=1; //选择并行接口write_com(0x30); //基本指令操作delay_us(4);write_com(0x0c); //只开显示delay_us(4);write_com(0x01); //清屏指令delay(15);write_com(0x06); //游标每写完一个字指针就加一delay(5);write_com(0x80);}/*防止花屏,在画点前应该先清除GDRAM显示,记住水平方向是以字节为单位的,垂直方向以位为单位,所以一行行清除时,会出错*/void clear_GDRAM(){ uchar i,j,lcd_x=0x80,lcd_y=0x80,k;write_com(0x34); //因启用了GDRAM,所以需开扩展指令for(i=0;i<2;i++){ for(j=0;j<32;j++) //因垂直坐标有32位{write_com(lcd_y+j); //一行行的清除for(k=0;k<16;k++) //水平有16个字节{ write_date(0x00); //依次清除它们,水平方向地址会自动加一delay_us(1);}}lcd_x=0x88;}write_com(0x36);write_com(0x30);}void write_image(uchar *p){ uchar i,j,lcd_x=0x80,lcd_y=0x80,k;write_com(0x34); //因启用了GDRAM,所以需开扩展指令for(i=0;i<2;i++){ for(j=0;j<32;j++) //因垂直坐标有32位{ write_com(lcd_y+j); //一行行的清除write_com(lcd_x); //因for(k=0;k<16;k++) //水平有16个字节{ write_date(*p++); //依次清除它们,水平方向地址会自动加一delay_us(1);}}lcd_x=0x88;}write_com(0x36);write_com(0x30);}void lcd_pos(uchar x,uchar y) //设定显示位置,在第x行,且在x行的第y个字符显示{ uchar pos;switch (x){ case 1: x=0x80; break;case 2: x=0x90; break;case 3: x=0x88; break;case 4: x=0x98; break;}pos=x+y ;write_com(pos);}uchar code image[]={0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xAE,0x90,0x00,0x00,0x95,0x55,0x48,0x80,0x00,0x00,0x00,0x00,0x2B,0x55,0x00,0x00,0x00,0xA8,0x00,0x22,0x15,0x20,0x00,0x00,0x00,0x97,0xFB,0x00,0x00,0x00,0x45,0x55,0x08,0xA0,0x00,0x00,0x00,0x0A,0x6F,0x04,0x40,0x00,0x00,0xBA,0xE0,0x00,0x00, 0x00,0x4D,0x55,0x15,0x15,0x20,0x00,0x00, 0x95,0xD5,0x00,0x00,0x00,0x00,0xFF,0xE8, 0x40,0x40,0x00,0x00,0x00,0x4A,0xAA,0x80, 0x00,0x00,0x00,0xFF,0xFF,0x2A,0x00,0x40, 0x00,0x00,0x15,0x54,0x00,0x00,0x00,0x00,0xFF,0xFD,0xD0,0xAA,0x01,0x00,0x00,0x25, 0x20,0x10,0x00,0x00,0x00,0xFF,0xFF,0xB6, 0x00,0x10,0x00,0x01,0x4A,0x49,0x00,0x00, 0x00,0x00,0xFF,0xFF,0xFD,0xE8,0x40,0x00, 0x00,0x11,0x00,0x24,0x84,0x00,0x00,0xAB, 0xFF,0xFF,0x55,0x00,0x00,0x00,0x24,0x02, 0x49,0x5E,0xA0,0x00,0x84,0xBF,0xFF,0xF4, 0x88,0x00,0x00,0x00,0x10,0x05,0xFF,0xF4, 0x00,0x29,0x0B,0xFF,0xFA,0x20,0x00,0x00, 0x00,0x02,0xBF,0xFF,0xFC,0x00,0x44,0xA0, 0x57,0xFD,0x80,0x00,0x00,0x00,0x08,0x5F, 0xFF,0xFF,0x80,0x91,0x0A,0xAA,0xF6,0x50, 0x44,0xA0,0x01,0x1B,0x84,0x00,0x00,0x00, 0x26,0xFF,0xFF,0xFF,0x90,0x11,0x0A,0xAA, 0x6D,0x68,0x00,0x00,0x00,0x0B,0xFB,0xFF, 0xEF,0xE0,0xC4,0xA0,0x01,0x02,0x80,0x00, 0x00,0x00,0x43,0xF1,0xFE,0x63,0xF0,0x15, 0x55,0x54,0x55,0x6A,0x00,0x00,0x00,0x9F, 0xE3,0xFC,0x87,0x30,0xCA,0xAB,0x91,0x00, 0x90,0x00,0x00,0x00,0x07,0xC1,0xFA,0x2A, 0x80,0x25,0xFF,0xFE,0x95,0x2A,0x00,0x00, 0x00,0x2F,0x13,0xFE,0xFC,0x10,0x95,0xFF, 0xFF,0xC0,0x50,0x00,0x00,0x00,0x0F,0x41, 0xFF,0xF3,0x80,0x4F,0xFF,0xFF,0xF9,0x2A, 0x00,0x00,0x00,0x9F,0x08,0xFF,0xD4,0x00, 0xB3,0xFF,0xFF,0xFE,0x54,0x80,0x00,0x00, 0x1E,0xA0,0x7F,0xA0,0x00,0x5F,0xFE,0x7F, 0xFE,0xAA,0x00,0x00,0x00,0x5F,0x57,0xFE, 0x00,0x00,0xAF,0xFD,0x7F,0xFF,0x94,0x80, 0x00,0x00,0x1F,0xFE,0xE8,0x00,0x00,0x7F, 0xFA,0x7F,0x5F,0xCA,0x00,0x00,0x00,0x3F, 0x55,0x00,0x00,0x00,0xAF,0xF1,0x7F,0xDE, 0xF5,0x40,0x00,0x00,0x1A,0xA0,0x80,0x00, 0x00,0xDF,0xF2,0x3F,0xFC,0xC6,0x00,0x00, 0x00,0x50,0x08,0x00,0x00,0x00,0x2F,0xFA, 0x00,0x00,0x00,0x97,0xFE,0x3F,0xFF,0xE3, 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x5F,0xFF,0x48,0x02,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xAA,0xF4,0xA0,0xAA,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x45,0x09,0x05,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x28,0xA0,0x00,0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x04,0x52,0x12,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0x09,0x51,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x04,0x4A,0x12,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x05,0x50,0x21,0x48,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x02,0x84,0x12,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x20,0x00,0x02,0x02,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0x84,0x92,0x48,0x94,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};void main(){init();clear_GDRAM();write_image(image);lcd_pos(4,0);for(i=0;i<10;i++)write_date(table[i]);while(1);}。
#include <reg52.h>#include <intrins.h>#define dataPort P0 //数据口sbit rs=P2^6; //寄存器选择输入sbit rw=P2^5; //液晶读/写控制sbit en=P2^7; //液晶使能控制sbit psb=P3^2; //串/并方式控制//sbit LCD_RST =P3^7; //液晶复位端口unsigned char code Photo1[] ={0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3F,0xC0,0x80,0x42,0x04,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x1F,0xFC,0x42,0x04,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xDE,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x2A,0x87,0xF0,0xA2,0x0A,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x84,0x10,0xA2,0x0A,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0xFC,0xA2,0x0A,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x90,0x05,0x2F,0xCA,0xA4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0xE1,0xA8,0x4A,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xC2,0x24,0x48,0x44,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x84,0x24,0xA8,0x4A,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA6,0x58,0x3D,0x0F,0xD0,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x08,0x37,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x08,0x40,0x00,0xFF,0x90,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x86,0x10,0x40,0x00,0x08,0x08,0x01,0x02,0x49,0x40,0x40,0x00,0x7F,0x0B, 0xFC,0x08,0x0F,0x00,0x00,0x00,0x00,0x00, 0x01,0x08,0x00,0x40,0x20,0x00,0x10,0x00, 0x10,0x49,0x0F,0x00,0x00,0x00,0x00,0x00, 0x02,0x08,0x00,0x20,0x20,0x01,0xFF,0xDD, 0x10,0x2A,0x0F,0x00,0x00,0x00,0x00,0x00, 0x04,0x31,0x83,0x20,0x20,0x00,0x20,0x04, 0x91,0xFF,0xC6,0x00,0x00,0x00,0x00,0x00, 0x04,0x52,0x44,0x90,0x20,0x00,0x7F,0x04, 0x90,0x1C,0x06,0x00,0x00,0x00,0x00,0x00, 0x09,0xA4,0x28,0x4C,0x10,0x00,0xA1,0x04, 0x10,0x2A,0x00,0x00,0x00,0x00,0x00,0x00, 0x0E,0x44,0xE9,0xC3,0x90,0x01,0x3F,0x04, 0x70,0x49,0x06,0x00,0x00,0x00,0x00,0x00, 0x00,0x82,0xC5,0x81,0x70,0x00,0x21,0x0A, 0x01,0x88,0xC6,0x00,0x00,0x00,0x00,0x00, 0x01,0x01,0x83,0x00,0x80,0x00,0x3F,0x11, 0xFC,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x0C,0x70,0x00,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x13,0x87,0x10,0x40,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x20,0x78,0xA0,0x40,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x20,0x00,0x60,0x40,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x21,0x80,0x60,0x40,0x00,0x00,0x71, 0xEE,0x3C,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x11,0x98,0x90,0x80,0x00,0x00,0x8E, 0x31,0xC6,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x08,0x18,0x80,0x80,0x00,0x01,0x24, 0x24,0x83,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x96,0x01,0x01,0x00,0x00,0x01,0x40, 0x28,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x49,0x86,0x03,0x00,0x00,0x01,0x40, 0x28,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x34,0x78,0x8C,0x00,0x00,0x01,0x00, 0x20,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x0E,0x01,0x30,0x00,0x00,0x00,0x80, 0x30,0x06,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x71,0x87,0xCE,0x00,0x00,0x00,0x40, 0x68,0x0C,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xE0,0x78,0x07,0x00,0x00,0x00,0x20,0x01,0xAF,0xFF,0xC5,0x80,0x00,0x00,0x11, 0x82,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 0x03,0xA9,0xB6,0x45,0xC0,0x00,0x00,0x0B, 0x01,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x2F,0x03,0xC4,0xE0,0x00,0x00,0x06, 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 0x0E,0x16,0x01,0x88,0x70,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0F,0x08,0x00,0x10,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0F,0x84,0x00,0x21,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };//89c51系列延时/*void delayms(unsigned int n){unsigned char i;for(;n>0;n--)for(i=0;i<100;i++);}*///12c5a系列延时void delayms(unsigned int a) //@11.0592MHz {unsigned char i, j;while(a--){_nop_();i = 11;j = 190;do{while (--j);} while (--i);}}//判断是否忙void checkBusy(void){rs=0;rw=1;en=1;dataPort=0xff;while(dataPort & 0x80);en=0;}//写指令函数void writeCommand(unsigned char cmd){checkBusy();rs=0;rw=0;en=1;dataPort=cmd;_nop_();en=0;}//写数据函数void writeData(unsigned char adata){checkBusy();rs=1;rw=0;en=1;dataPort=adata;_nop_();en=0;}//读数据函数unsigned char readData(void){unsigned char RData;dataPort=0xff;checkBusy();rs=1;rw=1;en=0;en=1;RData=dataPort;en=0;return RData;}//清除rom函数,若不清除则会出现花屏现象void ClrGDRAM(void){unsigned char x,y;for(y=0;y<64;y++)for(x=0;x<16;x++){writeCommand(0x34);writeCommand(y+0x80); //行地址writeCommand(x+0x80); //列地址writeCommand(0x30);writeData(0x00);writeData(0x00);}//writeCommand(0x30);}//lcd12864初始化函数void LcmInit(void){writeCommand(0x30);delayms(50);writeCommand(0x01);delayms(50);writeCommand(0x06);delayms(50);writeCommand(0x0c);ClrGDRAM();psb=1;}//在坐标(x,y)处显示字符串void LcmPrint(unsigned char x,unsigned char y,unsigned char *adata) {unsigned char address;unsigned char i=0;switch (y){case 0:address=0x80+x;break;case 1:address=0x90+x;break;case 2:address=0x88+x;break;case 3:address=0x98+x;break;default:break;}writeCommand(address);while(*(adata+i)){writeData(*(adata+i));i++;}}/*********************************************************** 函数名:disp_picture函数说明:显示一幅128*64的图画传入参数:图形指针*img传出参数:无返回值:无**********************************************************/ void disp_picture(unsigned char *img){unsigned char i,j;for(j=0;j<32;j++){for(i=0;i<8;i++){writeCommand(0x34);writeCommand(0x80+j);writeCommand(0x80+i);writeCommand(0x30);writeData(img[j*16+i*2]);writeData(img[j*16+i*2+1]);}}for(j=32;j<64;j++){for(i=0;i<8;i++){writeCommand(0x34);writeCommand(0x80+j-32);writeCommand(0x80+(i+8));writeCommand(0x30);writeData(img[j*16+i*2]);writeData(img[j*16+i*2+1]);}}writeCommand(0x36);}/*********************************************************** 函数名:dispU_picture函数说明:上半屏显示一幅128*32的图画传入参数:图形指针*img传出参数:无返回值:无**********************************************************/ /*void dispU_picture(unsigned char *img){unsigned char i,j;for(j=0;j<32;j++){for(i=0;i<8;i++){writeCommand(0x34);writeCommand(0x80+j);writeCommand(0x80+i);writeCommand(0x30);writeData(img[j*16+i*2]);writeData(img[j*16+i*2+1]);}}writeCommand(0x36);}*//*********************************************************** 函数名:dispD_picture函数说明:下半屏显示一幅128*32的图画传入参数:图形指针*img传出参数:无返回值:无**********************************************************/ /*void dispD_picture(unsigned char *img){unsigned char i,j;for(j=0;j<32;j++){for(i=0;i<8;i++){writeCommand(0x34);writeCommand(0x80+j);writeCommand(0x80+(i+8));writeCommand(0x30);writeData(img[j*16+i*2]);writeData(img[j*16+i*2+1]);}}writeCommand(0x36);}*//*********************************************************** 函数名:drawPoint函数说明:画点传入参数:打点位置(x0,y0);color=1,点亮;color=0,擦除传出参数:无返回值:无**********************************************************/ void drawPoint(unsigned char x,unsigned char y,unsigned char color) {unsigned char row,collum,cbite;unsigned char tempH,tempL;writeCommand(0x34);delayms(5);writeCommand(0x36);collum=x>>4;cbite=x&0x0f;if(y<32)row=y;else{row=y-32;collum+=8;}writeCommand(0x80+row);delayms(5);writeCommand(0x80+collum);readData();delayms(5);tempH=readData();tempL=readData();writeCommand(0x80+row);delayms(5);writeCommand(0x80+collum);if (color){if(cbite<8){tempH|=(1<<(7-cbite));//tempL=(1<<(7-cbite));}else{//tempH=(1<<(15-cbite));tempL|=(1<<(15-cbite));}}else{if(cbite<8){tempH&=~(1<<(7-cbite));//tempL=(1<<(7-cbite));}else{//tempH=(1<<(15-cbite));tempL&=~(1<<(15-cbite));}}writeData(tempH);writeData(tempL);writeCommand(0x30);}/***********************************************************函数名:drawRowLine函数说明:画水平线传入参数:(x0,y0),水平线的起点;(x1,y0)水平线的终点color=1,点亮;color=0,擦除传出参数:无返回值:无**********************************************************/void drawRowLine(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char color) {unsigned char temp;if(x0>x1) // 对x0、x1大小进行排列,以便画图{temp = x1;x1 = x0;x0 = temp;}do{drawPoint(x0, y0, color); // 逐点显示,描出垂直线x0++;}while(x1>=x0);}/***********************************************************函数名:drawCollumLine函数说明:画竖直线传入参数:(x0,y0),竖直线的起点;(x1,y0)竖直线的终点;color=1,点亮;color=0,擦除传出参数:无返回值:无************************************************************/void drawCollumLine(unsigned char x0,unsigned char y0,unsigned char y1,unsigned char color) {unsigned char temp;if(y0>y1){temp=y0;y0=y1;y1=temp;}while (y0<=y1){drawPoint(x0,y0,color);y0++;}}/*************************************************************函数名:drawLine函数说明:使用Bresenham法,画任意两点间的直线传入参数:(x0,y0),竖直线的起点;(x1,y1)竖直线的终点color=1,点亮;color=0,擦除传出参数:无返回值:无*************************************************************/void drawLine(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char color){int dx; // 直线x轴差值变量int dy; // 直线y轴差值变量char dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向char dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向int dx_2; // dx*2值变量,用于加快运算速度int dy_2; // dy*2值变量,用于加快运算速度int di; // 决策变量dx = x1-x0; // 求取两点之间的差值dy = y1-y0;if (dx<0) dx_sym=-1;else{if(dx>0) dx_sym=1;else{drawCollumLine(x0,y0,y1,color);return;}}if(dy>0) dy_sym=1;else{if(dy<0) dy_sym=-1;else{drawRowLine(x0,y0,x1,color);return;}}dx=dx_sym*dx;dy=dy_sym*dy;dx_2=dx*2;dy_2=dy*2;if(dx>=dy){di=dy_2-dx;while(x0!=x1){drawPoint(x0,y0,color);x0+=dx_sym;if(di<0) di+=dy_2;else {di+=dy_2-dx_2;y0+=dy_sym;}}drawPoint(x0,y0,color);}else{di=dx_2-dy;while(y0!=y1){drawPoint(x0,y0,color);y0+=dy_sym;if(di<0) di+=dx_2;else {di+=dx_2-dy_2;x0+=dx_sym;}}drawPoint(x0,y0,color);}}//画圆函数void drawRound(int x0,int y0,unsigned char r){int x=0,y=r;float d;d=1.25-r;while(x<=y){drawPoint(x0+x,y0+y,1);drawPoint(x0+x,y0-y,1);drawPoint(x0-x,y0+y,1);drawPoint(x0-x,y0-y,1);drawPoint(x0+y,y0+x,1);drawPoint(x0+y,y0-x,1);drawPoint(x0-y,y0+x,1);drawPoint(x0-y,y0-x,1);if(d<0)d+=x*2.0+3;else{d+=2.0*(x-y)+5;y--;}x++;}}//清屏函数void clr_screen(){writeCommand(0x34); //扩充指令操作delayms(5);writeCommand(0x30); //基本指令操作delayms(5);writeCommand(0x01); //清屏delayms(5);ClrGDRAM();}void main(void){delayms(500);//等待上电稳定LcmInit();while(1){drawPoint(10,20,1);delayms(1000);clr_screen();delayms(1000);drawCollumLine(20,2,50,1);delayms(1000);clr_screen();delayms(1000);drawRowLine(10,3,50,1);delayms(1000);clr_screen();delayms(1000);drawLine(1,1,30,20,1);delayms(1000);clr_screen();delayms(1000);LcmPrint(1,20,"哈哈kkkah");delayms(1000);clr_screen();delayms(1000);drawRound(64,32,20);delayms(1000);clr_screen();delayms(1000);disp_picture(Photo1);delayms(1000);clr_screen();delayms(1000);}}。
/****************************************************************************** ******************************************************************************* *********///程序说明:本程序为12864(st7920)驱动程序,只实现了最简单的显示功能//端口设置:RS、RW、EN分别为P0口的0、1、2,数据口为P2口//注意:1.要想在液晶屏上同时显示自定义字库和绘图,必须先显示自定义字库// 2.本程序所有函数均有用且正确,由于我的keil未破解不能编译,所以将其注释了// 3.用取模软件取的图形或汉字必须是逐行取的,因为本函数是在液晶上逐行打点的/****************************************************************************** *****************************************************************************/ #include<reg51.h>#include<intrins.h> //内含-NOP-函数#include<stdlib.h> //内含rand()函数#define uchar unsigned char#define uint unsigned int//**********宏定义所需指令#define BASIC_SET 0x30#define EXTEND_SET 0x34#define DRAW_ON 0x36#define DRAW_OFF 0x34//*************端口定义sbit LCD_RS = P0^0;sbit LCD_RW = P0^1;sbit LCD_EN = P0^2;//************变量定义//uchar dis1[10];//****************短延时void delay(uint k){uint i;uchar j;for(i = 0; i < k ;i ++)for(j = 0; j < 10 ;j ++);}//***********ms级延时函数/*void delay_1ms(uint x){uint i,j;for(j = 0;j < x; j++)for(i = 0;i < 110; i++);} *///***********12864写指令函数void write_com(uchar cmd){LCD_RS = 0;LCD_RW = 0;P2 = cmd;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0;}//********12864写数据函数void write_dat(uchar dat){LCD_RS = 1;LCD_RW = 0;P2 = dat;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0;}//****************从LCD中读数据uchar read_dat(void){uchar temp;P2 = 0XFF; //释放数据线LCD_RS = 1; //数据LCD_RW = 1; // 读模式LCD_EN = 1; //E为高电平进行读数据或指令delay(1);temp = P2;LCD_EN = 0;return temp;}//********************************************************//设置光标(地址)函数//参数说明:x---为行号,y为列号//********************************************************void set_cursor(unsigned char x, unsigned char y){unsigned char i;switch(x) //确定行号{case 0x00: i=0x80; break; //第一行case 0x01: i=0x90; break; //第二行case 0x02: i=0x88; break; //第三行case 0x03: i=0x98; break; //第四行default : break;}i = y+i; //确定列号write_com(i);}//********************************************************//显示字符函数//********************************************************void display_char(unsigned char Alphabet){write_dat(Alphabet); //写入需要显示字符的显示码}//********************************************************//指定位置显示字符串函数//参数说明:x为行号,y为列号//********************************************************void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet) {unsigned char i=0;set_cursor(x,y); //设置显示的起始地址while(Alphabet[i]!='\0'){write_dat(Alphabet[i]); //写入需要显示字符的显示码i++;}}//***********************以下为GDRAM绘图部分***************************////*********************绘图显示的清屏函数(因清屏指令在画图时不能用)------------------------------------------------------------------------------注意!!!!!!!void gui_clear(){uchar i , j , k;write_com(EXTEND_SET);//扩展指令集,8位数据传输write_com(DRAW_OFF);//绘图显示关闭for(i = 0; i < 2; i ++)//分上下两屏写{for(j = 0; j < 32; j ++){write_com(0x80 + j);//写y坐标delay(1);if(i == 0) //写x坐标{write_com(0x80);delay(1);}else //写下半屏{write_com(0x88);delay(1);}for(k = 0; k < 16; k ++)//写一整行数据{write_dat(0x00);//写高字节write_dat(0x00);//写低字节delay(1);}}}write_com(DRAW_ON);//打开绘图显示write_com(BASIC_SET);//打开基本指令集}//******************************************************************//*****有反白显示功能的打点函数***********//参数:color=1,该点填充1;color=0,该点填充白色0;//*******************************************************************void GUI_Point(unsigned char x,unsigned char y,unsigned char color){unsigned char x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位unsigned char y_Dyte,y_byte; //定义为上下两个屏(取值为0,1),行地址(取值为0~31)unsigned char GDRAM_hbit,GDRAM_lbit;write_com(0x36); //扩展指令命令/***X,Y坐标互换,即普通的X,Y坐标***/x_Dyte=x/16; //计算在16个字节中的哪一个x_byte=x&0x0f; //计算在该字节中的哪一位y_Dyte=y/32; //0为上半屏,1为下半屏y_byte=y&0x1f; //计算在0~31当中的哪一行write_com(0x80+y_byte); //设定行地址(y坐标),即是垂直地址write_com(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏,即是水平地址read_dat(); //预读取数据GDRAM_hbit= read_dat(); //读取当前显示高8位数据GDRAM_lbit= read_dat(); //读取当前显示低8位数据delay(1);write_com(0x80+y_byte); //设定行地址(y坐标)write_com(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏delay(1);if(x_byte<8) //判断其在高8位,还是在低8位{if(color==1){write_dat(GDRAM_hbit|(0x01<<(7-x_byte))); //置位GDRAM区高8位数据中相应的点}elsewrite_dat(GDRAM_hbit&(~(0x01<<(7-x_byte)))); //清除GDRAM区高8位数据中相应的点write_dat(GDRAM_lbit); //显示GDRAM区低8位数据}else{write_dat(GDRAM_hbit);if(color==1)write_dat(GDRAM_lbit|(0x01<<(15-x_byte))); //置位GDRAM区高8位数据中相应的点elsewrite_dat(GDRAM_lbit&(~(0x01<<(15-x_byte))));//清除GDRAM区高8位数据中相应的点}write_com(0x30); //恢复到基本指令集}//***********(给定坐标并打点的)任意位置打点函数void lcd_set_dot(uchar x,uchar y){uchar x_byte,x_bit;//确定在坐标的那一字节哪一位uchar y_ping , y_bit;//确定在坐标的哪一屏哪一行uchar tmph , tmpl;//定义两个临时变量,用于存放读出来的数据write_com(EXTEND_SET);//扩展指令集write_com(DRAW_OFF);//绘图显示关闭x_byte = x / 16;//算出在哪一字节,注意一个地址是16位的x_bit = x % 16;//& 0x0f;//算出在哪一位y_ping = y / 32;//确定在上半屏还是下半屏,0代表上半屏,1代表下半屏y_bit = y % 32;//& 0x1f;//确定在第几行write_com(0X80 + y_bit);//先写垂直地址(最高位必须)write_com(0x80 + x_byte + 8 * y_ping);//水平坐标,下半屏坐标起始地址为0x88,(+8*y_ping)就是用来确定上半屏还是下半屏read_dat();//预读取数据tmph = read_dat();//读取当前显示高8位数据tmpl = read_dat();//读取当前显示低8位数据delay(1);write_com(0x80 + y_bit);//读操作会改变AC,所以重新设置一下write_com(0x80 + x_byte + 8 * y_ping);delay(1);if(x_bit < 8){write_dat(tmph | (0x01 << (7 - x_bit)));//写高字节,因为坐标是从左向右的,GDRAM 高位在昨,低位在右write_dat(tmpl);//原低位数据送回}else{write_dat(tmph);//原高位数据送回write_dat(tmpl | (0x01 << (15 - x_bit)));}write_com(DRAW_ON); //打开绘图显示write_com(BASIC_SET);//回到基本指令集}//************画水平线函数**********************************////x0、x1为起始点和终点的水平坐标,y为垂直坐标***************////**********************************************************//void gui_hline(uchar x0, uchar x1, uchar y){uchar bak;//用于对两个数互换的中间变量,使x1为大值if(x0 > x1){bak = x1;x1 = x0;x0 = bak;}do{lcd_set_dot(x0 , y);//从左到右逐点显示x0 ++;}while(x1 >= x0);}//***********画竖直线函数***********************************////x为起始点和终点的水平坐标,y0、y1为垂直坐标***************////**********************************************************//void gui_rline(uchar x, uchar y0, uchar y1)uchar bak;//用于对两个数互换的中间变量,使y1为大值if(y0 > y1){bak = y1;y1 = y0;y0 = bak;}do{lcd_set_dot(x , y0);//从上到下逐点显示y0 ++;}while(y1 >= y0);}//*********任意两点间画直线*********************************// //x0、y0为起始点坐标,x1、y1为终点坐标**********************// //**********************************************************// void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1){char dx;//直线x轴差值char dy;//直线y轴差值char dx_sym;//x轴增长方向,为-1时减值方向,为1时增值方向char dy_sym;//y轴增长方向,为-1时减值方向,为1时增值方向char dx_x2;//dx*2值变量,用于加快运算速度char dy_x2;//dy*2值变量,用于加快运算速度char di; //决策变量if(x0 == x1)//判断是否为垂直线{gui_rline(x0 , y0 , y1);//画垂直线return;}if(y0 == y1)//判断是否为水平线{gui_hline(x0 , x1 , y0);//画水平线return;}dx = x1 - x0;//求取两点之间的差值dy = y1 - y0;//****判断增长方向,或是否为水平线、垂直线、点*// if(dx > 0)//判断x轴方向dx_sym = 1;else{if(dx < 0)dx_sym = -1;else{gui_rline(x0 , y0 , y1);return;}}if(dy > 0)//判断y轴方向dy_sym = 1;else{if(dy < 0)dy_sym = -1;else{gui_hline(x0 , x1 , y0);return;}}/*将dx、dy取绝对值***********/dx = dx_sym * dx;dy = dy_sym * dy;/****计算2倍的dx、dy值*******/dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点对应dy_x2 = dy * 1;/***使用bresenham法进行画直线***/if(dx >= dy)//对于dx>=dy,使用x轴为基准{di = dy_x2 - dx;while(x0 != x1){lcd_set_dot(x0,y0);x0 +=dx_sym;if(di < 0)di += dy_x2;//计算出下一步的决策值else{di += dy_x2 - dx_x2;y0 += dy_sym;}}lcd_set_dot(x0, y0);//显示最后一点}else //对于dx<dy使用y轴为基准{di = dx_x2 - dy;while(y0 != y1){lcd_set_dot(x0, y0);y0 += dy_sym;if(di < 0)di += dx_x2;else{di += dx_x2 - dy_x2;x0 += dx_sym;}}lcd_set_dot(x0, y0);//显示最后一点}}//***************************************************************************// //*******************画指定宽度的任意两点之间的直线**************************// //参数说明:x0、y0为起始点坐标,x1、y1为终点坐标,with为线宽*****************// //***************************************************************************// void gui_linewith(uchar x0 , uchar y0 , uchar x1 , uchar y1 , uchar with){char dx; // 直线x轴差值变量char dy; // 直线y轴差值变量char dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向char dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向char dx_x2; // dx*2值变量,用于加快运算速度char dy_x2; // dy*2值变量,用于加快运算速度char di; // 决策变量char wx, wy; // 线宽变量char draw_a, draw_b;// 参数过滤if(with==0) return;if(with>50) with = 50;dx = x1-x0; // 求取两点之间的差值dy = y1-y0;wx = with/2;wy = with-wx-1;//判断增长方向,或是否为水平线、垂直线、点if(dx>0) // 判断x轴方向{dx_sym = 1; // dx>0,设置dx_sym=1 }else{if(dx<0){dx_sym = -1; // dx<0,设置dx_sym=-1 }else{//dx==0,画垂直线,或一点wx = x0-wx;if(wx<0) wx = 0;wy = x0+wy;while(1){x0 = wx;gui_rline(x0, y0, y1);if(wx>=wy) break;wx++;}return;}}if(dy>0) // 判断y轴方向{dy_sym = 1; // dy>0,设置dy_sym=1}else{if(dy<0){dy_sym = -1; // dy<0,设置dy_sym=-1 }else{//dy==0,画水平线,或一点wx = y0-wx;if(wx<0) wx = 0;wy = y0+wy;while(1){y0 = wx;gui_hline(x0, x1, y1);if(wx>=wy) break;wx++;}return;}}// 将dx、dy取绝对值dx = dx_sym * dx;dy = dy_sym * dy;//计算2倍的dx及dy值dx_x2 = dx*2;dy_x2 = dy*2;//使用Bresenham法进行画直线if(dx>=dy) // 对于dx>=dy,则使用x轴为基准{di = dy_x2 - dx;while(x0!=x1){//x轴向增长,则宽度在y方向,即画垂直线draw_a = y0-wx;if(draw_a<0) draw_a = 0;draw_b = y0+wy;gui_rline(x0, draw_a, draw_b);x0 += dx_sym;if(di<0){di += dy_x2; // 计算出下一步的决策值}else{di += dy_x2 - dx_x2;y0 += dy_sym;}}draw_a = y0-wx;if(draw_a<0) draw_a = 0;draw_b = y0+wy;gui_rline(x0, draw_a, draw_b);}else // 对于dx<dy,则使用y轴为基准{di = dx_x2 - dy;while(y0!=y1){//y轴向增长,则宽度在x方向,即画水平线draw_a = x0-wx;if(draw_a<0) draw_a = 0;draw_b = x0+wy;gui_hline(draw_a, y0, draw_b);y0 += dy_sym;if(di<0){di += dx_x2;}else{di += dx_x2 - dy_x2;x0 += dx_sym;}}draw_a = x0-wx;if(draw_a<0) draw_a = 0;draw_b = x0+wy;gui_hline(draw_a, y0, draw_b);}//***********画矩形函数*************************************// //x0、y0为矩形左上角坐标值,x1、y1为矩形右下角坐标值********// //**********************************************************// void gui_rectangle(uchar x0 , uchar y0 , uchar x1 , uchar y1){gui_hline(x0 , x1 , y0);gui_rline(x0 , y0 , y1);gui_rline(x1 , y0 , y1);gui_hline(x0 , x1 , y1);}//****************画填充矩形函数****************************// //x0、y0为矩形左上角坐标值,x1、y1为矩形右下角坐标值********// //**********************************************************// /*void gui_rectangle_fill(uchar x0 , uchar y0 , uchar x1 , uchar y1){uchar i;//转换数据的中间变量,使x1、y1大if(x0 > x1){i = x0;x0 = x1;x1 = i;}if(y0 > y1){i = y0;y0 = y1;y1 = i;}//***判断是否是直线***//* if(y0 == y1)//画水平线{gui_hline(x0 , x1 , y0);return;}if(x0 == x1)//画竖直线gui_rline(x0 , y0 , y1);return;}while(y0 <= y1)//画填充矩形{gui_hline(x0 , x1 , y0);y0 ++;}} *///*******************画正方形函数*************************// //x0、y0为正方形左上角坐标,with正方形边长****************// //********************************************************// /*void gui_square(uchar x0 , uchar y0 , uchar with){if(with == 0)return;if((x0 + with) > 127)//横轴超出液晶边界return;if((y0 + with) > 63)return;gui_rectangle(x0 , y0 , x0 + with , y0 + with);} *///****************画填充正方形函数*************************// //x0、y0为正方形左上角坐标,with正方形边长*****************// //*********************************************************// /*void gui_square_fill(uchar x0 , uchar y0 , uchar with){if(with == 0)return;if((x0 + with) > 127)//横轴超出液晶边界return;if((y0 + with) > 63)return;gui_rectangle_fill(x0 , y0 , x0 + with , y0 + with);} *///****************画圆函数*********************************////x0、y0为圆心坐标,r为圆的半径****************************////*********************************************************///*void gui_circle(uchar x0 , uchar y0 , uchar r){char a , b;char di;if(r > 31 || r == 0)//圆大于液晶屏或者没半径则返回return;a = 0;b = r;di = 3 - 2 * r;//判断下个点位置的标志while(a <= b){lcd_set_dot( x0 - b , y0 - a);//3lcd_set_dot( x0 + b , y0 - a); //0lcd_set_dot( x0 - a , y0 + b); //1lcd_set_dot( x0 - b , y0 - a); //7lcd_set_dot( x0 - a , y0 - b); //2lcd_set_dot( x0 + b , y0 + a); //4lcd_set_dot( x0 + a , y0 - b); //5lcd_set_dot( x0 + a , y0 + b); //6lcd_set_dot( x0 - b , y0 + a);a ++;//***使用bresenham算法画圆********//* if(di < 0)di += 4 * a + 6;else{di += 10 + 4 * (a - b);b --;}lcd_set_dot( x0 + a , y0 + b);}} *///***************************************************************************// //***************************画正椭圆函数************************************// //说明:给定椭圆的四个点的参数,最左、最右点的x轴坐标值为x0、x1,最上、最下点// 的y轴坐标为y0、y1.//说明:----------------------------显示效果不好//***************************************************************************// /*void gui_ellipse(char x0, char x1, char y0, char y1){char draw_x0, draw_y0; // 刽图点坐标变量char draw_x1, draw_y1;char draw_x2, draw_y2;char draw_x3, draw_y3;char xx, yy; // 画图控制变量char center_x, center_y; // 椭圆中心点坐标变量char radius_x, radius_y; // 椭圆的半径,x轴半径和y轴半径int radius_xx, radius_yy; // 半径乘平方值int radius_xx2, radius_yy2; // 半径乘平方值的两倍char di; // 定义决策变量/* 参数过滤*//* if( (x0==x1) || (y0==y1) ) return; *//* 计算出椭圆中心点坐标*//* center_x = (x0 + x1) >> 1;center_y = (y0 + y1) >> 1; *//* 计算出椭圆的半径,x轴半径和y轴半径*//* if(x0 > x1){ radius_x = (x0 - x1) >> 1;}else{ radius_x = (x1 - x0) >> 1;}if(y0 > y1){ radius_y = (y0 - y1) >> 1;}else{ radius_y = (y1 - y0) >> 1;} *//* 计算半径平方值*//* radius_xx = radius_x * radius_x;radius_yy = radius_y * radius_y; *//* 计算半径平方值乘2值*//* radius_xx2 = radius_xx<<1;radius_yy2 = radius_yy<<1; *//* 初始化画图变量*//* xx = 0;yy = radius_y;di = radius_yy2 + radius_xx - radius_xx2*radius_y ; // 初始化决策变量/* 计算出椭圆y轴上的两个端点坐标,作为作图起点*//* draw_x0 = draw_x1 = draw_x2 = draw_x3 = center_x;draw_y0 = draw_y1 = center_y + radius_y;draw_y2 = draw_y3 = center_y - radius_y;lcd_set_dot(draw_x0, draw_y0); // 画y轴上的两个端点lcd_set_dot(draw_x2, draw_y2);while( (radius_yy*xx) < (radius_xx*yy) ){ if(di<0){ di+= radius_yy2*(2*xx+3);}else{ di += radius_yy2*(2*xx+3) + 4*radius_xx - 4*radius_xx*yy;yy--;draw_y0--;draw_y1--;draw_y2++;draw_y3++;}xx ++; // x轴加1draw_x0++;draw_x1--;draw_x2++;draw_x3--;lcd_set_dot(draw_x0, draw_y0);lcd_set_dot(draw_x1, draw_y1);lcd_set_dot(draw_x2, draw_y2);lcd_set_dot(draw_x3, draw_y3);}di = radius_xx2*(yy-1)*(yy-1) + radius_yy2*xx*xx + radius_yy + radius_yy2*xx - radius_xx2*radius_yy;while(yy>=0){ if(di<0){ di+= radius_xx2*3 + 4*radius_yy*xx + 4*radius_yy - 2*radius_xx2*yy;xx ++; // x轴加1draw_x0++;draw_x1--;draw_x2++;draw_x3--;}else{ di += radius_xx2*3 - 2*radius_xx2*yy;}yy--;draw_y0--;draw_y1--;draw_y2++;draw_y3++;lcd_set_dot(draw_x0, draw_y0);lcd_set_dot(draw_x1, draw_y1);lcd_set_dot(draw_x2, draw_y2);lcd_set_dot(draw_x3, draw_y3);}} *///******************************************************************* //*******画满屏图片-----本程序为逐行写,因此图片数据也应该是逐行取的//参数:dat为填充的数据------用本程序时需要满屏图的数组//******************************************************************* /*void gui_draw_full_picture (unsigned char *dat){unsigned char i;unsigned char j;unsigned char k;unsigned char bGDRAMAddrX = 0x80; //GDRAM水平地址unsigned char bGDRAMAddrY = 0x80; //GDRAM垂直地址for(i = 0; i < 2; i++){for(j = 0; j < 32; j++){for(k = 0; k < 8; k++){write_com(0x34); //设置为8位MPU接口,扩充指令集,关闭绘图显示write_com(bGDRAMAddrY+j); //垂直地址Ywrite_com(bGDRAMAddrX+k); //水平地址Xwrite_dat(*dat++); //写数据高字节write_dat(*dat++); //写数据低字节}}bGDRAMAddrX = 0x88; //写下半屏幕}write_com(0x36); //打开绘图模式write_com(0x30); //恢复基本指令集,关闭绘图模式} */unsigned char code DCB2HEX_TAB[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; //****************************输出一行数据函数,此行可任意长,不必非得是8的倍数**和下个函数合用画任意大小(矩形)的图形或汉字//参数:flag反显标志,1为反显,x、y为指定显示位置的起始点,*dat要输出的点阵数组,no显示此行所需的点个数,即图形一行的点数void gui_loadline(unsigned char x,unsigned char y,unsigned char *dat,unsigned char no,unsigned char flag){unsigned char bit_dat;unsigned char i;/* 参数过滤,若指定显示位置超出液晶屏则返回*/if(x>127) return;if(y>63) return;for(i=0; i<no; i++)//超出本行所规定的点数则本行显示完成{/* 判断是否要读取点阵数据,每字节的开始读取一次点阵数组即i为8的倍数时*/if( (i%8)==0 ) bit_dat = *dat++;/* 对相应的点打1或打0,i&0x07意思是对8求余*/if( (bit_dat&DCB2HEX_TAB[i&0x07])==0 )//取出i对应的位,并判断是否为0{if(flag==0) //判断是否反显,该位取出的数据为0,反显要打为1,flag==0代表不反显GUI_Point(x,y,0); //正常显示0,GUI_Point(x,y,0)代表在x、y处打0elseGUI_Point(x,y,1); //将0反显}else{if(flag==0)GUI_Point(x,y,1);elseGUI_Point(x,y,0);}if( (++x)>127) return;//若显示超出了液晶屏则返回}}//*********************************************************************//********在自定义大小的区域内画图或画字函数****************************//参数说明:x、y指定显示区域的起始点坐标// dat 要输出显示的图形或汉字点阵数组。