文章目录
一.概要
做一个基于STM32的电子游戏机,其意义远不止是"焊一块电路板让它跑起来"。在技术学习、产品思维和个人成长等多个维度上,它都是一个具有很高价值的综合性实践项目。
本文就做一个STM32电子游戏机模型,采用STM32F103C8T6单片机+1.8寸液晶+6个独立按键。按键实现动作输入,液晶实现游戏内容显示,目前实现了贪吃蛇,俄罗斯方块,王牌飞行员飞机游戏。

二.实验模型原理
1.硬件连接原理框图

模型主要分为三部分:主芯片单元,按键输入单元,液晶显示单元。

图中主控芯片为STM32F103C8T6单片机,按键输入单元为6个按键,液晶显示单元为1.8寸TFT液晶显示。
信号线连接:6个按键接到单片机的PB6,PB7,PB8,PB9,PB12,PB13的引脚。液晶显示模块接单片机的PA5,PA7引脚,采用SPI通讯方式。
2.各个传感器模块控制原理
按键输入原理
单片机的PB6,PB7,PB8,PB9,PB12,PB13引脚都配置成GPIO输入上拉,按键按下,对应的引脚就会接地,能读到低电平,通过外部中断下降沿触发,从而判断对应的按键是否被按下。
1.8寸TFT原理
TFT-LCD,全称Thin Film Transistor Liquid Crystal Display,即薄膜晶体管液晶显示器,是多数液晶显示器的一种,使用薄膜晶体管技术改善影象品质。它在液晶显示屏的每一个像素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD 也被叫做真彩液晶显示器。


1.8寸TFT LCD彩屏是128x160像素的分辨率,我们可以理解为:水平方向分布了128个像素点,垂直方向分布了160个像素点。我们在画点的时候坐标Y的取值为0-159,坐标X的取值为0-127。
下图红色箭头的方向就是坐标递增的方向。

PCtoLCD2002 是专业的取字模软件,采用C语言和汇编语言两种格式,支持逐行、逐列、行列、列行四种取模方式,可以选择字体、大小、文字的长宽,自动生成你想要的字符,能生成字符字模,中文字模。
软件只需要几步就能轻松生成字符

三.电子游戏机程序
单片机板子与按键连接:
板子B9-----按键UP
板子B8-----按键DOWN
板子B6-----按键LEFT
板子B7-----按键RIGHT
板子B12----按键EXIT
板子B13----按键START
单片机板子与TFT液晶连接:
板子3.3V------VCC
板子G----------GND
板子A5---------SCL
板子A7---------SDA
板子A2---------RES
板子A1---------DC
板子A4---------CS
板子A0---------BL
打开STM32CubeMX软件,新建工程

Part Number处输入STM32F103C8,再双击就创建新的工程

配置下载口引脚

配置外部晶振引脚

配置系统主频

PB6,PB7,PB8,PB9,PB12,PB13配成中断输入,而且是上拉,因为要读取按键的低电平信号。

外部中断使能

PA0,PA1,PA2,PA4配置成输出,用于驱动液晶的RES,CS,DC等引脚。

配置SPI1使能,PA5为SPI的SCK引脚,PA7为SPI的MOSI引脚。

配置工程文件名,保存路径,KEIL5工程输出方式

生成工程

用Keil5打开工程

添加代码
添加显示LCD显示驱动,添加俄罗斯方块文件。

main函数中调用显示与俄罗斯方块文件。

按键信息与游戏界面融合。

主要程序:
c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
LCD_Init();//LCD初始化
LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
Game_Init();// 游戏初始化
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Game_Run();//游戏运行
}
/* USER CODE END 3 */
}
// 游戏初始化
void Game_Init(void)
{
// 初始化随机种子
srand(HAL_GetTick());
// 初始化游戏状态
game.state = GAME_START_SCREEN;
game.score = 0;
game.high_score = 0; // 实际项目中可以从EEPROM读取
game.level = 1;
game.lines_cleared = 0;
game.fall_speed = 100; // 初始下落速度100ms
game.last_fall_time = 0;
game.last_move_time = 0;
game.game_over_flag = 0;
game.pause_flag = 0;
game.FirstStartFlag=0;
// 清空游戏板
for(int y = 0; y < BOARD_HEIGHT; y++) {
for(int x = 0; x < BOARD_WIDTH; x++) {
game.board[y][x] = 0;
}
}
// 生成第一个和下一个方块
Game_GenerateNextPiece();
Game_SpawnPiece();
Game_GenerateNextPiece();
}
// 游戏主循环
void Game_Run(void)
{
static uint32_t last_update_time = 0;
uint32_t current_time = HAL_GetTick();
switch(game.state) {
case GAME_START_SCREEN:
Game_DrawStartScreen();
Game_ProcessInput();
break;
case GAME_PLAYING:
// 每500ms更新一次游戏逻辑
if(current_time - last_update_time >= 500) {
Game_ProcessInput();
if(game.fall_speed==0)
{
Game_Update();
Game_Update();
}else
{
Game_Update();
}
Game_Draw();
last_update_time = current_time;
}
break;
case GAME_PAUSED:
Game_DrawPauseScreen();
Game_ProcessInput();
break;
case GAME_OVER:
Game_DrawGameOverScreen();
Game_ProcessInput();
break;
default:
break;
}
}
// 绘制游戏
void Game_Draw(void)
{
Game_DrawBoard();//绘制边框
Game_DrawCurrentPiece();//绘制当前方块
Game_DrawNextPiece();//绘制下一个方块
Game_DrawUI();//绘制分数
}
四.实验效果视频
STM32单片机游戏机
五.小结
在升学或求职时,这个项目的价值往往超乎想象:
面试中的谈资:相比那些千篇一律的跟随式项目,一个亲手打造的、完整的电子游戏机,能让你在面试官面前清晰地讲述"遇到了什么问题、怎么解决的、最后效果如何"。这种项目闭环能力是很多企业看重的。
综合解决问题的能力:调试硬件的玄学问题(比如按键抖动、屏幕花屏)、解决编译器的报错、优化内存占用......这些过程中锻炼出的耐心和排查问题的思路,是光靠看书刷题无法获得的。