嗯,首先要说的是,仿真和实物真心差的很远很远……
所以YY的盆友一定不要想的太简单,就像我一样,一直以为仿真做完了,实物会很easy,其实不然,特别是我这
种敲代码敲的比较多,上手焊电路比较少的来说,更是蛋疼的要死,按键我就焊了好几次……
言归正传,之前写过仿真的推箱子(在这里)。实物我用的是CX12864B,具体的参数,网上多的是,略去不提。
至于实物和仿真的区别,差不多有以下几点吧:
(PS:这都是 I think ,因为水平有限,如果有错误,麻烦您提出来,我的邮箱[email protected])
Node 1:
仿真是没有字库的,需要用取模软件一个一个自己扣字,相当恶心啊……
实物是有字库的,直接字符串输出就行(汉字是16*16的点阵,字母数字是16行8列点阵,具体见代码,图片)
Node 2:
仿真的显示通常是有片选位的,用来选择控制左半屏和右半屏,就像我写的那个仿真一样,CS1、CS2分别对应两
个半屏
实物没有片选,PSB口来控制串行还是并行,因为默认的高电平对应并行8位,所以在下面的代码里面,我并没有处
理那个口
Node 3:
仿真的推箱子,我用的是光标定址,然后更新 8*8 点阵,这有点类似控制台C游戏的做法,因为这样的话,可以把地图
的每个元素(人,箱子,墙,箱子目的地,空格)用一个具体数值表示,然后用数组存下来,更新和维护都比较方便
然后是实物12864下的推箱子,对于实物12864,有两种模式,普通模式(显示汉字,还有自定义字符);绘图模式(需要打开绘图开关),整个屏分为
上下两个半屏。控制端给12864分先后,送垂直地址,水平地址,每次显示16位,然后地址自动向后累加。
问题来了,刚才提到的,我用仿真的时候,是每次更新一个 8*8 点阵来实现游戏画面对按键录入的动态响应的,可是,我尝试了很久,都没有找到实物液
晶,一次在一个指定坐标画出一个 8*8 点阵的方法……= =1,最后,最后的最后,我用了一个比较扯淡的办法:
地图还是按照 8*8 矩阵来存,更新的时候,精度不能到 8*8 的话,那就更新每个需要更新点所在的 16*16 (也就是两行两列的四个 8*8 点阵)的点阵……
是不是挺笨的= =!,可是暂时找不到别的办法了,哪位路过的大大,如果有好办法,麻烦您告诉我一声,省的咱继续把代码贴在这现眼……
差不多了吧,至于别的我没提到的,看看代码吧,很简单
Thanks :大海橡树:http://hi.baidu.com/new/dahaixiangshu
Code:
#include<reg52.h> #include<stdlib.h> #include<stdio.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit RS = P3^0; sbit RW = P3^1; sbit EN = P3^2; sbit key_up = P2^1; sbit key_down = P2^2; sbit key_left = P2^0; sbit key_right = P2^3; #define LCD_data P1 int cur_x,cur_y,X,dir[4][2]={-1,0,1,0,0,-1,0,1},where[3][2]={4,6,5,6,6,6}; uchar code table1[]="LCD12864"; uchar code table2[]="推箱子"; uchar code table3[]="BY laoda"; uchar code table4[]="You Win!"; uchar code tmp[]={//空格 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; /* 0表示空格,1表示墙,2表示人,3表示箱子,4表示目的地 */ uchar code mat[8][8]={ 1,1,1,1,1,1,1,1, 1,1,1,1,0,2,1,1, 1,1,0,0,3,0,1,1, 1,1,0,1,0,1,1,1, 1,0,0,1,0,1,4,1, 1,0,1,0,0,3,4,1, 1,0,3,0,0,0,4,1, 1,1,1,1,1,1,1,1 }; uchar map[8][8]; uchar code Qiang[]={//方格,有间隙 0xff,0x81,0x81,0x81,0x81,0x81,0x81,0xff }; uchar code Ren[]={//人 0xff,0xff,0xe3,0xc5,0xb1,0xc5,0xe3,0xff }; uchar code Xiang[]={//箱子 0xff,0x42,0x24,0x18,0x18,0x24,0x42,0xff }; uchar code Mudi[]={//目的地 0xff,0xff,0xe7,0x81,0x81,0xe7,0xff,0xff }; void delay(uint i) //延时函数 { while(--i); } void read_busy()//读忙函数。每次读写都要进行读忙操作 { RS=0; RW=1; EN=1; while(LCD_data & 0x80);//最高位为BF位 DB7---BF EN=0; } void write_LCD_command(uchar value)//写指令函数 { read_busy(); RS=0; RW=0; EN=1; //EN从1---0锁存数据 LCD_data=value; delay(20); EN=0; } void write_LCD_data(uchar value)//写数据函数 { read_busy(); RS=1; RW=0; EN=1; //EN从1---0锁存数据 LCD_data=value; delay(20); EN=0; } void init_BMP() { write_LCD_command(0x36);//CL=1--8位。扩充指令(RE=1),绘图打开(G=1) delay(100); //适当延时 write_LCD_command(0x36); delay(37); write_LCD_command(0x3E);//8位(CL=1),扩充指令(RE=1),绘图打开(G=1) delay(100); write_LCD_command(0x01);//清屏指令 delay(100); } void init_Hanzi() //8位并口方式LCD1864初始化函数 { delay(4000); //等待时间>40ms write_LCD_command(0x30);//功能设定:8位数据、基本指令操作 delay(100); //等待时间>100us write_LCD_command(0x30);//功能设定:8位数据、基本指令操作 delay(37); //等待时间>37us write_LCD_command(0x0C);//显示设定:整体显示、游标关、不反白 delay(100); // 等待时间>100us //write_LCD_command(0x01);//清屏指令 //delay(10000); //等待时间>10ms write_LCD_command(0x06);//进入点设定:地址指针加1 } void display_BMP(uchar fuck,uchar name1,uchar name2,uchar y,uchar x) { uchar shit,i; if(fuck==0)shit=0x80; else shit=0x88; for(i=0;i<8;i++) { write_LCD_command(0x80+i+8*x);//先送垂直地址 write_LCD_command(shit+y); //再送水平地址 ----显示图片的上半部分 if(name1==0) write_LCD_data(tmp[i]); else if(name1==1) write_LCD_data(Qiang[i]); else if(name1==2) write_LCD_data(Ren[i]); else if(name1==3) write_LCD_data(Xiang[i]); else if(name1==4) write_LCD_data(Mudi[i]); if(name2==0) write_LCD_data(tmp[i]); else if(name2==1) write_LCD_data(Qiang[i]); else if(name2==2) write_LCD_data(Ren[i]); else if(name2==3) write_LCD_data(Xiang[i]); else if(name2==4) write_LCD_data(Mudi[i]); } } void show_map(){ uchar i,j,x,y; for(i=0;i<2;i++){ for(j=0;j<4;j++){ x=2*i; y=2*j; display_BMP(0,map[x][y],map[x][y+1],j,2*i); x=2*i+1; y=2*j; display_BMP(0,map[x][y],map[x][y+1],j,2*i+1); } } for(i=2;i<4;i++){ for(j=0;j<4;j++){ x=2*i; y=2*j; display_BMP(1,map[x][y],map[x][y+1],j,2*(i-2)); x=2*i+1; y=2*j; display_BMP(1,map[x][y],map[x][y+1],j,2*(i-2)+1); } } init_Hanzi(); write_LCD_command(0x80+4); for(i=0;i<8;i++) { write_LCD_data(table1[i]); } write_LCD_command(0x90+4); for(i=0;i<8;i++) { write_LCD_data(table2[i]); } write_LCD_command(0x88+4); for(i=0;i<8;i++) { write_LCD_data(table3[i]); } delay(100); } void clear()//图形模式下,没有清屏函数,手动全部送0 { uchar i,j; for(i=0;i<32;i++){ write_LCD_command(0x80+i);//先送垂直地址 write_LCD_command(0x80); //再送水平地址 ----显示图片的上半部分 for(j=0;j<16;j++)write_LCD_data(0); } for(i=0;i<32;i++){ write_LCD_command(0x80+i); //先送垂直地址 write_LCD_command(0x88); //显示图片的下半部分 for(j=0;j<16;j++)write_LCD_data(0); } } uchar judge(int x,int y,int id){ //id 表示方向数组的行标,0,1,2,3 分别表示上下左右 int xx,yy,xxx,yyy; xx=x+dir[id][0]; yy=y+dir[id][1]; if(map[xx][yy]==0 || map[xx][yy]==4)return 1; //1表示前面是 空格 或者 目的地,就是可以直接移动 else if(map[xx][yy]==1)return 0; //0表示无法移动 else if(map[xx][yy]==3){ xxx=xx+dir[id][0]; yyy=yy+dir[id][1]; if(map[xxx][yyy]==1 || map[xxx][yyy]==3)return 0; else if(map[xxx][yyy]==0 || map[xxx][yyy]==4)return 2; //2表示需要间接移动,先把前面的箱子移动一,再让人移动一 }return 0; } void update(uchar a,uchar b){ uchar i,j,x,y; write_LCD_command(0x3E);//8位(CL=1),扩充指令(RE=1),绘图打开(G=1) delay(100); if(a<4){ i=a/2; j=b/2; x=2*i; y=2*j; display_BMP(0,map[x][y],map[x][y+1],j,2*i); x=2*i+1; y=2*j; display_BMP(0,map[x][y],map[x][y+1],j,2*i+1); } else { i=a/2; j=b/2; x=2*i; y=2*j; display_BMP(1,map[x][y],map[x][y+1],j,2*(i-2)); x=2*i+1; y=2*j; display_BMP(1,map[x][y],map[x][y+1],j,2*(i-2)+1); } } void fun(uchar key,uchar dirction){ uchar x,y; /* 0表示空格,1表示墙,2表示人,3表示箱子,4表示目的地 */ if(key==1){//直接移动 if(mat[cur_x][cur_y]==4)map[cur_x][cur_y]=4; else map[cur_x][cur_y]=0; update(cur_x,cur_y); cur_x+=dir[dirction][0]; cur_y+=dir[dirction][1]; map[cur_x][cur_y]=2; update(cur_x,cur_y); } else if(key==2){//间接移动 if(mat[cur_x][cur_y]==4)map[cur_x][cur_y]=4; else map[cur_x][cur_y]=0; update(cur_x,cur_y); cur_x+=dir[dirction][0]; cur_y+=dir[dirction][1]; map[cur_x][cur_y]=2; update(cur_x,cur_y); x=cur_x+dir[dirction][0]; y=cur_y+dir[dirction][1]; map[x][y]=3; update(x,y); } } void lcd_init(){ uchar i,j; init_BMP(); cur_x=1; cur_y=5; X=3; for(i=0;i<8;i++){ for(j=0;j<8;j++)map[i][j]=mat[i][j]; } } void main() { uchar i,num,index=6; lcd_init(); clear(); show_map(); /* 0表示空格,1表示墙,2表示人,3表示箱子,4表示目的地 */ while(1){ num=0; for(i=0;i<3;i++){ if(map[ where[i][0] ][ where[0][1] ]==3)num++; else break; } if(num==X)goto WIN; if(key_up==0){ delay(500); if(key_up==0){ index=judge(cur_x,cur_y,0); fun(index,0); }while(!key_up); } else if(key_down==0){ delay(500); if(key_down==0){ index=judge(cur_x,cur_y,1); fun(index,1); }while(!key_down); } else if(key_left==0){ delay(500); if(key_left==0){ index=judge(cur_x,cur_y,2); fun(index,2); }while(!key_left); } else if(key_right==0){ delay(500); if(key_right==0){ index=judge(cur_x,cur_y,3); fun(index,3); }while(!key_right); } } WIN: init_Hanzi(); write_LCD_command(0x98+4); for(i=0;i<8;i++) { write_LCD_data(table4[i]); } delay(1000); while(1); }