标签:
原文链接: http://bbs.elecfans.com/forum.php?mod=viewthread&tid=282698&extra=&highlight=12864&page=1
参考帖子:http://home.eeworld.com.cn/my/space-uid-159112-blogid-40752.html
http://v.youku.com/v_show/id_XNDYwOTM2Njc2.html
void main()
{
SPI_MasterInit();
LCD_INTI ();
while(1)
{
}
}
最后是我用ATMEGA324PA单片机和LCD12864做的一个贪吃蛇游戏,见开头视频。
全部程序如下:
/***********************************************************************
LCD12864贪吃蛇
贪吃蛇游戏(不死版)
单片机:ATMEGA324PA
编程软件:IAR
编程语言:C++
屏幕:LCD12864
按键:上下左右
***********************************************************************/
<main.cpp>:
#define F_CPU 8
#include"delay.h"
#include <stdlib.h>
#include <math.h>
#include<ioavr.h>
#include "function.h"
#define K0 PINA_Bit0
#define K1 PINA_Bit1
#define K2 PINA_Bit2
#define K3 PINA_Bit3
#define K4 PINA_Bit4
#define K5 PINA_Bit5
class Point{
public:
char x;//x:0~127
char y;//y:0~63
Point(){};
Point(char m,char n){x=m;y=n;}
bool operator==(Point &a)
{
if(x==a.x&&y==a.y)return true;
else return false;
}
//char Get_x(){return x;}
//char Get_y(){return y;}
};
class Snake{
public:
char length;
Point body[64];//头:body[0]尾:body[length-1] 其余:空
Point food;
Snake()
{
length=3;
for(char i=0;i<64;i++)body=Point(0,0);
body[0]=Point(64,33);
body[1]=Point(64,32);
body[2]=Point(64,31);
}
void Go_ahead();
//void Go_back();
void Turn_left();
void Turn_right();
void Turn_up();
void Turn_down();
void Generate_food();
void Eat();
void Restart();
bool Near_food();
char Get_direction();
void Refresh(Point p);
};
void Snake::Go_ahead()
{
Point temp=body[0],temp1=body[length-1];
char v=Get_direction();
switch(v)
{
case 0:
if(body[0].y==63)Restart();
else body[0].y++;break;
case 1:
if(body[0].y==0)Restart();
else body[0].y--;break;
case 2:
if(body[0].x==0)Restart();
else body[0].x--;break;
case 3:
if(body[0].x==127)Restart();
else body[0].x++;break;
default:break;
}
if(body[0].x==food.x&&body[0].y==food.y)
{
length++;
for(char i=length-1;i>1;i--)
{
body=body[i-1];
}
body[1]=temp;
Generate_food();
}
else
{
for(char i=length-1;i>1;i--)
{
body=body[i-1];
}
body[1]=temp;
}
Refresh(body[0]);
Refresh(temp1);
}
void Snake::Turn_left()
{
Point temp1=body[length-1];
for(char i=length-1;i>0;i--)
{
body=body[i-1];
}
if(body[0].x==0)Restart();
else body[0].x--;
Refresh(body[0]);
Refresh(temp1);
}
void Snake::Turn_right()
{
Point temp1=body[length-1];
for(char i=length-1;i>0;i--)
{
body=body[i-1];
}
if(body[0].x==127)Restart();
else body[0].x++;
Refresh(body[0]);
Refresh(temp1);
}
void Snake::Turn_up()
{
Point temp1=body[length-1];
for(char i=length-1;i>0;i--)
{
body=body[i-1];
}
if(body[0].y==63)Restart();
else body[0].y++;
Refresh(body[0]);
Refresh(temp1);
}
void Snake::Turn_down()
{
Point temp1=body[length-1];
for(char i=length-1;i>0;i--)
{
body=body[i-1];
}
if(body[0].y==0)Restart();
else body[0].y--;
Refresh(body[0]);
Refresh(temp1);
}
void Snake::Generate_food()
{
char x,y,i=0;
while(i!=length)
{ x=rand()%128;
y=rand()%64;
food=Point(x,y);
for(i=0;i<length;i++)
{
if(food==body)break;
}
}
Refresh(food);
}
bool Snake::Near_food()
{
bool k;
if(body[0].x==food.x&&body[0].y==food.y)
k=true;
else k=false;
return k;
}
void Snake::Eat()
{
for(char i=length;i>0;i--)
{
body=body[i-1];
}
body[0]=food;
length++;
Generate_food();
}
//enum direction{up,down,left,right}
char Snake::Get_direction()
{
char i;
if(body[0].x==body[1].x)
{
if(body[0].y>body[1].y){i=0;}
else i=1;
}
else
{
if(body[0].x>body[1].x){i=3;}
else i=2;
}
return i;
}
void Snake::Refresh(Point p)
{
char temp1=0,temp2=0,a,b,c;
for(char i=0;i<2;i++)
{
a=p.x-p.x%8;
if((p.x/8)%2==0)
{
b=a+8;
c=b+8;
}
else
{
b=a;
a-=8;
c=b+8;
}
for(char i=0;i<length;i++)
{
if(body.y==p.y)
{
if(body.x>=a&&body.x<b)temp1|=(1<<7-body.x%8);
if(body.x>=b&&body.x<c)temp2|=(1<<7-body.x%8);
}
if(food.y==p.y)
{
if(food.x>=a&&food.x<b){temp1|=(1<<7-food.x%8);}
if(food.x>=b&&food.x<c){temp2|=(1<<7-food.x%8);}
}
}
Show_2Byte(p.x/16,p.y,temp1,temp2);
}
}
void WDT_off(void)
{
__disable_interrupt();
__watchdog_reset();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Turn off WDT */
WDTCSR = 0x00;
__enable_interrupt();
}
void WDT_Prescaler_Change(void)
{
__disable_interrupt();
__watchdog_reset();
/* Start timed equence */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Set new prescaler(time-out) value = 64K cycles (~16 ms) */
WDTCSR = (1<<WDE);
__enable_interrupt();
}
void Snake::Restart()
{
//WDT_Prescaler_Change();
}
void main()
{
WDT_off();
Snake Snake1;
DDRB=0xff;
PORTA=0x00;
DDRA=0x00;
SPI_MasterInit();
LCD_INIT();
Clear_Gcrom();
Snake1.Generate_food();
while(1)
{
{
delay_ms(50);
Snake1.Go_ahead();
if(!K2)
{
Snake1.Turn_left();
}
if(!K3)
{
Snake1.Turn_up();
}
if(!K4)
{
Snake1.Turn_right();
}
if(!K5)
{
Snake1.Turn_down();
}
//if(Snake1.body[0].x<0||Snake1.body[0].x>127||Snake1.body[0].y<0||
Snake1.body[0].y>63)
//Snake1.Die();
}
}
}
///////////////////////////////////////////////////////////////////////////
<LCD12864.c>:
#define F_CPU 8
#include<ioavr.h>
#include"delay.h"
void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
//DDRB =(1<<7)|(1<<5)|(1<<4);//(1<<5)|(1<<7);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<6)|(1<<4);//|(1<<1)|0x01;//1<<SPE 1<<MSTR 1<<SPR1//128分频
SPSR = 1<<0;//SPI2X倍速
}
void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<7)));//1<<SPIF
}
void LCD_Write (char RS,char content)
{ char Start,High4,Low4;
Start=0xf8|(RS<<1);
High4=content&0xf0;
Low4=(content<<4)&0xf0;
//SS=1;
SPI_MasterTransmit(Start);
SPI_MasterTransmit(High4);
SPI_MasterTransmit(Low4);
//SS=0;
delay_us(300);
}
/*-----------------------------------*/
void LCD_INIT(void)
{
LCD_Write (0,0x30); /*30---基本指令动作*/
LCD_Write (0,0x01); /*清屏,地址指针指向00H*/
LCD_Write (0,0x06); /*光标的移动方向*/
LCD_Write (0,0x0c); /*开显示,关游标*/
}
/*--------------清DDRAM------------------*/
void ClearRam(void)
{
LCD_Write (0,0x30);
LCD_Write (0,0x01);
}
char lcd_x,lcd_y;
void Clear_Gcrom()
{
char i,j,k;
lcd_x=0x80;
lcd_y=0x80;
LCD_Write (0,0x34);
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
LCD_Write (0,lcd_y+j);
LCD_Write (0,lcd_x);
for(k=0;k<16;k++) { LCD_Write (1,0x00); }
}
lcd_x=0x88;
}
LCD_Write (0,0x36);
LCD_Write (0,0x30);
}
void Show_2Byte(char x,char y,char dat1,char dat2)// x:0~7 y:0~63
{
if(y<32)//下屏
{
x+=8;
y=31-y;
}
else//上屏
{
y=63-y;
}
LCD_Write (0,0x34);
LCD_Write (0,0x80+y);//y:0~31
LCD_Write (0,0x80+x);//x:0~15
LCD_Write (1,dat1);
LCD_Write (1,dat2);
LCD_Write (0,0x36);
LCD_Write (0,0x30);
}
void Show_Hang(char y,char p[64][16]) //显示一行 y:0~63
{
char k,y0=y;
lcd_y=0x80;
LCD_Write (0,0x34);
if(y<32)
{
lcd_x=0x80+8;//下屏
y=31-y;
}
else
{
lcd_x=0x80;//上屏
y=63-y;
}
//LCD_Write (0,0x80+0);//y1:0~31
//LCD_Write (0,0x80+0);//x1:0~15
LCD_Write (0,lcd_y+y);
LCD_Write (0,lcd_x);
for(k=0;k<16;k++) //写入显示数据
{ LCD_Write (1,p[y0][k]); }
LCD_Write (0,0x36);
LCD_Write (0,0x30);
}
//////////////////////////////////////////////////////////////////////////////
<delay.h>:
#ifndef __IAR_DELAY_H
#define __IAR_DELAY_H
#include <intrinsics.h>
#define delay_us(x) __delay_cycles ((unsigned long)(x * F_CPU))
#define delay_ms(x) __delay_cycles ((unsigned long)(x * F_CPU*1000UL))
#define delay_s(x) __delay_cycles ((unsigned long)(x * F_CPU*1000000UL))
#endif
//////////////////////////////////////////////////////////////////////////////
<function.h>:
#ifndef _FUNCTION_INCLUDED
#define _FUNCTION_INCLUDED
extern void Show_Hang(char y,char p[64][16]); //显示一行 y:0~63
extern void LCD_INIT(void);
extern void Clear_Gcrom();
extern void ClearRam(void);
extern void SPI_MasterInit(void);
extern void Show_2Byte(char x,char y,char dat1,char dat2);// x:0~7 y:0~63
#endif
[转载]轻松玩转LCD12864-基于AVR单片机的LCD12864串行显示
标签:
原文地址:http://www.cnblogs.com/watson8544/p/5581330.html