写点什么

基于 STM32 设计的拼图小游戏

作者:DS小龙哥
  • 2022 年 8 月 24 日
    重庆
  • 本文字数:14763 字

    阅读完需:约 48 分钟

一、环境介绍

MCU: STM32F103ZET6


编程软件环境: keil5


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

二、运行效果



三、功能介绍

因为代码原来是在 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:%x\r\n",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); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00);
LcdWriteReg(0xC8); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00);
LcdWriteReg(0xC9); 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(0xE0); LcdWriteData(0x16); LcdWriteData(0x00); LcdWriteData(0x1C); LcdWriteData(0x00); LcdWriteData(0x21); LcdWriteData(0x00); LcdWriteData(0x36); LcdWriteData(0x00); LcdWriteData(0x46); LcdWriteData(0x00); LcdWriteData(0x52); LcdWriteData(0x00); LcdWriteData(0x64); LcdWriteData(0x00); LcdWriteData(0x7A); LcdWriteData(0x00); LcdWriteData(0x8B); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0xA8); LcdWriteData(0x00); LcdWriteData(0xB9); LcdWriteData(0x00); LcdWriteData(0xC4); LcdWriteData(0x00); LcdWriteData(0xCA); LcdWriteData(0x00); LcdWriteData(0xD2); LcdWriteData(0x00); LcdWriteData(0xD9); LcdWriteData(0x00); LcdWriteData(0xE0); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00);
LcdWriteReg(0xE1); LcdWriteData(0x16); LcdWriteData(0x00); LcdWriteData(0x1C); LcdWriteData(0x00); LcdWriteData(0x22); LcdWriteData(0x00); LcdWriteData(0x36); LcdWriteData(0x00); LcdWriteData(0x45); LcdWriteData(0x00); LcdWriteData(0x52); LcdWriteData(0x00); LcdWriteData(0x64); LcdWriteData(0x00); LcdWriteData(0x7A); LcdWriteData(0x00); LcdWriteData(0x8B); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0xA8); LcdWriteData(0x00); LcdWriteData(0xB9); LcdWriteData(0x00); LcdWriteData(0xC4); LcdWriteData(0x00); LcdWriteData(0xCA); LcdWriteData(0x00); LcdWriteData(0xD2); LcdWriteData(0x00); LcdWriteData(0xD8); LcdWriteData(0x00); LcdWriteData(0xE0); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00);
LcdWriteReg(0xE2); LcdWriteData(0x05); LcdWriteData(0x00); LcdWriteData(0x0B); LcdWriteData(0x00); LcdWriteData(0x1B); LcdWriteData(0x00); LcdWriteData(0x34); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00); LcdWriteData(0x4F); LcdWriteData(0x00); LcdWriteData(0x61); LcdWriteData(0x00); LcdWriteData(0x79); LcdWriteData(0x00); LcdWriteData(0x88); LcdWriteData(0x00); LcdWriteData(0x97); LcdWriteData(0x00); LcdWriteData(0xA6); LcdWriteData(0x00); LcdWriteData(0xB7); LcdWriteData(0x00); LcdWriteData(0xC2); LcdWriteData(0x00); LcdWriteData(0xC7); LcdWriteData(0x00); LcdWriteData(0xD1); LcdWriteData(0x00); LcdWriteData(0xD6); LcdWriteData(0x00); LcdWriteData(0xDD); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00); LcdWriteReg(0xE3); LcdWriteData(0x05); LcdWriteData(0x00); LcdWriteData(0xA); LcdWriteData(0x00); LcdWriteData(0x1C); LcdWriteData(0x00); LcdWriteData(0x33); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00); LcdWriteData(0x50); LcdWriteData(0x00); LcdWriteData(0x62); LcdWriteData(0x00); LcdWriteData(0x78); LcdWriteData(0x00); LcdWriteData(0x88); LcdWriteData(0x00); LcdWriteData(0x97); LcdWriteData(0x00); LcdWriteData(0xA6); LcdWriteData(0x00); LcdWriteData(0xB7); LcdWriteData(0x00); LcdWriteData(0xC2); LcdWriteData(0x00); LcdWriteData(0xC7); LcdWriteData(0x00); LcdWriteData(0xD1); LcdWriteData(0x00); LcdWriteData(0xD5); LcdWriteData(0x00); LcdWriteData(0xDD); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00);
LcdWriteReg(0xE4); LcdWriteData(0x01); LcdWriteData(0x00); LcdWriteData(0x01); LcdWriteData(0x00); LcdWriteData(0x02); LcdWriteData(0x00); LcdWriteData(0x2A); LcdWriteData(0x00); LcdWriteData(0x3C); LcdWriteData(0x00); LcdWriteData(0x4B); LcdWriteData(0x00); LcdWriteData(0x5D); LcdWriteData(0x00); LcdWriteData(0x74); LcdWriteData(0x00); LcdWriteData(0x84); LcdWriteData(0x00); LcdWriteData(0x93); LcdWriteData(0x00); LcdWriteData(0xA2); LcdWriteData(0x00); LcdWriteData(0xB3); LcdWriteData(0x00); LcdWriteData(0xBE); LcdWriteData(0x00); LcdWriteData(0xC4); LcdWriteData(0x00); LcdWriteData(0xCD); LcdWriteData(0x00); LcdWriteData(0xD3); LcdWriteData(0x00); LcdWriteData(0xDD); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00); LcdWriteReg(0xE5); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x02); LcdWriteData(0x00); LcdWriteData(0x29); LcdWriteData(0x00); LcdWriteData(0x3C); LcdWriteData(0x00); LcdWriteData(0x4B); LcdWriteData(0x00); LcdWriteData(0x5D); LcdWriteData(0x00); LcdWriteData(0x74); LcdWriteData(0x00); LcdWriteData(0x84); LcdWriteData(0x00); LcdWriteData(0x93); LcdWriteData(0x00); LcdWriteData(0xA2); LcdWriteData(0x00); LcdWriteData(0xB3); LcdWriteData(0x00); LcdWriteData(0xBE); LcdWriteData(0x00); LcdWriteData(0xC4); LcdWriteData(0x00); LcdWriteData(0xCD); LcdWriteData(0x00); LcdWriteData(0xD3); LcdWriteData(0x00); LcdWriteData(0xDC); LcdWriteData(0x00); LcdWriteData(0xF3); LcdWriteData(0x00);
LcdWriteReg(0xE6); LcdWriteData(0x11); LcdWriteData(0x00); LcdWriteData(0x34); LcdWriteData(0x00); LcdWriteData(0x56); LcdWriteData(0x00); LcdWriteData(0x76); LcdWriteData(0x00); LcdWriteData(0x77); LcdWriteData(0x00); LcdWriteData(0x66); LcdWriteData(0x00); LcdWriteData(0x88); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0xBB); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0x66); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00); LcdWriteData(0x45); LcdWriteData(0x00); LcdWriteData(0x43); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00);
LcdWriteReg(0xE7); LcdWriteData(0x32); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00); LcdWriteData(0x76); LcdWriteData(0x00); LcdWriteData(0x66); LcdWriteData(0x00); LcdWriteData(0x67); LcdWriteData(0x00); LcdWriteData(0x67); LcdWriteData(0x00); LcdWriteData(0x87); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0xBB); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0x77); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00); LcdWriteData(0x56); LcdWriteData(0x00); LcdWriteData(0x23); LcdWriteData(0x00); LcdWriteData(0x33); LcdWriteData(0x00); LcdWriteData(0x45); LcdWriteData(0x00);
LcdWriteReg(0xE8); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0x87); LcdWriteData(0x00); LcdWriteData(0x88); LcdWriteData(0x00); LcdWriteData(0x77); LcdWriteData(0x00); LcdWriteData(0x66); LcdWriteData(0x00); LcdWriteData(0x88); LcdWriteData(0x00); LcdWriteData(0xAA); LcdWriteData(0x00); LcdWriteData(0xBB); LcdWriteData(0x00); LcdWriteData(0x99); LcdWriteData(0x00); LcdWriteData(0x66); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00); LcdWriteData(0x44); LcdWriteData(0x00); LcdWriteData(0x55); LcdWriteData(0x00);
LcdWriteReg(0xE9); LcdWriteData(0xAA); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00);
LcdWriteReg(0x00); LcdWriteData(0xAA);
LcdWriteReg(0xCF); 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(0xF0); LcdWriteData(0x00); LcdWriteData(0x50); LcdWriteData(0x00); LcdWriteData(0x00); LcdWriteData(0x00);
LcdWriteReg(0xF3); LcdWriteData(0x00);
LcdWriteReg(0xF9); LcdWriteData(0x06); LcdWriteData(0x10); LcdWriteData(0x29); LcdWriteData(0x00);
LcdWriteReg(0x3A); LcdWriteData(0x55); //66
LcdWriteReg(0x11); DelayMs(100); LcdWriteReg(0x29); LcdWriteReg(0x35); LcdWriteData(0x00);
LcdWriteReg(0x51); LcdWriteData(0xFF); LcdWriteReg(0x53); LcdWriteData(0x2C); LcdWriteReg(0x55); LcdWriteData(0x82); LcdWriteReg(0x2c); lcddev.width=320; lcddev.height=480; LCD_LED=1; //点亮背光}
复制代码

4.3 LCD 相关的绘图函数代码示例

/*函数功能:画点函数参    数:x,y坐标          color颜色值*/void LcdDrawPoint(u16 x,u16 y,u16 color){  LcdSetCursor(x,y);      //设置光标位置   LcdWriteRAM_Prepare();  //开始写入GRAM  LCD_RAM=color; }

/*函数功能:清屏函数参 数:color颜色值*/void LcdClear(u16 color){ u32 i; LcdSetCursor(0,0); //设置光标位置 LcdWriteRAM_Prepare(); //开始写入GRAM for(i=0;i<320*480;i++)LCD_RAM=color; }

/*函数功能:显示一个指定大小的汉字参 数: x,y :汉字的坐标 font:取模数据 size:字体大小尺寸*/void LcdShowFont(u16 x,u16 y,u8 *dzk,u8 size){ u8 temp,t,t1; u16 x0=x; u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数 for(t=0;t<csize;t++) { temp=dzk[t]; for(t1=0;t1<8;t1++) { if(temp&0x80)LcdDrawPoint(x,y,0x0); else { LcdDrawPoint(x,y,0xffff); } temp<<=1; x++; if((x-x0)==size) { x=x0; y++; break; } } } }

/*函数功能:矩形颜色填充参 数:(sx,sy),(ex,ey):矩形对角坐标 color:要填充的颜色*/void LcdFill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color){ u16 i,j; u16 xlen=0; xlen=ex-sx+1; for(i=sy;i<=ey;i++) { LcdSetCursor(sx,i); //设置光标位置 LcdWriteRAM_Prepare(); //开始写入GRAM for(j=0;j<xlen;j++)LcdWriteData(color); } }

/*函数功能:画直线参 数:x1,y1:起点坐标 x2,y2:终点坐标 */void LcdDrawLine(u16 x1, u16 y1, u16 x2, u16 y2,u16 color){ u16 t; int xerr=0,yerr=0,delta_x,delta_y,distance; int incx,incy,uRow,uCol; delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1; uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if(delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if(delta_y==0)incy=0;//水平线 else{incy=-1;delta_y=-delta_y;} if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<=distance+1;t++ )//画线输出 { LcdDrawPoint(uRow,uCol,color);//画点 xerr+=delta_x ; yerr+=delta_y ; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } } }

/*函数功能:任意角度画直线 参 数: w :线段的长度 len:半径 c :颜色 x,y:坐标*/#include <math.h>void LcdDrawAngleLine(u32 x,u32 y,float du,u32 len,u32 w,u16 c){ int i; int x0,y0; float k=du*(3.1415926535/180); for(i=len-w;i<len;i++) { x0=cos(k)*i; y0=sin(k)*i; LcdDrawPoint(x+x0,y+y0,c); } }

/*函数功能:画矩形 参 数:(x1,y1),(x2,y2):矩形的对角坐标*/void LcdDrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color){ LcdDrawLine(x1,y1,x2,y1,color); LcdDrawLine(x1,y1,x1,y2,color); LcdDrawLine(x1,y2,x2,y2,color); LcdDrawLine(x2,y1,x2,y2,color);}

/*函数功能:在指定位置画一个指定大小的圆参 数: (x,y):中心点 r :半径*/void LcdDrawCircle(u16 x0,u16 y0,u8 r,u16 color){ int a,b; int di; a=0;b=r; di=3-(r<<1); //判断下个点位置的标志 while(a<=b) { LcdDrawPoint(x0+a,y0-b,color); //5 LcdDrawPoint(x0+b,y0-a,color); //0 LcdDrawPoint(x0+b,y0+a,color); //4 LcdDrawPoint(x0+a,y0+b,color); //6 LcdDrawPoint(x0-a,y0+b,color); //1 LcdDrawPoint(x0-b,y0+a,color); LcdDrawPoint(x0-a,y0-b,color); //2 LcdDrawPoint(x0-b,y0-a,color); //7 a++; if(di<0)di +=4*a+6; //Bresenham画圆算法 else { di+=10+4*(a-b); b--; } }}

/*函数功能:显示图片参 数:(图片起始横坐标,图片起始纵坐标,图片横像素,图片纵像素,要显示的图片首地址)*/void LcdShowPicture(u32 x,u32 y,u32 x1,u32 x2,const unsigned char * p){ u32 x0,y0; for(y0=0;y0<x2;y0++) { for(x0=0;x0<x1;x0++) { LcdDrawPoint(x+x0,y+y0,(*p<<8)+*(p+1)); //图片取模方式-->高位在前 //画点LCD的像素是16位的,所以需要将2个8位像素合成16位像素。 p+=2; } }}
复制代码

五、按键驱动代码示例

拼图的时候,通过 4 个按键控制上下左右方向的,按键的代码如下:


功能    :按键的初始化硬件连接:KEY1:PA0  --按下是高电平KEY2:PE2  --按下是低电平KEY3:PE3  --按下是低电平KEY4:PE4  --按下是低电平返回值:无*/void KeyInit(void){   /*1. 开时钟*/   RCC->APB2ENR|=1<<2; //PA   RCC->APB2ENR|=1<<6; //PE      /*2. 配置GPIO口模式*/   GPIOA->CRL&=0xFFFFFFF0;   GPIOA->CRL|=0x00000008; //上下拉输入模式      GPIOE->CRL&=0xFFF000FF;   GPIOE->CRL|=0x00088800; //上下拉输入模式     /*3. 上下拉控制*/   //GPIOA->ODR&=~(1<<0); //PA0下拉   GPIOE->ODR|=1<<2;   GPIOE->ODR|=1<<3;   GPIOE->ODR|=1<<4;}
/*功 能:获取按键值返回值: 1表示按键1按下 2表示按键2按下 3表示按键3按下 4表示按键4按下 0表示没有按键按下实现单次按下模式(上一次按下的按键没有松开,就不做检测)和连续按下的模式。
模式: mode=1; //表示单击 mode=0; //表示连续*/u8 GetKeyValue(u32 mode){ static int stat=0; //保存上一次按键的状态 if(mode==0)stat=0; if((KEY1||KEY2==0||KEY3==0||KEY4==0) && stat==0) { DelayMs(20); //延时消抖 stat=1; //表示上次有按键按下 if(KEY1)return 1; if(KEY2==0)return 2; if(KEY3==0)return 3; if(KEY4==0)return 4; } else { if(KEY1==0&&KEY2&&KEY3&&KEY4)stat=0; //判断所有的按键是否已经松开 } return 0;}
复制代码

六、拼图的逻辑代码

分隔图片: 这里是按照 320*240---2.8 寸计算的


//           0,0         60,0         120,0         180,0//           0,80        60,80        120, 80        180,80//           0,160       60,160,      120, 160,      180,160//           0,240,      60,240       120, 240       180,240//显示位置起始坐标。u32 record[16][2];
int pic[16][2]= {//第i张图片的屏幕所在位置。 {60,160},{180,80},{0,80}, {180,0},{180,160},{180,240}, {0,160},{120,160},{60,80},{120,0}, {120,240},{120,80},{0,0},{60,240},{60,0},{0,240}};
复制代码


循环里处理图片移动逻辑:


while(1)  {      //【1】产生随机图片ID号:0--15,   4号图片用作空白图片。 //ID号和图片首地址固定。图片所在的位置不固定。      picture_production(tu32,pic);    while(1)    {        key=GetKeyValue(1);       if(key==1)      //右移动        {if(record[4][0]>0)              //180,160          {            number=lookingfor_blankblock(record[4][0]-60,record[4][1],tu32);            show_picture_(record[4][0],record[4][1],tu32,number);//空白左边图覆盖空白            show_picture_(record[4][0]-60,record[4][1],tu32,4);  //出现新空白            k=record[number][0];            record[number][0]=record[4][0];            record[4][0]=k;                                                     }        }        if(key==3)    //左移动        {if(record[4][0]<180)              //180,160          {            number=lookingfor_blankblock(record[4][0]+60,record[4][1],tu32);            show_picture_(record[4][0],record[4][1],tu32,number);//空白左边图覆盖空白            show_picture_(record[4][0]+60,record[4][1],tu32,4);  //出现新空白            k=record[number][0];            record[number][0]=record[4][0];            record[4][0]=k;                                                        //新空白横坐标          }        }        if(key==2)    //下移动        {if(record[4][1]>0)             {             number=lookingfor_blankblock(record[4][0],record[4][1]-80,tu32);            show_picture_(record[4][0],record[4][1],tu32,number);//空白左边图覆盖空白            show_picture_(record[4][0],record[4][1]-80,tu32,4);  //出现新空白            k=record[number][1];            record[number][1]=record[4][1];            record[4][1]=k;           }        }                if(key==4)    //上移动        {          if(record[4][1]<240)            {            number=lookingfor_blankblock(record[4][0],record[4][1]+80,tu32);            show_picture_(record[4][0],record[4][1],tu32,number);//空白左边图覆盖空白            show_picture_(record[4][0],record[4][1]+80,tu32,4);  //出现新空白            k=record[number][1];            record[number][1]=record[4][1];            record[4][1]=k;            }        }      }  }
复制代码


发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
基于STM32设计的拼图小游戏_8月月更_DS小龙哥_InfoQ写作社区