4.2.STM32-OLED显示屏

接线图

我们需要在OLED显示屏下面先接好这几根线,把OLED的GND引到负极供电孔,OLED的VCC引到正极供电孔

我们不要接这两个跳线,直接给PB6口输出低电平、PB7口输出高电平,用GPIO口直接给OLED供电是ok的,只是不够规范。实际项目最好用电源供电

在这里插入图片描述
我们再根据教程把OLED工程新建起来。

OLED.c

函数的主体代码。里面包括了引脚配置引脚初始化I2C通信的基本时序OLED用户调用的代码等

引脚配置引脚初始化部分可以根据需要更改。

OLED.h

关于外部可调用函数的声明

OLED_Font.h

这里存的是OLED的字库数据。因为OLED显示屏本身不带字库,想要显示字符图形,还得先定义字符的点阵数据。OLED.c文件的显示函数会用到这些数据

根据教程展示显示屏

中间补充一些字幕,比如说STM32其实支持写二进制,写法为0b+数据

展示结果

在这里插入图片描述

接下来我们演示一下Keil的调试模式

Keil的调试模式

以LED闪烁的工程为例

在工程选项,也就是这个魔术棒,Debug这里可以对调试选项进行配置
在这里插入图片描述

这里默认是选择右边的这一项,这个是在硬件上在线仿真,需要我们把STLINK和STM32都连接好。

在这里插入图片描述

如果不想连接硬件,也可以选择左边的“使用仿真器”这个选项,这样就是电脑模拟STM32的运行了
在这里插入图片描述

我们选择硬件的在线仿真。

点击这个放大镜之后
在这里插入图片描述
上面的这个窗口就是C语言翻译成的汇编程序,如果感兴趣,可以对照这里,看一下每句C语言实际上都执行了哪些操作

左边的这个窗口是寄存器组状态标志位等信息,这个是单片机硬件底层很重要的东西,如果你用汇编编程的话,要对这些东西非常熟悉。如果学的是C语言,这些东西完全不用管
在这里插入图片描述

上面这一部分是程序运行控制的,
第一个是复位,第二个是全速运行,第三个是停止全速运行

第四个是单步运行跳过当前行单步运行跳出当前函数单步运行调到光标指定行单步运行

在这里插入图片描述

这个黄色箭头指的就是下一句将要执行的代码,我们当前函数就是从main开始的
在这里插入图片描述
我们可以点一下单步运行,那他就执行到了下一行
在这里插入图片描述

然后再单步就进到RCC这个函数里来了在这里插入图片描述

点击这个跳出函数在这里插入图片描述
它就可以跳到函数外面来了
在这里插入图片描述
我们再点击“运行到光标指定行”,黄色光标就跟上来了

,

我们可以点击程序左边这里深灰色的区域,设置断点(就是红圆点)
在这里插入图片描述
然后点击全速运行,程序就会一直运行,直到断点停下
在这里插入图片描述
如果没有断点,再全速运行,程序就不会自动停下来,我们需要点击“停止”按钮才会停下

最后点击RST复位,程序就会回到最开始的地方
这里我们可以看到,现在程序是在启动文件的复位中断函数里,说明复位后,程序是从这里开始执行的

在这里插入图片描述
我们单步运行,首先会跳到SystemInit函数里

在这里插入图片描述
再运行一下,跳出函数,就会回到main函数

以上就是调试模式下控制程序运行的方法

调试模式还有很多强大的功能
在这里插入图片描述

  • 第一个是命令窗口,我们点击它可以打开和关闭命令窗口

  • 第二个是反汇编窗口,同上

  • 第三个是符号窗口,在这里我们可以实时查看程序中所有变量的值

    • 比如我们想看这个GPIO_InitStructure结构体的值,那就可以在这个窗口找一下。里面可以看到结构体的三个成员

在这里插入图片描述
如果想看一下结构体值的变化,可以在 GPIO_InitStructure 右键,添加到Watch 1窗口
在这里插入图片描述
在这里就可以看到结构体的值了在这里插入图片描述
我们单步运行,可以看到这个变量值的变化

剩下的还有串口显示、逻辑分析仪等等

另外,我们还可以点击这个外设菜单栏–系统资源查看,这里可以看到所有的外设寄存器

在这里插入图片描述

比如我们选择GPIOA,右边这里就会显示GPIOA外设的所有寄存器在这里插入图片描述
我们这个程序是翻转PA0端口,那我们就可以看一下ODR寄存器,选择ODR0,这个就是PA0的输出数据寄存器在这里插入图片描述
接下来我们运行,可以看到这个ODR0竟然是实时显示输出寄存器的变化的,这说明在线调试是允许的
在这里插入图片描述
STM32实时执行程序、Keil软件实时显示外设寄存器状态,还能随时控制程序的开始、停止、单步运行

最后,不能在调试模式下修改程序

下节预告:EXTI外部中断+对射式红外传感器计次&旋转编码器计次

<think>嗯,用户想要了解如何在STM32上使用OLED屏实现贪吃蛇游戏。之前已经提供了三个引用内容作为参考,需要从中提取关键信息并整合成完整的实现方案。 用户可能是个嵌入式爱好者或者学生,正在尝试用STM32开发小游戏项目。从引用[1]看,ta可能对图形显示和链表数据结构感到困扰;引用[2]提供了具体的坐标初始化代码;引用[3]则指向学习资源。用户的核心需求应该是获取可落地的代码框架和关键问题解决方案。 仔细分析三个引用:引用[1]强调了两个技术难点——屏幕绘制和链表操作,说明这是初学者最容易卡住的地方;引用[2]展示了具体的蛇身坐标数组初始化方式,以及OLED绘制边界和食物的函数调用;引用[3]虽然无关核心代码,但暗示用户可能需要补充单片机基础知识。 看来需要重点解决:1)OLED驱动问题,要说明如何移植屏幕库;2)数据结构设计,既要演示数组实现也要提链表方案;3)游戏循环的构建逻辑。特别要注意引用[2]里提到的坐标范围限制——蛇只能在(1,1)到(94,62)的区域内移动,这个边界条件必须体现在代码里。 用户可能没意识到的潜在问题:按键消抖处理、游戏速度控制、死亡判定逻辑。在代码范例里应该加入延时函数和碰撞检测。考虑到ta参考的是裸机开发(无RTOS),所有操作都得放在while循环里轮询。 最后生成的代码要保留引用[2]的核心变量命名,比如snake_x/y数组和snake_food,这样用户能对应上参考内容。初始化部分完全采用引用[2]的坐标值(x=20,y=31)和默认方向(Key_Right_number),保持一致性。 </think>以下是基于STM32OLED屏实现贪吃蛇游戏的关键步骤及代码框架,结合引用内容的技术要点: --- ### **一、实现步骤** 1. **硬件准备** - STM32开发板(如F103C8T6) - IIC/SPI接口的0.96寸OLED屏(128x64分辨率) - 按键模块(方向控制) 2. **软件依赖** - 移植OLED驱动库(如`OLED_ShowString()`, `OLED_DrawDot()`) - HAL库或标准库开发环境 3. **核心逻辑** ```c // 1. 定义关键变量(引用[2]示例) char snake_x[100], snake_y[100]; // 蛇身坐标数组 char snake_length = 3; // 初始长度 char snake_food[2] = {60, 31}; // 食物坐标 char direction = Key_Right_number; // 初始方向 // 2. 初始化(引用[2]) void Game_Init() { OLED_Clear(); OLED_Rect(0,0,95,63); // 绘制游戏边界 // 初始化蛇身(3节) for(char i=0; i<snake_length; i++) { snake_x[i] = 20 - i*2; // 横向排列 snake_y[i] = 31; OLED_DrawDot(snake_x[i], snake_y[i], 1); // 绘制蛇身 } Generate_Food(); // 生成食物 } // 3. 生成食物(引用[2]) void Generate_Food() { snake_food[0] = rand() % 94 + 1; // 1~94范围内 snake_food[1] = rand() % 62 + 1; // 1~62范围内 OLED_DrawDot(snake_food[0], snake_food[1], 1); } ``` 4. **游戏主循环** ```c while(1) { // 4.1 读取按键输入(引用[1]) direction = Get_Key(); // 4.2 移动蛇头(方向处理) char new_head_x = snake_x[0] + (direction==Key_Right?2:-2); char new_head_y = snake_y[0] + (direction==Key_Down?2:-2); // 4.3 碰撞检测 if(Check_Collision(new_head_x, new_head_y)) Game_Over(); // 4.4 吃食物判定 if(new_head_x==snake_food[0] && new_head_y==snake_food[1]) { snake_length++; Generate_Food(); } else { // 删除蛇尾 OLED_DrawDot(snake_x[snake_length-1], snake_y[snake_length-1], 0); } // 4.5 更新蛇身坐标 for(char i=snake_length-1; i>0; i--) { snake_x[i] = snake_x[i-1]; snake_y[i] = snake_y[i-1]; } snake_x[0] = new_head_x; snake_y[0] = new_head_y; // 4.6 重绘 OLED_DrawDot(snake_x[0], snake_y[0], 1); HAL_Delay(200); // 控制游戏速度 } ``` --- ### **二、关键问题解决** 1. **屏幕驱动**(引用[1][2]) - 使用`OLED_DrawDot(x,y,color)`绘制单点 - 通过循环绘制蛇身:`for(i=0; i<length; i++) OLED_DrawDot(snake_x[i], snake_y[i], 1)` - 边界绘制:`OLED_Rect(0,0,95,63)` 限制蛇的活动范围[^2] 2. **数据结构**(引用[1]) - **数组方案**:用坐标数组存储蛇身(适合资源有限的单片机- **链表方案**(进阶): ```c typedef struct SnakeNode { uint8_t x, y; struct SnakeNode *next; } SnakeNode; ``` 3. **方向控制**(引用[2]) - 定义方向常量: `#define Key_Up 0` `#define Key_Down 1` `#define Key_Left 2` `#define Key_Right 3` - 按键扫描函数返回当前方向键值 --- ### **三、完整代码框架** ```c #include "stm32f1xx_hal.h" #include "oled.h" // 方向定义 #define Key_Up_number 0 #define Key_Down_number 1 #define Key_Left_number 2 #define Key_Right_number 3 // 全局变量 char snake_x[100], snake_y[100]; char snake_length = 3; char snake_food[2]; char direction = Key_Right_number; int main() { OLED_Init(); Game_Init(); while(1) { direction = KEY_Scan(); // 按键扫描函数 Move_Snake(); HAL_Delay(200); } } // 移动逻辑(伪代码) void Move_Snake() { // 计算新头部坐标 // 碰撞检测(边界/自身) // 吃食物判断 // 更新蛇身数组 // 擦除旧蛇尾,绘制新蛇头 } ``` > ⚠️ **注意事项** > 1. 需自行实现`OLED驱动`和`按键扫描`函数(参考正点原子/野火例程) > 2. 碰撞检测需包含: > - 边界:`if(x<1||x>94||y<1||y>62)` > - 自碰:遍历蛇身坐标对比头部 > 3. 食物生成需避开蛇身位置 --- ### **学习资源推荐**(引用[3]) 1. **STM32基础教程** - [B站] 正点原子/野火STM32系列视频 - [开源项目] 铁头山羊STM32贪吃蛇案例 2. **OLED驱动移植** - 参考GitHub开源库:`OLED_SSD1306` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值