STM32课程设计贪吃蛇.docx
《STM32课程设计贪吃蛇.docx》由会员分享,可在线阅读,更多相关《STM32课程设计贪吃蛇.docx(21页珍藏版)》请在冰豆网上搜索。
STM32课程设计贪吃蛇
STM32大作业报告
学生姓名:
学号:
所在院系:
光电信息与计算机工程学院
专业班级:
授课教师:
完成时间:
2016年
前言
随着科学技术的不断进步,嵌入式近些年来逐渐兴起,其领域比较新,发展非常迅速,由于它属于新兴领域,接触的人并不是很多,但是嵌入式在各种电子设备上的应用越来越越广泛,并且各种电子设备也在朝着嵌入式微系统,智能化的方向前进。
STM32系列是基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARMCortex-M内核。
作为21世纪的人才,为了与社会实际需要相衔接,提高我们的学习兴趣,利用STM32系列单片机进行了一次嵌入式系统设计。
摘要
在本次作业中采用STM32系列中的STM32F103RCT6微控制器芯片,采用ALIENTEK战舰STM32开发板,使用MiniSTM32开发板上的LCD接口,来点亮TFTLCD,实现触摸屏功能。
一、课程设计任务要求
本次的课程设计目的是实现一个经典的贪吃蛇游戏,整个游戏实现功能分别为:
1、初始化程序。
2、随机红点、左转、右转、判断边框。
二、系统硬件设计
硬件设计原理图
根据此硬件设计图再结合软件设计就能做出此游戏。
三、系统软件实现
此次的课程设计在于开发个贪吃蛇游戏,其流程图如下图所示。
程序流程图
为方便介绍,此软件实现只给出主要程序部分:
1、本例程提供了硬件平台的初始化
GPIO是常规输入/输出端口,STM32F103RCT6有PA、PB、PC、PD、PE共5个16位的GPIO。
STM32的GPIO都可编程,具有很多复用功能。
GPIO可以配置为很多总模式,这些模式有:
输入浮空、输入上拉、输入下拉、模拟输入、开漏输入、推挽输出、推挽复用、开漏复用。
通过对GPIO寄存器编程,可以设置每个端口的工作模式。
24C02EEPROM是开发板板载的2Kbit(256个字节)EEPROM,型号为:
24C02,用于掉电数据保存。
因为STM32内部没有EEPROM,所开发板外扩了24C02,用于存储重要数据,用来做IIC实验,该芯片直接挂在STM32的IO口上。
IIC(Inter-IntegratedCircuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。
在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。
IIC总线在传送数据过程中共有三种类型信号,它们分别是:
开始信号、结束信号和应答信号。
开始信号:
SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:
SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号:
接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。
CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。
若未收到应答信号,由判断为受控单元出现故障。
/********************************************************************
*名称:
AT24CXX_Init(void)
*功能:
初始化IIC接口
********************************************************************/
//初始化IIC接口
voidAT24CXX_Init(void)
{
IIC_Init();
}
voidIIC_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//先使能外设IOPORTC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
/*******************************************************************
*名称:
voidCMLCD_Init(void)
*功能:
初始化触摸屏的硬件接口
********************************************************************/
voidCMLCD_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能PORTC时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_3|GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//设置成推免输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化GPIOC0313
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;//初始化GPIOC21
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
TPEN=1;
}
2、贪吃蛇功能控制
SPI是串行外设端口,是一种同步串行外设端口,它可以使MCU与各种外围设备以串行方式进行通信、交换信息。
STM32的SPI支持全双工同步传输,可选择以8或16位传输帧格式进行传输,支持多种模式。
USART为STM32的同步异步接收器。
它提供了一种灵活的方法与使用异步串行数据格式的外部设备之间进行全双工数据交换。
USART利用分数波特率发生器提供宽范围的波特率选择。
另外,它还允许多处理器通信。
USART也可以使用DMA方式直接将接受的数据存储到内存或从内存中批量发送数据,也支持多种中断方式。
TFT-LCD即薄膜晶体管液晶显示器。
其英文全称为:
ThinFilmTransistor-LiquidCrystalDisplay。
TFT-LCD与无源TN-LCD、STN-LCD的简单矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。
TFT-LCD也被叫做真彩液晶显示器。
ALIENTEK提供的2.8寸TFTLCD模块,其驱动芯片有很多种类型,比如有:
ILI9341/ILI9325/RM68042/RM68021/ILI9320/ILI9328/LGDP4531/LGDP4535/SPFD5408/SSD1289/1505/B505/C505/NT35310/NT35510等。
LED(DS0和DS1)。
其电路在ALIENTEKMiniSTM32开发板上默认是已经连接好了的。
DS0接PA8,DS1接PD2。
/********************************************************************
*名称:
intmain(void)
*功能:
主函数
********************************************************************/
#include"led.h"
#include"delay.h"
#include"sys.h"
#include"usart.h"
#include"lcd.h"
#include"tanchishe.h"
#include"cmlcd.h"
#include"timeit.h"
#include"stdlib.h"
//画一个大点(2*2的点)
//x,y:
坐标
//color:
颜色
voidTP_Draw_Big_Point(u16x,u16y,u16color)
{
POINT_COLOR=color;
LCD_DrawPoint(x,y);//中心点
LCD_DrawPoint(x+1,y);
LCD_DrawPoint(x,y+1);
LCD_DrawPoint(x+1,y+1);
}
intmain(void)
{
u8sta,sta1;
u16rand_color;
delay_init();//延时函数初始化
uart_init(9600);//串口初始化为9600
LED_Init();//初始化与LED连接的硬件接口
LCD_Init();
time_init();
CMLCD_Init();//触摸屏初始化
AT24CXX_Init();//eeprom初始化
sta1=TP_Get_Adjdata();
if(!
sta1)
{
sta=CMLCD_Adjust();
if(sta)
{
TP_Save_Adjdata();//校准成功就保存参数
LCD_ShowString(40,40,100,16,16,"SUCCESSFUL!
");
}
else
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
}
}
TABCHISHE_Init();
while
(1)
{
delay_ms(500);
//产生随机坐标
if(snake.eat_sta)
{
snake.eat_sta=0;
snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
rand_color=LCD_ReadPoint(snake.rand_x,snake.rand_y);
while(rand_color==BLUE)//随机点不能是蛇身上的点
{
snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
rand_color=LCD_ReadPoint(snake.rand_x,snake.rand_y);
}
LCD_Fill(snake.rand_x,snake.rand_y,snake.rand_x+snake.size,snake.rand_y+snake.size,RED);
}
LED0=!
LED0;
TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);//关中断防止中断服务函数对显示坐标的影响
snake.eat_sta=show(snake.d1);
disappear(snake.d2,turn);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//开中断
}
}
/*******************************************************************
*名称:
voidTABCHISHE_Init(void)
*功能:
贪吃蛇初始化
********************************************************************/
voidTABCHISHE_Init(void)
{
Shuzu_Init(turn);//转向数组初始化
LCD_Clear(WHITE);
POINT_COLOR=RED;
LCD_DrawLine(0,282,240,282);
LCD_DrawLine(120,280,120,320);
LCD_ShowString(20,290,72,12,12,"left/down");
LCD_ShowString(20,303,36,12,12,"score:
");
LCD_ShowString(140,290,64,12,12,"right/up");
//以下为贪吃蛇程序初始化
LCD_Fill(120,160,136,168,BLUE);//一开始蛇长度为2个SIZE
snake.eat_sta=0;
snake.length=2;
LCD_ShowxNum(56,303,snake.length,3,12,0x80);
snake.max=MAX;
snake.size=8;
snake.d1=0;
snake.d2=0;
snake.x1=128;snake.x2=snake.x1+snake.size;snake.y1=160;snake.y2=snake.y1+snake.size;
snake.X1=112;snake.X2=snake.X1+snake.size;snake.Y1=160;snake.Y2=snake.Y1+snake.size;
snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
LCD_Fill(snake.rand_x,snake.rand_y,snake.rand_x+snake.size,snake.rand_y+snake.size,RED);
}
/*******************************************************************
*名称:
voiddisappear(u8d,u16turn[MAX][3])
*功能:
贪吃蛇移动尾部消失格子
********************************************************************/
//新消失的一格
//参数:
往左消失,往右消失
voiddisappear(u8d,u16turn[MAX][3])
{
inti=0;
if(d==0)//默认方向为从左到右
{
snake.X1=snake.X1+snake.size;snake.X2=snake.X2+snake.size;
LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE);//新显示的一格
}
elseif(d==1)//方向为下到上
{
snake.Y1=snake.Y1-snake.size;snake.Y2=snake.Y2-snake.size;
LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE);//新显示的一格
}
elseif(d==2)//方向为右到左
{
snake.X1=snake.X1-snake.size;snake.X2=snake.X2-snake.size;
LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE);//新显示的一格
}
elseif(d==3)//方向为上到下
{
snake.Y1=snake.Y1+snake.size;snake.Y2=snake.Y2+snake.size;
LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE);//新显示的一格
}
for(i=0;i{
if(snake.X1==turn[i][0]&&snake.Y1==turn[i][1])
{
snake.d2=turn[i][2];
turn[i][0]=400;//转向完毕清除记录的坐标(将坐标变为LCD以外区域)
turn[i][1]=400;
break;
}
}
}
/*******************************************************************
*名称:
u8show(u8d)
*功能:
贪吃蛇移动前部新增格子
********************************************************************/
//新显示的一格
//参数:
往左显示,往右显示
u8show(u8d)
{
staticu8i=0;
u16color,color1;
//判断是否撞到自己的身体
if(d==0)
{
color=LCD_ReadPoint(snake.x2+4,snake.y2-4);
color1=LCD_ReadPoint(snake.x2+3,snake.y2-3);
if(color==BLUE&&color1==BLUE)
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
printf("color%xcolor1%x\r\n",color,color1);
printf("shezhuangziji0\r\n");
delay_ms(5000);
TABCHISHE_Init();
d=snake.d1;
}
}
elseif(d==1)
{
color=LCD_ReadPoint(snake.x1+4,snake.y1-4);
color1=LCD_ReadPoint(snake.x1+3,snake.y1-3);
if(color==BLUE&&color1==BLUE)
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
printf("color%xcolor1%x\r\n",color,color1);
printf("shezhuangziji1%d%d%d\r\n",snake.d1,snake.d2,d);
delay_ms(5000);
TABCHISHE_Init();
d=snake.d1;
printf("%d%d%d\r\n",snake.d1,snake.d2,d);
}
}
elseif(d==2)
{
color=LCD_ReadPoint(snake.x1-4,snake.y1+4);
color1=LCD_ReadPoint(snake.x1-3,snake.y1+3);
if(color==BLUE&&color1==BLUE)
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
printf("color%xcolor1%x\r\n",color,color1);
printf("shezhuangziji2\r\n");
delay_ms(5000);
TABCHISHE_Init();
d=snake.d1;
}
}
elseif(d==3)
{
color=LCD_ReadPoint(snake.x2-4,snake.y2+4);
color1=LCD_ReadPoint(snake.x2-3,snake.y2+3);
if(color==BLUE&&color1==BLUE)
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
printf("color%xcolor1%x\r\n",color,color1);
printf("shezhuangziji3\r\n");
delay_ms(5000);
TABCHISHE_Init();
d=snake.d1;
}
}
if((snake.y1==0&&d==1)||(snake.x1==0&&d==2)||(snake.y2==280&&d==3)||(snake.x2==240&&d==0))//蛇撞到墙了
{
LCD_ShowString(40,40,100,16,16,"NOSUCCESSFUL!
");
printf("shezhuangqiang\r\n");
delay_ms(5000);
TABCHISHE_Init();
d=snake.d1;
}
if(snake.rand_x==snake.x1&&snake.rand_y==snake.y1)//判断是否增加长度即碰到随机点
{
i=1;
if(snake.d2==0)
{snake.X1-=16;snake.X2-=16;}//在尾端增加一格
elseif(snake.d2==1)
{snake.Y1+=16;snake.Y2+=16;}
elseif(snake.d2==2)
{snake.X1+=16;snak