嗯,首先要说的是,仿真和实物真心差的很远很远……
所以YY的盆友一定不要想的太简单,就像我一样,一直以为仿真做完了,实物会很easy,其实不然,特别是我这
种敲代码敲的比较多,上手焊电路比较少的来说,更是蛋疼的要死,按键我就焊了好几次……
言归正传,之前写过仿真的推箱子(在这里)。实物我用的是CX12864B,具体的参数,网上多的是,略去不提。
至于实物和仿真的区别,差不多有以下几点吧:
(PS:这都是 I think ,因为水平有限,如果有错误,麻烦您提出来,我的邮箱laoda.greenhand@foxmail.com)
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);
}