AVR单片机运行俄罗斯方块.docx
《AVR单片机运行俄罗斯方块.docx》由会员分享,可在线阅读,更多相关《AVR单片机运行俄罗斯方块.docx(30页珍藏版)》请在冰豆网上搜索。
AVR单片机运行俄罗斯方块
AVR单片机俄罗斯方块游戏-(宋彦佑)
游戏已经尘封于多年,特拿出有需要的参考下
游戏基于AVRX系统运行于Atmega128单片机,基于Syany的绘图库支持,使用12864液晶屏显示
有需要的请到网上下载完成程序运行包.
graph.h
/*
//===========程序名称:
data_class.h=======================
//--程序目的:
绘图函数库V3.0----------------------
//-----设计&编写者:
宋彦佑--电子邮件:
syylmbhbB@-------
//------------程序&函数有存在BUG的可能------------------
//---可运行在AVR8位单片机上并且具有极高的运算效率----------
//----严禁用于商业目的,否则后果自负------
//------------作者保留此代码的所有权力------------------
//--CopyrightYanyouSong,Allrightsreserved.---------------
//----设计日期:
2006------------------
//======================================================
//本图形库提供最基本的绘图功能,不提供图形的变幻,有兴趣的读者可以自己研究.
//最后更新日期:
2011
*/
#ifndef_GRAPH_
#define_GRAPH_1
#include
#include
//定义图形缓冲大小
#defineBufferXSize128//此处为液晶屏的横向的点数,修改为实际的点数
#defineBufferYSize64//此处为液晶屏的列数,修改为实际的列数
//以下不需要修改
#defineBufferColumnZBufferXSize/8
#defineBufferLinesZBufferYSize
unsignedcharSBuffer[BufferColumnZ][BufferLinesZ];//内存定义的图形缓冲数组
//-----------------------
//清除定义缓冲区
//0清除1全屏点亮2取反
//-----------------------
voidScreenrClr(unsignedcharRevClr);
//----------------------------
//缓冲区绘点
//大于定义缓冲区,不执行,操作
//0清点,1划点,2取反
//----------------------------
voidPixel(intBX,intBY,unsignedcharFill);
//---------限定区域向左移动1列-----------------------
//当Fill为0时以0填充,当为1时以1填充,当为2时循环填充
//EndX-StartX必须大于8
//----------------2006-04-09---------------------
voidMoveLeft(intStartX,intStartY,intEndX,intEndY,unsignedcharFill);
//---------限定区域向右移动1列-----------------------
//当Fill为0时以0填充,当为1时以1填充,当为2时循环填充
//EndX-StartX必须大于8
//----------------2006-04-09---11:
16------------------
voidMoveRight(intStartX,intStartY,intEndX,intEndY,unsignedcharFill);
//---------限定区域向上移动1列-----------------------
//当Fill为0时以0填充,当为1时以1填充,当为2时循环填充
//EndX-StartX必须大于8
//2006-04-30testok
voidMoveUp(intStartX,intStartY,intEndX,intEndY,unsignedcharFill);
//---------限定区域向下移动1列-----------------------
//当Fill为0时以0填充,当为1时以1填充,当为2时循环填充
//EndX-StartX必须大于8
//2006-04-30writeandtestok
voidMoveDown(intStartX,intStartY,intEndX,intEndY,unsignedcharFill);
//---------整屏向上移动16点------------------------
voidMoveUpLines16(void);
//---------整屏向上移动8点------------------------
voidMoveUpLines8(void);
//------------------------------------------------------------------
//----任意大小图片据载入程序,访问程序存储器
//----StartX显示缓冲对一屏幕的起始值,缓冲对应屏幕左上角,坐标为0,0此参数对应的范围是
//----PX图片的大小,允许非8的整数倍,但是图片数据必须为8的整数倍
//----Fill-0
//--------------------------------------------------------------------------
voidBLoadP(intStartX,intStartY,intPX,intPY,constprog_void*TableP,charFill);
//------------规定区域取反函数------------------
voidLimitReverse(intStartX,intStartY,intEndX,intEndY);
//----------画线函数-----------------
//0清线,1划线,2取反--------
//---任意方向绘制直线----
//2006-05-06
voidLine(intStartX,intStartY,intEndX,intEndY,charFill);
//-------------画三角形-----------
//Fill0清,1划,2取反--------
voidTrigon(intXA,intYA,intXB,intYB,intXC,intYC,charFill);
//---------画矩形函数---------------------
//2006-05-06--
//fill0不填充,1填充,2网格填充(网格只有填充模式)
//Fill0清,1划,2取反--------
voidBox(intStartX,intStartY,intEndX,intEndY,charDM,charFill);
//-----------画圆函数-----------
voidCircle(intCX,intCY,intCR,charFill);
//--------绘制椭圆函数---------------
voidEllipe(intCX,intCY,intEA,intEB,charFill);
#endif
GameTetris.h
//=======指示LED控制相关声明==================
TimerControlBlockRunningLEDDelay;
AVRX_GCC_TASKDEF(RunningLedControl,35,8);
//==============键盘扫描任务相关定义================
TimerControlBlockKeyScanDelay;
AVRX_GCC_TASKDEF(KeyScan,40,4);//LedTask1任务声明,占用40字节堆栈,任务优先级3
unsignedcharKeyPushed;//
unsignedcharKeyValue;//
unsignedcharKeyPushDown;//
//按键分配给哪个端口,如果需要改变按键顺序,只需要改变定义的顺序即可
#defineKeyUP0x01//PD0
#defineKeyLeft0x02//PD1
#defineKeyRight0x04//PD2
#defineKeyDown0x08//PD3
#defineKeyStart0x10//PD3
//===========液晶屏相关定义=======================
TimerControlBlockLcdDelay;
//如果需要更改相关液晶屏连接引脚,只需在此处修改即可
//液晶启动复位延时最大65536
#defineRestDelay3000
////下面是宏定义,LCD总线接口
#defineDDRDATADDRA
#definePORTDATAPORTA
//RD信号定义--读信号
#defineDDr_RD_SINGAL_Out(DDRG|=(1<<1))
#definePort_RD_SINGAL_L(PORTG&=~(1<<1))
#definePort_RD_SINGAL_H(PORTG|=(1<<1))
//WR信号定义--写信号
#defineDDr_WR_SINGAL_Out(DDRG|=(1<<0))
#definePort_WR_SINGAL_L(PORTG&=~(1<<0))
#definePort_WR_SINGAL_H(PORTG|=(1<<0))
//RS信号定义-数据/指令信号
#defineDDr_RS_SINGAL_Out(DDRC|=(1<<0))
#definePort_RS_SINGAL_L(PORTC&=~(1<<0))
#definePort_RS_SINGAL_H(PORTC|=(1<<0))
//RST信号定义--复位信号
#defineDDr_RST_SINGAL_Out(DDRC|=(1<<2))
#definePort_RST_SINGAL_L(PORTC&=~(1<<2))
#definePort_RST_SINGAL_H(PORTC|=(1<<2))
//CS信号定义-选择信号低电平有效
#defineDDr_CE_SINGAL_Out(DDRC|=(1<<1))
#definePort_CE_SINGAL_L(PORTC&=~(1<<1))
#definePort_CE_SINGAL_H(PORTC|=(1<<1))
//液晶函数声明
voidlcd_command_write(unsignedchardata_8);
voidlcd_data_write(unsignedchardata_8);
//显示开关函数0开大于0关
voidlcd_on_off(unsignedchardata_8);
//显示起始行设置范围0~64
voidlcd_display_start_line(unsignedchardata_8);
//页地址设置范围0~7
voidlcd_page_address_set(unsignedchardata_8);
//列地址设置范围0~131
voidlcd_column_address_set(unsignedchardata_8);
//驱动输出0正常大于0反向水平
voidlcd_adc_select(unsignedchardata_8);
//输出反向0正常大于0反向整体
voidlcd_display_normal(unsignedchardata_8);
//液晶屏显示方向设置 输出反向0正常大于0反向垂直
voidlcd_out_modol_seclet(unsignedchardata_8);
//液晶屏写入
voidlcd_screen_write(unsignedcharx,unsignedchary,unsignedchardata_8);
//屏幕亮度设置
voidlcd_volume(unsignedcharvolume);
//液晶屏 实时更新 任务=
//AVRX_GCC_TASKDEF(LcdUpData,100,5);
//===============游戏定义=================
TimerControlBlockgraph_act;
#defineTIMER0x1c//inruningTimerCounter=0;
#defineSIZE3
#defineSCOREINTERVAL30
//游戏变量定义
unsignedcharboard[12][22];//gameboard
intCurShape;//indexofshapewhichisfalling
intsx,sy;//coordernateofshapewhichisfalling
intnext=-1;//indexofnextshapeprepared
unsignedintscore=0;
unsignedcharspeed=0,lnNextLevelScore=SCOREINTERVAL;
unsignedcharTimerCounter=0;
enumbool{False=0,True=1};
enumboolfGameOver=False,fAccel=False;
enumdirect{Left,Right,Down};
structshape
{
charxy[8];
charnext;
};
structshapeshapes[19]=
{
//{x1,y1,x2,y2,x3,y3,x4,y4,next}
{0,-2,0,-1,0,0,1,0,1},//
{-1,0,0,0,1,-1,1,0,2},//█
{0,-2,1,-2,1,-1,1,0,3},//█
{-1,-1,-1,0,0,-1,1,-1,0},//██
{0,-2,0,-1,0,0,1,-2,5},//
{-1,-1,-1,0,0,0,1,0,6},//██
{0,0,1,-2,1,-1,1,0,7},//█
{-1,-1,0,-1,1,-1,1,0,4},//█
{-1,0,0,-1,0,0,1,0,9},//
{-1,-1,0,-2,0,-1,0,0,10},//
{-1,-1,0,-1,0,0,1,-1,11},//█
{0,-2,0,-1,0,0,1,-1,8},//███
{-1,0,0,-1,0,0,1,-1,13},//██
{0,-2,0,-1,1,-1,1,0,12},//██
{-1,-1,0,-1,0,0,1,0,15},//██
{0,-1,0,0,1,-2,1,-1,14},//██
{0,-3,0,-2,0,-1,0,0,17},//█
{-1,0,0,0,1,0,2,0,16},//█
//█
//█
{0,-1,0,0,1,-1,1,0,18},//██
//██
};
//游戏函数声明
intGetNextShape(void);
voidNumBoard(void);
voidDrawBlock(charx,chary);
voidDrawShape(unsignedcharindex,unsignedcharsx,unsignedcharsy);
voidNewGame(void);
enumboolConfilict(intShapeIndex,intx,inty);
enumboolMoveable(intShapeIndex,intx,inty,enumdirectdir);
voidMove(intShapeIndex,int*x,int*y,enumdirectdir);
enumboolRollable(intShapeIndex,intx,inty,int*offset);
voidRoll(int*ShapeIndex,int*x,inty,intoffset);
voidDeleteRow(inty);
enumboolRowFull(inty);
intDeleteRows(inty);
intBonus(unsignedcharnum);
enumboolCheckGameOver(void);
enumboolGameOver(void);
AVRX_GCC_TASKDEF(tetris,180,11);//俄罗斯方块任务
//-------------------------------
GameTetrisMain.c
#include
#include
#include"avrx.h"
#include
#include
#include
#include"graph.h"
#include"GameTetris.h"
//=============================================================
AVRX_SIGINT(SIG_OVERFLOW0)
{
IntProlog();//Switchtokernelstack/context
TCNT0+=162;
AvrXTimerHandler();//CallTimequeuemanager
Epilog();//Returntotasks
}
//============键盘扫描处理任务=========================
NAKEDFUNC(KeyScan)
{
unsignedcharPDRD;
DDRD&=0xf0;//将按键端口PD0123设置为输入
PORTD|=0x0f;//将按键端口PD0123设置为上拉
while
(1)//死循环一直执行
{
AvrXDelay(&KeyScanDelay,10);
PDRD=PIND&0x0f;//读取PD引脚并只保留0~3引脚数值
switch(PDRD)//确定哪个按键
{
caseKeyUP:
//
if(KeyPushDown==0)//当按键从抬起变化到按下时有效,否则无效,按键按下只有一次有效
{
KeyValue=KeyUP;//设置按下的按键数值
KeyPushDown=1;//设置变量为1,再次循环到此处,按键无效,除非抬起按键
KeyPushed=1;//设置变量为1通知程序有新按键按下,程序收到后将变量设置为0
}
break;
caseKeyLeft:
//
if(KeyPushDown==0)//当按键从抬起变化到按下时有效,否则无效,按键按下只有一次有效
{
KeyValue=KeyLeft;//设置按下的按键数值
KeyPushDown=1;//设置变量为1,再次循环到此处,按键无效,除非抬起按键
KeyPushed=1;//设置变量为1通知程序有新按键按下,程序收到后将变量设置为0
}
break;
caseKeyRight:
//
if(KeyPushDown==0)//当按键从抬起变化到按下时有效,否则无效,按键按下只有一次有效
{
KeyValue=KeyRight;//设置按下的按键数值
KeyPushDown=1;//设置变量为1,再次循环到此处,按键无效,除非抬起按键
KeyPushed=1;//设置变量为1通知程序有新按键按下,程序收到后将变量设置为0
}
break;
caseKeyDown:
//
if(KeyPushDown==0)//当按键从抬起变化到按下时有效,否则无效,按键按下只有一次有效
{
KeyValue=KeyDown;//设置按下的按键数值
KeyPushDown=1;//设置变量为1,再次循环到此处,按键无效,除非抬起按键
KeyPushed=1;//设置变量为1通知程序有新按键按下,程序收到后将变量设置为0
}
break;
caseKeyStart:
//
if(KeyPushDown==0)//当按键从抬起变化到按下时有效,否则无效,按键按下只有一次有效
{
KeyValue=KeyStart;//设置按下的按键数值
KeyPushDown=1;//设置变量为1,再次循环到此处,按键无效,除非抬起按键
KeyPushed=1;//设置变量为1通知程序有新按键按下,程序收到后将变量设置为0
}
break;
default:
KeyPushDown=0;
break;
}
}
}
//============液晶屏操作相关函数=====================
//写指令
voidlcd