基于STM32设计的拼图小游戏详解

发布时间:2023-06-27  

一、环境介绍

MCU:STM32F103ZET6


编程软件环境:keil5

LCD显示屏:正点原子的TFT 3.5寸显示屏


二、运行效果

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


三、功能介绍

因为代码原来是在2.8寸屏上设计的,但是2.8寸屏摔碎了,现在手上只有块3.5寸的LCD屏。就把代码移植到3.5寸屏上显示了,目前运行的效果可以看上面的效果图。

拼图游戏在小时候还是经常玩,玩法也比较简单,这里就使用STM32设计一个拼图小游戏分享出来一起学习。

目前游戏是通过开发板上4按键进行控制图片的移动,完成最终的拼图效果,如果想要在上面扩充其他游戏功能都还是比较容易。

当然,设计编写这个款小游戏不仅仅是为了玩游戏这么简单,主要是为了通过设计游戏的过程学习STM32编程、LCD的编程、按键、图片等等很多编程知识。

做拼图这款游戏主要的硬件就是LCD显示屏和几个按键,没有其他外设,如果自己有其他STM32最小系统板有LCD显示屏的话,完全可以把代码移植过去运行。当前的代码兼容正点原子战舰开发板,可以直接在正点原子战舰直接编译下载运行。其他的开发板上运行也是一样的道理,底层替换自己LCD画点函数即可。

目前的拼图的游戏工程里图片是提前通过取模软件取好模之后把数据放在工程里的,如果想要动态更加灵活的切换拼图的图片,可以加上SD卡和FATFS文件系统,把图片放在SD卡,通过按键选择指定图片切割进行拼图。

代码分为3个部分:

1. LCD屏驱动代码部分

2. 按键驱动代码部分

3. 拼图的逻辑代码部分


四、LCD屏驱动代码

4.1 LCD介绍

这款LCD显示屏的驱动芯片型号是NT35310,时序支持8080时序,普通的MCU可以采用IO模拟8080时序驱动,有硬件接口的可以采用硬件接口驱动。STM32F103ZET6的FSMC是可以输出8080时序,为了提高刷屏速度,这里代码就采用FSMC接口来驱动LCD屏。照着LCD的手册指令集,自己编写一遍LCD的初始化代码,可以深入学习一遍LCD编程原理。

4.2 LCD显示屏的初始化代码示例

/*

函数功能:写寄存器函数

参    数:regval:寄存器值

*/  

void LcdWriteReg(u16 regval)

{

LCD_REG=regval;//写入要写的寄存器序号  

}



/*

函数功能:写LCD数据

函数参数:data:要写入的值

*/

void LcdWriteData(u16 data)

{  

LCD_RAM=data;  

}



/*

函数功能:读LCD数据

返 回 值:读到的值

*/

u16 LcdReadData(void)

{

vu16 ram; //防止被优化

ram=LCD_RAM;

return ram;  

}


/*

函数功能:读寄存器

函数参数:LCD_Reg:寄存器地址

返 回 值:读到的数据

*/

u16 LcdReadReg(u16 LCD_Reg)

{    

LcdWriteReg(LCD_Reg); //写入要读的寄存器序号

DelayUs(5);   

return LcdReadData(); //返回读到的值

}



/*

函数功能:开始写GRAM

*/

void LcdWriteRAM_Prepare(void)

{

  LCD_REG=0X2C;   

}



/*

函数功能:LCD写GRAM

函数参数:RGB_Code:颜色值

*/

void LcdWriteRAM(u16 RGB_Code)

{     

LCD_RAM = RGB_Code;//写十六位GRAM

}



/*

函数功能:设置光标位置

函数参数:

         Xpos:横坐标

         Ypos:纵坐标

*/

void LcdSetCursor(u16 Xpos, u16 Ypos)

{  

  LcdWriteReg(0X2A); 

LcdWriteData(Xpos>>8);

  LcdWriteData(Xpos&0XFF);  

LcdWriteReg(0X2B); 

LcdWriteData(Ypos>>8);

  LcdWriteData(Ypos&0XFF); 

}



/*

功能:读取个某点的颜色值

参数:x,y:坐标

返回值:此点的颜色

*/

u16 LcdReadPoint(u16 x,u16 y)

{

  u16 r=0,g=0,b=0;   

LcdSetCursor(x,y);     

LcdWriteReg(0X2E);

  r=LcdReadData(); //dummy Read    

DelayUs(1);   

  r=LcdReadData();    //实际坐标颜色


DelayUs(1);   

b=LcdReadData(); 

g=r&0XFF; //5310第一次读取的是RG的值,R在前,G在后,各占8位

g<<=8;

return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));

}





/*

功  能: 初始化LCD屏幕

说  明: 用于3.5寸屏幕的初始化。 

         LCD ID:5310

*/

void LcdInit(void)

{   

RCC->AHBENR|=1<<8;      //使能FSMC时钟   

  RCC->APB2ENR|=1<<3;      //使能PORTB时钟

RCC->APB2ENR|=1<<5;      //使能PORTD时钟

RCC->APB2ENR|=1<<6;      //使能PORTE时钟

  RCC->APB2ENR|=1<<8;      //使能PORTG时钟  

GPIOB->CRL&=0XFFFFFFF0; //PB0 推挽输出 背光

GPIOB->CRL|=0X00000003;    

//PORTD复用推挽输出

GPIOD->CRH&=0X00FFF000;

GPIOD->CRH|=0XBB000BBB; 

GPIOD->CRL&=0XFF00FF00;

GPIOD->CRL|=0X00BB00BB;     

//PORTE复用推挽输出

GPIOE->CRH&=0X00000000;

GPIOE->CRH|=0XBBBBBBBB; 

GPIOE->CRL&=0X0FFFFFFF;

GPIOE->CRL|=0XB0000000;         

//PORTG12复用推挽输出      

GPIOG->CRH&=0XFFF0FFFF;

GPIOG->CRH|=0X000B0000; 

GPIOG->CRL&=0XFFFFFFF0;//PG0->RS

GPIOG->CRL|=0X0000000B;  


//寄存器清零

//bank1有NE1~4,每一个有一个BCR+TCR,所以总共八个寄存器。

//这里我们使用NE4 ,也就对应BTCR[6],[7]。     

FSMC_Bank1->BTCR[6]=0X00000000;

FSMC_Bank1->BTCR[7]=0X00000000;

FSMC_Bank1E->BWTR[6]=0X00000000;

//操作BCR寄存器 使用异步模式

FSMC_Bank1->BTCR[6]|=1<<12; //存储器写使能

FSMC_Bank1->BTCR[6]|=1<<14; //读写使用不同的时序

FSMC_Bank1->BTCR[6]|=1<<4; //存储器数据宽度为16bit    

//操作BTR寄存器

//读时序控制寄存器     

FSMC_Bank1->BTCR[7]|=0<<28; //模式A    

FSMC_Bank1->BTCR[7]|=1<<0; //地址建立时间(ADDSET)为2个HCLK 1/36M=27ns(实际>200ns)  

//因为液晶驱动IC的读数据的时候,速度不能太快,尤其对1289这个IC。

FSMC_Bank1->BTCR[7]|=0XF<<8;  //数据保存时间为16个HCLK  

//写时序控制寄存器  

FSMC_Bank1E->BWTR[6]|=0<<28; //模式A     

FSMC_Bank1E->BWTR[6]|=0<<0; //地址建立时间(ADDSET)为1个HCLK 

 

//4个HCLK(HCLK=72M)因为液晶驱动IC的写信号脉宽,最少也得50ns。72M/4=24M=55ns   

FSMC_Bank1E->BWTR[6]|=3<<8; //数据保存时间为4个HCLK

//使能BANK1,区域4

FSMC_Bank1->BTCR[6]|=1<<0; //使能BANK1,区域4

DelayMs(50); // delay 50 ms 

  

lcddev.id=LcdReadReg(0x0000); //读ID(9320/9325/9328/4531/4535等IC)   


LcdWriteReg(0XD4);    

lcddev.id=LcdReadData();//dummy read  

lcddev.id=LcdReadData();//读回0X01  

lcddev.id=LcdReadData();//读回0X53

lcddev.id<<=8;  

lcddev.id|=LcdReadData(); //这里读回0X10  


printf(" LCD ID:%xrn",lcddev.id); //打印LCD ID

//if(lcddev.id==0x5310)

LcdWriteReg(0xED);

LcdWriteData(0x01);

LcdWriteData(0xFE);


LcdWriteReg(0xEE);

LcdWriteData(0xDE);

LcdWriteData(0x21);


LcdWriteReg(0xF1);

LcdWriteData(0x01);

LcdWriteReg(0xDF);

LcdWriteData(0x10);


//VCOMvoltage//

LcdWriteReg(0xC4);

LcdWriteData(0x8F);   //5f


LcdWriteReg(0xC6);

LcdWriteData(0x00);

LcdWriteData(0xE2);

LcdWriteData(0xE2);

LcdWriteData(0xE2);

LcdWriteReg(0xBF);

LcdWriteData(0xAA);


LcdWriteReg(0xB0);

LcdWriteData(0x0D);

LcdWriteData(0x00);

LcdWriteData(0x0D);

LcdWriteData(0x00);

LcdWriteData(0x11);

LcdWriteData(0x00);

LcdWriteData(0x19);

LcdWriteData(0x00);

LcdWriteData(0x21);

LcdWriteData(0x00);

LcdWriteData(0x2D);

LcdWriteData(0x00);

LcdWriteData(0x3D);

LcdWriteData(0x00);

LcdWriteData(0x5D);

LcdWriteData(0x00);

LcdWriteData(0x5D);

LcdWriteData(0x00);


LcdWriteReg(0xB1);

LcdWriteData(0x80);

LcdWriteData(0x00);

LcdWriteData(0x8B);

LcdWriteData(0x00);

LcdWriteData(0x96);

LcdWriteData(0x00);


LcdWriteReg(0xB2);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x02);

LcdWriteData(0x00);

LcdWriteData(0x03);

LcdWriteData(0x00);


LcdWriteReg(0xB3);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);


LcdWriteReg(0xB4);

LcdWriteData(0x8B);

LcdWriteData(0x00);

LcdWriteData(0x96);

LcdWriteData(0x00);

LcdWriteData(0xA1);

LcdWriteData(0x00);


LcdWriteReg(0xB5);

LcdWriteData(0x02);

LcdWriteData(0x00);

LcdWriteData(0x03);

LcdWriteData(0x00);

LcdWriteData(0x04);

LcdWriteData(0x00);


LcdWriteReg(0xB6);

LcdWriteData(0x00);

LcdWriteData(0x00);


LcdWriteReg(0xB7);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x3F);

LcdWriteData(0x00);

LcdWriteData(0x5E);

LcdWriteData(0x00);

LcdWriteData(0x64);

LcdWriteData(0x00);

LcdWriteData(0x8C);

LcdWriteData(0x00);

LcdWriteData(0xAC);

LcdWriteData(0x00);

LcdWriteData(0xDC);

LcdWriteData(0x00);

LcdWriteData(0x70);

LcdWriteData(0x00);

LcdWriteData(0x90);

LcdWriteData(0x00);

LcdWriteData(0xEB);

LcdWriteData(0x00);

LcdWriteData(0xDC);

LcdWriteData(0x00);


LcdWriteReg(0xB8);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);


LcdWriteReg(0xBA);

LcdWriteData(0x24);

LcdWriteData(0x00);

LcdWriteData(0x00);

LcdWriteData(0x00);


LcdWriteReg(0xC1);

LcdWriteData(0x20);

LcdWriteData(0x00);

LcdWriteData(0x54);

LcdWriteData(0x00);

LcdWriteData(0xFF);

LcdWriteData(0x00);


LcdWriteReg(0xC2);

LcdWriteData(0x0A);

LcdWriteData(0x00);

LcdWriteData(0x04);

LcdWriteData(0x00);


LcdWriteReg(0xC3);

LcdWriteData(0x3C);

LcdWriteData(0x00);

LcdWriteData(0x3A);

LcdWriteData(0x00);

LcdWriteData(0x39);

LcdWriteData(0x00);

LcdWriteData(0x37);

LcdWriteData(0x00);

LcdWriteData(0x3C);

LcdWriteData(0x00);

LcdWriteData(0x36);

LcdWriteData(0x00);

LcdWriteData(0x32);

LcdWriteData(0x00);

LcdWriteData(0x2F);

LcdWriteData(0x00);

LcdWriteData(0x2C);

LcdWriteData(0x00);

LcdWriteData(0x29);

LcdWriteData(0x00);

LcdWriteData(0x26);

LcdWriteData(0x00);

LcdWriteData(0x24);

LcdWriteData(0x00);

LcdWriteData(0x24);

LcdWriteData(0x00);

LcdWriteData(0x23);

LcdWriteData(0x00);

LcdWriteData(0x3C);

LcdWriteData(0x00);

LcdWriteData(0x36);

LcdWriteData(0x00);

LcdWriteData(0x32);

LcdWriteData(0x00);

LcdWriteData(0x2F);

LcdWriteData(0x00);

LcdWriteData(0x2C);

LcdWriteData(0x00);

LcdWriteData(0x29);

LcdWriteData(0x00);

LcdWriteData(0x26);

LcdWriteData(0x00);

LcdWriteData(0x24);

LcdWriteData(0x00);

LcdWriteData(0x24);

LcdWriteData(0x00);

LcdWriteData(0x23);

LcdWriteData(0x00);


LcdWriteReg(0xC4);

LcdWriteData(0x62);

LcdWriteData(0x00);

LcdWriteData(0x05);

LcdWriteData(0x00);

LcdWriteData(0x84);

LcdWriteData(0x00);

LcdWriteData(0xF0);

LcdWriteData(0x00);

LcdWriteData(0x18);

LcdWriteData(0x00);

LcdWriteData(0xA4);

LcdWriteData(0x00);

LcdWriteData(0x18);

LcdWriteData(0x00);

LcdWriteData(0x50);

LcdWriteData(0x00);

LcdWriteData(0x0C);

LcdWriteData(0x00);

LcdWriteData(0x17);

LcdWriteData(0x00);

LcdWriteData(0x95);

LcdWriteData(0x00);

LcdWriteData(0xF3);

LcdWriteData(0x00);

LcdWriteData(0xE6);

LcdWriteData(0x00);


LcdWriteReg(0xC5);

LcdWriteData(0x32);

LcdWriteData(0x00);

LcdWriteData(0x44);

LcdWriteData(0x00);

LcdWriteData(0x65);

LcdWriteData(0x00);

LcdWriteData(0x76);

LcdWriteData(0x00);

LcdWriteData(0x88);

LcdWriteData(0x00);


LcdWriteReg(0xC6);

LcdWriteData(0x20);

LcdWriteData(0x00);

LcdWriteData(0x17);

LcdWriteData(0x00);

LcdWriteData(0x01);

LcdWriteData(0x00);


LcdWriteReg(0xC7);

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>