FPB-RX14T 开发板测评:开箱、环境搭建与基础外设验证

本次由衷的感谢贸泽电子提供的开发板体验官的活动,让我有机会有这篇文章!
贸泽电子的个人空间-哔哩哔哩】 https://b23.tv/AIWapeX
在这里插入图片描述
也欢迎大家关注贸泽电子的开发板体验活动哦可以拿到各种性能优异的开发板期待大佬们的开源项目!

概述

在线文档目录:https://github.com/318973613/fpb-rx14t-examples/tree/main/docs (里面有本次配套的项目源码和文档)
本文是对瑞萨 FPB-RX14T 快速原型开发板的完整测评记录。测评从开箱检查开始,依次完成 e2 studio 开发环境搭建、工程创建与下载调试配置,并通过多组递进实验验证开发板的基础能力:GPIO 输出(LED 闪烁)、定时器中断(呼吸灯)、软件 IIC 外设通信、Smart Configurator 图形化配置的硬件 I2C OLED 驱动,以及基于 OLED 和按键的开源小游戏移植。

通过本文,读者可以了解:

  • FPB-RX14T 的硬件组成与板载资源分布。
  • e2 studio + CC-RX 工具链的安装与工程创建流程。
  • Smart Configurator 图形化配置 GPIO、CMT 定时器和 I2C Master Mode 的完整步骤。
  • 板载 E2 Lite 调试器的连接、下载与调试验证方法。
  • 软件 IIC 与硬件 I2C 驱动 SSD1306 OLED 的接线、配置与代码实现。
  • 如何把一个 STM32 OLED Dino 小游戏移植到 RX14T,并用 P10 按键完成交互。

第一章 开箱与开发板认识

1.1 开发板实物

开箱后首先对开发板正反面进行外观检查,确认 USB Type-C 接口、调试器区域、MCU 芯片、排针、用户 LED 和按键等关键部件完整无损。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述
在这里插入图片描述

1.2 FPB-RX14T 简介

FPB-RX14T 是瑞萨电子面向 RX14T MCU 推出的快速原型开发板。其核心优势在于板载 E2 Lite 调试器——仅需一根 USB Type-C 数据线即可同时完成供电、程序下载和在线调试,无需额外购置调试工具。

1.3 核心 MCU 参数

参数 规格
型号 R5F514T5AMFM(RX14T 系列,64 引脚 LFQFP)
内核 RXv2,32 位,最高主频 48 MHz
代码 Flash 128 KB
RAM 12 KB
Data Flash 4 KB

RX14T 定位于电机控制与逆变器场景,片上集成 TFU 三角函数加速单元、双通道 12 位高速 ADC、可编程增益放大器(PGA)以及 MTU/GPT 定时器组等专用外设。本测评从最基础的 GPIO 输出开始,逐步验证这些外设的实际表现。

1.4 板上常用资源

板上资源 MCU 引脚 工程宏 说明
LED1 P32 LED1 用户 LED,本测评主要验证目标
LED2 P92 LED2 辅助 LED,可用于状态指示
S1 用户按键 P10 S1 可配置为普通输入或 IRQ0 外部中断
S2 复位按键 RES# - 硬件复位 MCU

1.5 官方资源

  • 英文产品页:https://www.renesas.com/en/design-resources/boards-kits/fpb-rx14t
  • 中文产品页:https://www.renesas.cn/zh/design-resources/boards-kits/fpb-rx14t
  • e2 studio 下载页:https://www.renesas.cn/zh/software-tool/e2-studio

第二章 e2 studio 环境搭建

2.1 下载 e2 studio

从瑞萨官方网站下载适配 RX 系列的 e2 studio 安装包:

https://www.renesas.cn/zh/software-tool/e2studio-information-rx-family#overview

下载前需登录 My Renesas 账号;若尚未注册,需先在官网完成账号创建。

在这里插入图片描述

2.2 安装 e2 studio

运行安装程序后,选择 Custom Install 模式,以便手动确认 RX 相关组件是否安装完整。

在这里插入图片描述

2.3 勾选 RX 相关组件

在组件选择页面,需确认以下内容已勾选:

  • RX Family 支持。
  • Renesas C/C++ Compiler Package for RX(即 CC-RX)。
  • RX Smart Configurator。
  • RX Debug Support。
  • E2 Lite 或 E2 Emulator 调试支持。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:若此处漏选 RX、CC-RX 或 Smart Configurator,后续可能出现无法创建 RX14T 工程、找不到芯片型号或无法生成代码等问题。

2.4 安装完成后检查工具链

安装完成后启动 e2 studio。若创建工程时未显示 CC-RX 工具链,需通过 Help -> Manage Toolchains 安装或启用 Renesas CC-RX Compiler。

注意:若 Toolchain Version 为空或无可选版本,说明 CC-RX 编译器未正确安装,需进入 Manage Toolchains 手动添加。


第三章 创建 RX14T 工程

3.1 选择工程类型

启动 e2 studio 后,新建工程并选择 Renesas CC-RX C/C++ Executable Project

在这里插入图片描述

选择 CC-RX 的理由:它是瑞萨官方 RX 编译器,对 RX14T 内核和 Smart Configurator 的支持最完整、最稳定。Executable Project 会生成可直接下载到 MCU 的程序文件(如 .x.mot)。GCC for RX 也可使用,但目前对 Smart Configurator 的支持略逊于 CC-RX,因此本测评统一采用 CC-RX 工具链。

3.2 填写工程名称

在工程名称页面填写项目名,本测评使用的工程名为 test

在这里插入图片描述

3.3 配置芯片与开发板

在工程配置页面,确认芯片和开发板信息:

  • Device:R5F514T5AxFM
  • Board:FPB-RX14T
  • Toolchain:CC-RX
  • Build Configuration:HardwareDebug

在这里插入图片描述

注意:若工程页面找不到 FPB-RX14T 或 R5F514T5AxFM,说明 RX14T 板卡或芯片支持包未安装,需返回第二章补装相关组件。

3.4 完成创建

确认配置无误后,点击 Finish 完成工程创建。

在这里插入图片描述


第四章 下载与调试配置

4.1 打开调试配置

工程创建完成后,需配置程序下载方式。进入:

Run -> Debug Configurations...

选择当前工程的 HardwareDebug 配置。

在这里插入图片描述

在这里插入图片描述

4.2 确认 E2 Lite 与目标芯片

在调试配置页面中,需确认以下参数:

  • Debug Hardware:E2 Lite
  • Target Device:R5F514T5
  • Connection:FINE
  • Program:HardwareDebug/test.x
  • Load image:启用

注意:若 Debug Hardware 显示不是 E2 Lite,需手动切换为 E2 Lite;若目标芯片不是 R5F514T5,需改为 RX14T 对应型号。

4.3 硬件连接

使用 USB Type-C 数据线连接开发板与电脑。根据官方文档,J7 跳线需调整至右侧位置。

在这里插入图片描述

注意:若电脑无法识别开发板,首先确认 USB 线是否支持数据传输(部分线缆仅支持充电),再检查 J7 跳线是否到位。

4.4 验证电脑识别开发板

连接成功后,Windows 设备管理器中应出现:

Renesas USB Development Tools -> Renesas E2 Lite

同时,板上 LED4 亮起表示调试器供电和 USB 连接状态正常。

在这里插入图片描述

确认识别正常后,点击 e2 studio 顶部的 Debug 按钮即可开始程序下载。

在这里插入图片描述


第五章 点亮第一颗 LED:LED1

5.1 实验目标

本章完成最基础的 GPIO 输出实验:让 LED1 以 500 ms 间隔闪烁。LED1 对应 MCU 的 P32 引脚。相比常亮,闪烁方式更容易判断程序是否已成功下载并运行。

5.2 当前工程中的 LED1 引脚

当前工程的 workspace/test/src/smc_gen/r_pincfg/Pin.h 中已包含 LED1 宏定义:

#define LED1        3,2

规范做法并非在业务代码中直接操作 PORT3.PDRPORT3.PODR 等寄存器,而是先在 Smart Configurator 中将 P32 配置为 GPIO 输出,再在应用代码中使用生成的 PIN_WRITE(LED1) 宏控制 LED。

需要注意:Pin.h 中出现 LED1 宏仅表示符号名可用,不代表端口方向初始化代码已成功生成。

5.3 使用 Smart Configurator 配置 LED1

打开 test.scfg,进入 Smart Configurator 的 Pins/Ports 配置页面,找到 LED1 对应的 P32 引脚,按以下方式配置:

  • Pin:P32
  • Function:GPIO
  • Direction:Output
  • Initial Output:High 或 Low 均可,本实验会在代码中翻转 LED 状态
  • Symbolic Name:LED1

配置完成后,点击 Smart Configurator 的生成代码按钮,e2 studio 会重新生成端口初始化代码。生成后,工程中会出现或更新 Config_PORT 相关文件,系统初始化流程将调用 R_Config_PORT_Create() 完成 P32 输出方向配置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.4 生成成功判定

以下 4 项同时满足,才表示 LED1 的端口配置已正确生成:

  1. 工程中出现 workspace/test/src/smc_gen/Config_PORT/Config_PORT.c
  2. workspace/test/src/smc_gen/general/r_cg_hardware_setup.c 中调用了 R_Config_PORT_Create()
  3. workspace/test/src/smc_gen/general/r_smc_entry.h 中包含了 Config_PORT.h
  4. Config_PORT.c 中可见 PORT3.PDR 的 P32 输出配置(Pm2_MODE_OUTPUT)。

补充说明:workspace/test/src/smc_gen/r_pincfg/Pin.c 中即使仍显示 No pins have been configured in the Pins tab.,在当前 Config_PORT 生成链路下不影响 LED1 点亮。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.5 编写应用代码

打开 workspace/test/src/test.c,将 main() 修改为:

void main(void)
{
    PIN_WRITE(LED1) = 1U;

    while (1)
    {
        PIN_WRITE(LED1) = ~PIN_READ(LED1);
        R_BSP_SoftwareDelay(500U, BSP_DELAY_MILLISECS);
    }
}

各行代码作用:

  • PIN_WRITE(LED1) = 1U:先将 P32 输出置为高电平,点亮 LED1。
  • PIN_WRITE(LED1) = ~PIN_READ(LED1):循环读取当前输出状态并取反,实现 LED1 交替闪烁。
  • R_BSP_SoftwareDelay(500U, BSP_DELAY_MILLISECS):每次翻转后延时 500 ms。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.6 编译工程

右键 test 工程,选择 Build Project。编译成功后,Console 中会显示 Build complete,并生成:

  • HardwareDebug/test.x
  • HardwareDebug/test.mot

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.7 下载并运行

点击 Debug 按钮进入调试模式。程序下载完成后,e2 studio 通常会停在 main() 入口处。

此时需点击 Resume 按钮(或按 F8),程序才会继续执行。运行后,LED1 应以约 500 ms 的间隔稳定闪烁。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


第六章 定时器实验:LED1 呼吸灯

前面的 LED1 点灯实验已验证下载、调试和 P32 GPIO 输出均正常。本章在此基础上前进一步,将”何时改变输出”交给硬件定时器。这种架构更接近 RX14T 在电机控制场景中的实际使用方式:主程序负责初始化和业务逻辑,定时器负责按固定节拍产生周期事件。

本章的技术架构如下:

LED1 呼吸灯

开发板层

FPB-RX14T

板载 LED1

LED1 接在 P32

E2 Lite 下载调试

图形化配置层

Smart Configurator

Ports 生成 Config_PORT

P32 配成 GPIO Output

CMT driver 生成 r_cmt_rx

程序层

main 初始化工程

CMT 创建周期回调

callback 定时执行

PIN_WRITE 控制 LED1

现象层

快速亮灭形成 PWM

占空比逐步变化

肉眼看到呼吸效果

本实验并非单纯实现”灯的亮暗变化”,而是用 LED1 模拟电机控制中最典型的节拍控制问题。后续接入电机后,LED1 的亮灭逻辑可直接对应为 PWM 占空比更新、电机转速调节或控制周期刷新。

6.1 为什么选择 CMT 做定时器实验

RX14T 面向电机控制、逆变器、小型运动控制等场景设计,片上定时器资源围绕”按精确时间驱动外部对象”展开。电机控制中的常见需求——固定频率 ADC 采样、PWM 占空比更新、保护信号检测、异常快速关断——都依赖定时器支持。

本次测评未连接电机,因此用板载 LED1 替代负载。LED 亮灭虽简单,但能直观体现定时器的核心价值:程序无需在 while 循环中死等延时,而是由硬件定时器按固定节拍触发回调,回调函数中更新输出状态即可。

FPB-RX14T 定时器实验

开发板定位

RX14T 面向电机控制

定时器资源丰富

板载 LED 可替代电机观察输出

定时器用途

周期中断

PWM 占空比控制

ADC 采样触发

电机保护配合

本实验选择

CMT 提供固定节拍

GPIO 控制 LED1

软件 PWM 模拟亮度变化

后续扩展

GPT/MTU 硬件 PWM

按键调速

ADC 调亮度

电机驱动波形

RX14T 片上定时器资源概览:

定时器/外设 典型用途 本实验是否使用
CMT 固定周期中断、系统节拍、软件定时 使用
TMR 简单计数、短周期定时、基础事件 不使用
MTU 电机控制、复杂 PWM、输入捕获/输出比较 不使用
GPT 通用 PWM、周期波形、占空比输出 不使用
POE PWM 输出保护、异常关断 不使用

本章选择 CMT 的原因:它结构最简单,最适合讲解定时器中断的基本概念。待 CMT 的节拍、回调、软件 PWM 逻辑验证通过后,再迁移到 MTU/GPT 做硬件 PWM 会更加顺畅。

从硬件到软件的对应关系:

层级 本实验内容 作用
开发板硬件 LED1、P32、E2 Lite 观察输出、下载程序
Smart Configurator Config_PORTr_cmt_rx 图形化生成端口初始化和 CMT 驱动
生成代码 R_Config_PORT_Create()r_cmt_rx_if.h 提供初始化函数和 CMT API 声明
用户代码 R_CMT_CreatePeriodicAssignChannelPriority()breathing_timer_callback()PIN_WRITE(LED1) 创建定时器节拍,在回调中控制 LED

需要区分两个概念:Config_PORT 管”引脚能不能输出”,CMT 管”多久执行一次回调”。LED1 的亮灭最终由 PIN_WRITE(LED1) 写出的电平决定。

6.2 呼吸灯原理

普通闪灯只有亮、灭两个状态。呼吸灯的亮度看起来连续变化,实质是快速开关 LED,并持续改变”亮的时间占整个周期的比例”——即占空比。

以 100 份 PWM 周期为例:

  • 亮 10 份、灭 90 份 → 肉眼感知较暗。
  • 亮 50 份、灭 50 份 → 中等亮度。
  • 亮 90 份、灭 10 份 → 较亮。

本实验中,CMT 每 100 us 触发一次回调。代码以 100 次回调构成一个软件 PWM 周期(约 10 ms),每隔 200 次回调(约 20 ms)调整一次亮度等级。亮度从 0 递增到 100,再从 100 递减到 0,循环往复形成呼吸效果。

CMT 每 100 us 触发一次中断

进入 breathing_timer_callback

软件 PWM 计数 g_pwm_count 加 1

g_pwm_count < g_brightness?

LED1 输出高电平

LED1 输出低电平

累计呼吸节拍

达到 20 ms?

调整 g_brightness

到达最亮或最暗?

改变增减方向

需注意:CMT 本身不直接驱动 LED 引脚,它只负责定时触发 CPU 中断。真正改变 P32 电平的是 PIN_WRITE(LED1)。因此 Smart Configurator 中需要同时配置两项:

  • Config_PORT:将 P32 配置为 GPIO 输出。
  • r_cmt_rx:提供固定周期的 CMT 定时器回调。

6.3 本实验用到的 CMT 函数

本实验的实现思路:

  • CMT 负责提供稳定的周期节拍。
  • P32/LED1 仍作为普通 GPIO 输出。
  • 呼吸效果通过软件 PWM 实现,不占用硬件 PWM 输出引脚。

关键函数调用:

R_CMT_CreatePeriodicAssignChannelPriority(CMT_FREQUENCY_HZ,
                                          breathing_timer_callback,
                                          CMT_CHANNEL,
                                          CMT_PRIORITY_5);

四个参数说明:

参数 本实验取值 作用
frequency_hz 10000U 回调频率,每秒 10000 次(100 us 一次)
callback breathing_timer_callback 每次 CMT 中断时执行的回调函数
channel 0U 使用 CMT0 通道
priority CMT_PRIORITY_5 中断优先级设为 5

函数创建成功后,CMT 自动开始周期计数并执行回调。主循环 while (1) 无需再用软件延时控制 LED,输出节奏完全交给定时器回调处理。

各函数的调用关系:

main

R_Config_PORT_Create

P32 变成 GPIO 输出

R_CMT_CreatePeriodicAssignChannelPriority

CMT0 周期计数

breathing_timer_callback

计算软件 PWM

PIN_WRITE LED1

LED1 明暗变化

  • R_Config_PORT_Create():由 Smart Configurator 生成,系统初始化时调用,配置 P32 的方向和输出初值。
  • R_CMT_CreatePeriodicAssignChannelPriority():FIT CMT 驱动提供的 API,创建固定频率的周期回调。
  • breathing_timer_callback():用户编写的回调函数,每个 CMT 周期执行一次。
  • PIN_WRITE(LED1):实际写 LED1 引脚电平的宏。原理图中 LED1 为高电平点亮,因此输出高电平时亮,低电平时灭。
  • R_BSP_SoftwareDelay():仅用于 CMT 创建失败时的错误提示分支——LED1 以 100 ms 快闪表示异常;正常呼吸灯不依赖此函数。

规范做法是:先在 Smart Configurator 中配置 PORTCMT driver 并生成代码,再在用户代码中调用 CMT API。这样既保留了图形化配置的完整性,也让代码聚焦于”定时器回调中的业务逻辑”。

6.4 新建 timer_breathing_led 工程

新建独立工程 timer_breathing_led,避免影响已验证通过的 test 点灯工程。工程配置不变:FPB-RX14T、R5F514T5AxFM、CC-RX 工具链。

6.5 添加 PORT 组件

打开 timer_breathing_led.scfg,进入 Smart Configurator 的 Components 页面,点击添加组件按钮,选择 Ports

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

组件配置名保持默认 Config_PORT

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加 Config_PORT 的原因:Pin.h 中存在 LED1 宏仅表示符号名可用,P32 的输出方向仍需在系统初始化阶段通过 R_Config_PORT_Create() 完成配置。

6.6 配置 LED1 对应的 P32 引脚

切换到 Pins 页面,找到 P32(位于 MCU Package 图上侧,引脚编号 41)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 Pin Function 表中勾选 P32,将其作为 LED1 使用。此处 P32 仅需 GPIO 输出功能,无需切换到硬件定时器波形输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本实验重点在于”通过定时器中断观察周期控制效果”,因此未使用 MTU/GPT 硬件 PWM 输出。CMT 产生固定节拍,软件在回调中控制 LED1 亮灭比例,思路更直观。

6.7 添加 CMT 定时器驱动

返回 Components 页面,添加 CMT driver(短名 r_cmt_rx)。这是 FIT 驱动组件,不会生成 Code Generator 风格的 Config_CMT0_Create() 初始化函数,而是通过 R_CMT_CreatePeriodicAssignChannelPriority() 等 API 在代码中动态创建周期定时器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本次配置参数:

  • CMT interrupts priority level5
  • Include software support for nested interrupt CMT channel 0Not
  • 其他通道的 nested interrupt:Not

点击 Generate Code,生成成功后工程中应出现:

  • src/smc_gen/r_cmt_rx/r_cmt_rx_if.h
  • src/smc_gen/r_cmt_rx/src/r_cmt_rx.c
  • src/smc_gen/r_config/r_cmt_rx_config.h
  • src/smc_gen/Config_PORT/Config_PORT.c

6.8 编写呼吸灯代码

打开 workspace/timer_breathing_led/src/timer_breathing_led.c,核心代码如下:

#include “r_smc_entry.h”
#include “r_cmt_rx_if.h”

#define CMT_CHANNEL             (0U)
#define CMT_FREQUENCY_HZ        (10000U)
#define PWM_STEPS               (100U)
#define BREATH_UPDATE_TICKS     (200U)

static volatile uint8_t g_pwm_count = 0U;
static volatile uint8_t g_brightness = 0U;
static volatile uint16_t g_breath_tick = 0U;
static volatile int8_t g_breath_dir = 1;

CMT_FREQUENCY_HZ 设为 10000U,即每秒 10000 次中断(每 100 us 一次)。PWM_STEPS 设为 100,表示软件 PWM 分为 100 个亮度等级。

main() 中创建周期定时器:

timer_started = R_CMT_CreatePeriodicAssignChannelPriority(CMT_FREQUENCY_HZ,
                                                          breathing_timer_callback,
                                                          CMT_CHANNEL,
                                                          CMT_PRIORITY_5);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这行代码将 CMT0 配置为周期定时器,并注册 breathing_timer_callback() 为中断回调。创建成功后,LED1 亮灭完全由 CMT 回调驱动,主循环无需延时翻转。

回调函数完成两项任务:

  • 根据当前亮度值产生软件 PWM 波形。
  • 周期性调整亮度值,实现从暗到亮、再从亮到暗的循环。

若定时器创建失败,程序会让 LED1 以 100 ms 间隔快速闪烁作为错误提示。

6.9 编译下载与现象

代码编写完成后,依次执行:

Project -> Clean

然后右键 timer_breathing_led 工程,选择 Build Project。编译通过后进入 Debug 下载,程序停在 main() 时点击 Resume

运行后,LED1 不再是固定频率闪烁,而是呈现平滑的明暗渐变。这一现象表明 CMT 定时器已在稳定产生周期中断,软件 PWM 根据定时器节拍持续调整 LED 输出占空比。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


第七章 OLED 实验:IIC 驱动 0.96 寸 SSD1306

前面两个实验均使用开发板自带资源:LED1 点灯验证 GPIO,呼吸灯验证定时器。接下来换成外接模块,测评开发板的扩展能力。测试使用的屏幕是常见的 0.96 寸 OLED,控制芯片为 SSD1306,通信方式为 IIC。

本章先采用软件 IIC,也就是用普通 GPIO 模拟 SCL 和 SDA 的时序。这样做的好处是工程依赖少,先把接线、地址、SSD1306 初始化流程跑通;后面再单独做一章,把同样的 OLED 改成 Smart Configurator 生成的硬件 I2C 驱动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.1 为什么用 OLED 测扩展接口

OLED 比 LED 更适合做“外设通信”测评。LED 只有一个输出电平,能验证 GPIO;OLED 需要连续发送命令和显存数据,能同时验证引脚、时序、电源、IIC 地址和外设初始化流程。

这一章的学习路线如下:

OLED IIC 实验

外设模块

0.96 寸 OLED

SSD1306 控制芯片

常见地址 0x3C 或 0x3D

供电使用 3V3

开发板引脚

PMOD1-SCL

PMOD1-SDA

Arduino SCL/SDA 复用

P26 模拟 SCL

P31 模拟 SDA

通信原理

IIC 起始信号

发送设备地址

等待 ACK

发送命令或数据

停止信号

程序结构

软件 IIC 层

SSD1306 命令层

显示绘图层

错误提示层

从测评角度看,这个实验能回答三个问题:

  • 开发板扩展口是否方便接常见模块。
  • 3.3 V 供电和 IIC 电平是否适合 SSD1306 OLED。
  • RX14T 在不用复杂外设驱动的情况下,能否通过 GPIO 模拟总线完成实际通信。

7.2 IIC 和 SSD1306 的基本原理

IIC 只需要两根信号线:

信号 作用 本实验引脚
SCL 时钟线,由主机产生节拍 P26
SDA 数据线,主机和从机共用 P31

IIC 总线的关键特点是“开漏/释放”思想。设备并不是主动把总线推成高电平,而是通过上拉电阻让线自然变高;需要输出低电平时,设备再把线拉低。因此软件 IIC 代码里不是简单地一直输出 0/1,而是:

  • 输出低电平:把引脚设成输出,并写 0。
  • 输出高电平:把引脚释放成输入,让上拉电阻把线拉高。

本实验中,代码用 PORT2.PDR.BIT.B6 控制 P26 的方向,用 PORT3.PDR.BIT.B1 控制 P31 的方向;用 PORT2.PCR.BIT.B6PORT3.PCR.BIT.B1 打开内部上拉。OLED 模块本身通常也带上拉电阻,所以内部上拉只是辅助。

SSD1306 的显示过程可以理解为两类数据:

类型 控制字节 作用
命令 0x00 设置显示开关、地址模式、扫描方向、对比度等
显示数据 0x40 写入显存,让屏幕上对应像素点亮或熄灭

本章的程序先发送一组 SSD1306 初始化命令,再清屏、画边框、显示文字。

main 进入

初始化 P26/P31/LED1

尝试 OLED 地址 0x3C

收到 ACK?

尝试 OLED 地址 0x3D

收到 ACK?

LED1 快闪报错

发送 SSD1306 初始化命令

清屏

画边框

写入测试文字

OLED 显示测评结果

7.3 引脚分配与接线

根据工程和官方板卡资料,FPB-RX14T 的 PMOD1/Arduino IIC 引脚可以这样使用:

OLED 引脚 开发板位置 MCU 引脚 说明
VCC 3V3 - 使用 3.3 V 供电
GND GND - 共地
SCL PMOD1-SCL / ARDUINO-SCL P26 / SCL0 本实验作为软件 IIC 时钟线
SDA PMOD1-SDA / ARDUINO-SDA P31 / SDA0 本实验作为软件 IIC 数据线

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接线时需要优先确认以下四项:

  1. OLED 的 VCC 接 3V3,不接 5V。
  2. OLED 的 GND 必须和开发板 GND 相连。
  3. SCL 接到 PMOD1-SCL / ARDUINO-SCL。
  4. SDA 接到 PMOD1-SDA / ARDUINO-SDA。

如果 SCL 和 SDA 接反,程序通常不会收到 OLED 的 ACK,LED1 会进入 100 ms 快闪错误提示。

7.4 新建 oled_iic 工程

本实验新建独立工程 oled_iic,避免影响前面已验证通过的 test 点灯工程和 timer_breathing_led 呼吸灯工程。工程配置保持一致:

  • Board:FPB-RX14T
  • Device:R5F514T5AxFM
  • Toolchain:CC-RX
  • Debugger:E2 Lite

本章没有添加 RIICSCI IIC 组件,因为这次是软件 IIC。Smart Configurator 在这里主要用于确认工程、芯片、时钟和引脚资料;真正的 SCL/SDA 时序由 oled_iic.c 中的 GPIO 代码实现。

后续如果要做硬件 IIC 版本,可以再在 Smart Configurator 中添加 I2C Master Mode 组件,选择 SCI6,把 P26/P31 切到 SSCL6/SSDA6 外设功能。

7.5 软件 IIC 代码结构

打开 workspace/oled_iic/src/oled_iic.c。本实验的代码分成四层:

board_pins_init

软件 IIC 层

SSD1306 命令层

清屏/画边框/写文字

OLED 显示结果

ACK 检测

LED1 错误提示

第一层是引脚初始化:

/* Software I2C on PMOD1/Arduino I2C: P26=SCL0, P31=SDA0. */
PORT2.PMR.BIT.B6 = 0U;
PORT3.PMR.BIT.B1 = 0U;
PORT2.PCR.BIT.B6 = 1U;
PORT3.PCR.BIT.B1 = 1U;

这里 P26 对应 PORT2.B6,P31 对应 PORT3.B1PMR 清 0 表示作为普通 GPIO 使用,PCR 置 1 表示打开内部上拉。

第二层是软件 IIC 的基本动作:

static void i2c_start(void);
static void i2c_stop(void);
static bool i2c_write_byte(uint8_t data);

i2c_start() 负责产生起始信号,i2c_stop() 负责产生停止信号,i2c_write_byte() 负责发送 8 位数据并读取 ACK。只要 OLED 没有应答,函数就会返回 false

第三层是 SSD1306 写命令和写数据:

static bool oled_cmd(uint8_t cmd);
static bool oled_cmd2(uint8_t cmd, uint8_t arg);
static bool oled_write(uint8_t control, const uint8_t * data, uint16_t length);

control0x00 时表示后面是命令;control0x40 时表示后面是显示数据。

第四层是显示内容:

oled_clear();
oled_draw_border();
oled_draw_text(1U, 14U, "FPB-RX14T");
oled_draw_text(3U, 18U, "OLED IIC");
oled_draw_text(4U, 10U, "SSD1306 OK");
oled_draw_text(6U, 4U, "SCL:P26 SDA:P31");

程序最终会在 OLED 上显示开发板名称、实验名称、SSD1306 通信成功提示,以及本次接线使用的 SCL/SDA 引脚。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.6 编译下载与运行现象

代码写完后,先在 e2 studio 中执行:

Project -> Clean

然后右键 oled_iic 工程,选择:

Build Project

编译通过后进入 Debug 下载。程序停在 main() 时,点击 Resume 继续运行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

运行成功时,OLED 会显示边框和测试文字。这个现象说明:开发板扩展口供电正常,SCL/SDA 接线正确,SSD1306 地址应答正常,软件 IIC 时序能够完成命令和显存数据传输。

7.7 本章小结

本章完成了第一个外接模块实验。与前面的 LED、定时器实验相比,OLED 实验增加了”外设通信”的概念:主控需要通过 IIC 地址找到设备,再按 SSD1306 的协议发送初始化命令和显示数据。

本章先采用软件 IIC,是为了降低工程配置复杂度,将重点放在接线、地址、ACK 和显示协议上。待这部分确认稳定后,再切换到 Smart Configurator 的硬件 I2C 配置,会更容易理解外设驱动、引脚复用和中断回调之间的关系。


第八章 OLED 硬件 I2C 实验:SCI6 驱动 SSD1306

软件 IIC 跑通以后,下一步就是把同一块 OLED 改成硬件外设驱动。这样做的意义不只是“换一种写法”,而是把 I2C 的起始信号、时钟节拍、ACK/NACK 检测和中断发送流程交给 MCU 外设与 Smart Configurator 生成代码处理,用户代码只负责组织 SSD1306 命令和显示数据。

本章使用新工程 oled_hard。它仍然驱动同一块 0.96 寸 SSD1306 OLED,接线也仍然使用 PMOD1/Arduino I2C 位置:

OLED 引脚 开发板位置 MCU 引脚 硬件功能
VCC 3V3 - 3.3 V 供电
GND GND - 共地
SCL PMOD1-SCL / ARDUINO-SCL P26 SSCL6
SDA PMOD1-SDA / ARDUINO-SDA P31 SSDA6

8.1 为什么这里用 SCI6 的 I2C mode

在组件列表中首先尝试寻找单独的 RIIC 配置项,但当前工程环境中更直接可用的是 I2C Master Mode 组件,并且它可以选择 SCI6 作为资源。RX14T 的 SCI 外设支持 Simple IIC / I2C mode,P26/P31 正好可以复用为 SSCL6/SSDA6,所以本章采用:

  • Smart Configurator 组件:I2C Master Mode
  • 配置名称:Config_SCI6
  • Work mode:I2C mode
  • Resource:SCI6
  • 引脚:SSCL6 -> P26SSDA6 -> P31

这样做仍然是硬件 I2C 思路:SCL/SDA 不再由 GPIO 手动翻转,而是由 SCI6 的 I2C mode 和生成的 Config_SCI6 驱动完成。

OLED 硬件 I2C 实验

工程层

oled_hard

CC-RX

Smart Configurator

外设层

I2C Master Mode

Config_SCI6

SCI6 I2C mode

中断方式发送

引脚层

SSCL6 -> P26

SSDA6 -> P31

PMOD1/Arduino I2C

应用层

SSD1306 初始化

清屏

画边框

显示测试文字

现象层

OLED 正常显示

LED1 快闪提示错误

8.2 添加 I2C Master Mode 组件

打开 oled_hard.scfg,进入 Components 页面,点击添加组件按钮。在组件列表中选择 I2C Master Mode,不要选择 SCI/SCIF Clock Synchronous Mode,也不要选择 Simple IIC Driver r_sci_iic_rx。前者更接近同步串行/SPI 场景,后者在本工程里通道支持不够直观;本实验最终使用的是 Code Generator 风格的 I2C Master Mode

在新建配置窗口中这样填写:

  • Configuration name:Config_SCI6
  • Work mode:I2C mode
  • Resource:SCI6

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里的关键是 Resource 必须选 SCI6。如果选成 SCI1 或其他通道,后面的引脚就不会对应到 PMOD1/Arduino I2C 的 P26/P31。

8.3 配置 I2C 传输参数

进入 Config_SCI6 的配置页面后,主要修改传输速率、噪声滤波、数据处理方式和回调。实际配置如下:

配置项 本实验设置
Transfer clock Internal clock
Baudrate 100 kbps
Enable noise filter 勾选
Noise filter clock Clock signal divided by 1
SSDA6 output delay No output delay
Transmit data handling Data handled in interrupt service routine
Receive data handling Data handled in interrupt service routine
IIC interrupt mode select Use ACK/NACK interrupts
TXI6/RXI6/TEI6 priority Level 13
Multiple interrupts 不勾选
Callback function 勾选 Transfer end,保留 Receive end 也可以

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里有一个容易踩坑的地方:Transmit data handlingReceive data handling 必须选择 Data handled in interrupt service routine。如果保持为 DTC,生成的 R_Config_SCI6_IIC_Master_Send() 不会真正使用 tx_buftx_num 发送缓冲区,OLED 命令数据就发不出去。

修改正确后,生成的 Config_SCI6.c 中应能看到:

gp_sci6_tx_address = tx_buf;
g_sci6_tx_count = tx_num;

这两行说明发送缓冲区已经由中断发送流程接管。

8.4 配置 P26/P31 引脚

切到 Pins 页面,将 SCI6 的 I2C 引脚分配到开发板的 PMOD1/Arduino I2C 位置:

SCI6 功能 MCU 引脚 板上标注
SSCL6 P26 PMOD1-SCL / ARDUINO-SCL
SSDA6 P31 PMOD1-SDA / ARDUINO-SDA

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果 Generate Code 日志中出现下面信息,就说明引脚已经从默认位置改到了目标位置:

SSCL6 assignment is changed from Pin 9 to Pin 44
SSDA6 assignment is changed from Pin 7 to Pin 42

生成后还可以直接检查代码。正确的 Config_SCI6.cPin.c 中应出现:

MPC.P26PFS.BYTE = 0x0AU;   /* SSCL6 */
MPC.P31PFS.BYTE = 0x0AU;   /* SSDA6 */

8.5 Generate Code 与生成文件

配置完成后点击 Generate Code。生成成功后,工程中会出现:

  • src/smc_gen/Config_SCI6/Config_SCI6.h
  • src/smc_gen/Config_SCI6/Config_SCI6.c
  • src/smc_gen/Config_SCI6/Config_SCI6_user.c
  • src/smc_gen/general/r_cg_sci.h
  • src/smc_gen/r_pincfg/Pin.c

生成代码的分工可以这样理解:

文件 作用
Config_SCI6.c 初始化 SCI6、配置 P26/P31 复用功能、提供 I2C Master 发送接口
Config_SCI6_user.c 中断服务函数和用户回调,适合放传输完成标志
Config_SCI6.h 对外声明 R_Config_SCI6_Start()R_Config_SCI6_IIC_Master_Send() 等接口
Pin.c 生成器统一维护的引脚初始化结果

8.6 硬件 I2C 代码结构

本工程的用户代码位于 workspace/oled_hard/src/oled_hard.c。和软件 IIC 版本相比,SSD1306 初始化、清屏、画边框、写字符这些上层逻辑基本不变,变化的是底层发送函数。

硬件 I2C 版本的发送流程如下:

main

R_Config_SCI6_Start

oled_init_at 0x3C

oled_write

sci6_iic_send_blocking

R_Config_SCI6_IIC_Master_Send

SCI6 中断发送地址和数据

Transfer end callback

设置 g_sci6_iic_tx_end

继续 SSD1306 初始化/显示

核心发送函数是:

static bool sci6_iic_send_blocking(uint8_t address, uint8_t * data, uint16_t length)
{
    uint32_t timeout = SCI6_IIC_WAIT_TIMEOUT;

    g_sci6_iic_tx_end = 0U;
    g_sci6_iic_error = 0U;

    R_Config_SCI6_IIC_Master_Send((uint8_t)(address << 1), data, length);

    while ((0U == g_sci6_iic_tx_end) && (0U == g_sci6_iic_error) && (timeout > 0UL))
    {
        timeout--;
    }

    return ((0U != g_sci6_iic_tx_end) && (0U == g_sci6_iic_error));
}

这里传入 address << 1,是因为生成的 R_Config_SCI6_IIC_Master_Send() 接收的是包含读写位位置的地址字节。OLED 的 7-bit 地址是 0x3C,左移一位后就是写地址 0x78

Config_SCI6_user.c 中在传输完成回调里设置标志:

static void r_Config_SCI6_callback_transmitend(void)
{
    g_sci6_iic_error = SCI6.SISR.BIT.IICACKR;
    g_sci6_iic_tx_end = 1U;
}

这样应用层可以用阻塞等待的方式保持代码简单,同时底层实际发送仍然由 SCI6 中断完成。

8.7 与软件 IIC 版本的对比

两种方式都能驱动 SSD1306,但教学重点不同:

项目 软件 IIC 版本 硬件 I2C 版本
工程名 oled_iic oled_hard
SCL/SDA 控制方式 GPIO 手动拉低/释放 SCI6 I2C mode 自动产生时序
Smart Configurator 作用 主要确认引脚和工程环境 生成 Config_SCI6 驱动和引脚复用
引脚功能 普通 GPIO SSCL6/SSDA6
代码重点 理解 IIC 起始、停止、ACK 理解组件配置、生成 API、中断回调
适合阶段 先跑通接线和协议 后续规范工程和外设驱动

软件 IIC 更适合解释总线时序,硬件 I2C 更接近实际项目。实际产品中通常会优先使用硬件外设,因为它的时序更稳定,CPU 占用更低,也更容易和中断、DMA/DTC 等机制配合。

8.8 编译下载与运行现象

确认 Config_SCI6 生成正确后,执行:

Project -> Clean

然后右键 oled_hard 工程,选择 Build Project。编译通过后进入 Debug 下载,程序停在 main() 时点击 Resume

运行成功后,OLED 会显示边框和测试文字:

  • FPB-RX14T
  • OLED HARD
  • SSD1306 OK
  • SCI6 P26/P31

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个现象说明:Smart Configurator 已经正确生成 SCI6 I2C 初始化代码,P26/P31 已经切换到 SSCL6/SSDA6,OLED 地址应答正常,SSD1306 初始化命令和显存数据都能通过硬件 I2C 发出。

8.9 本章小结

本章将第七章的软件 IIC OLED 实验升级为硬件 I2C 版本。最终可用的配置不是手写底层寄存器,而是在 Smart Configurator 中添加 I2C Master Mode,选择 SCI6,再把 SSCL6/SSDA6 分配到 P26/P31。

这个过程也暴露了图形化配置里最值得注意的几个点:

  1. 组件要选 I2C Master Mode,不要误选同步串行模式。
  2. 资源要选 SCI6,因为 OLED 接在 P26/P31。
  3. 引脚必须确认生成到 P26PFS/P31PFS,不能停留在默认的 P36/P37。
  4. 数据处理方式要选 ISR,否则发送缓冲区可能不会被使用。
  5. 用户代码应该调用生成 API,并把完成标志放在 Config_SCI6_user.c 的 user code 区,避免下次 Generate Code 被覆盖。

到这里,OLED 的两种驱动方式都已经跑通:软件 IIC 帮助理解协议细节,硬件 I2C 帮助理解规范工程配置和外设驱动流程。


第九章 开源项目移植:在 OLED 上运行 Dino 小游戏

前面已经完成了 OLED 的软件 IIC 和硬件 I2C 驱动,屏幕能够稳定显示文字和图形。接下来继续提高测评难度:不再只是显示固定内容,而是把一个开源的 STM32 OLED 小游戏移植到 FPB-RX14T 上,用同一块 SSD1306 OLED 显示画面,再用 P10 按键控制跳跃。

本章使用的参考项目 https://github.com/kuzlik340/stm32-dino-game# 是一个基于 STM32F411 的 Chrome Dino 小游戏,原项目说明中使用 Blackpill v2.0、SSD1306 OLED、PB6/PB7 I2C 和 PA0 按键。从 GitHub 下载源码并解压到本地工作目录后,即可开始移植。

参考链接:

  • GitHub 仓库:https://github.com/kuzlik340/stm32-dino-game
  • Chrome Dino 背景参考:chrome://dino
  • 许可证:MIT License

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9.1 为什么选择 Dino 小游戏

这个实验不是为了单纯“玩游戏”,而是为了让开发板测评更接近真实嵌入式小项目。Dino 小游戏虽然代码量不大,但同时覆盖了几个关键能力:

能力 在游戏中的体现
OLED 图形刷新 每帧刷新地面、云朵、分数、恐龙和障碍物
按键输入 P10 触发恐龙跳跃
状态机 运行、跳跃、死亡、等待重开
碰撞检测 恐龙和障碍物矩形区域重叠时判定失败
移植能力 将 STM32 寄存器代码替换成 RX14T + Smart Configurator 生成 API

相比单纯显示几行文字,小游戏能更明显地暴露刷新速度、I2C 稳定性、按键响应和程序结构问题。对于测评文章来说,它也更直观:只要 OLED 上的恐龙能跑、P10 能跳、撞到障碍后能显示 retry,就说明显示、输入和主循环都已经工作。

9.2 移植前先看原项目结构

原项目的文件结构很清晰:

原项目文件 作用
main.c 游戏主循环、跳跃、碰撞、死亡重开
SSD1306.c/.h OLED 初始化、显存、像素和位图绘制
i2c.c/.h STM32F411 的 I2C1 寄存器驱动
button.c/.h PA0 按键输入
systick.c/.h SysTick 延时
adc.c/.h 用 ADC 读数生成随机数
bitmaps.h 恐龙、障碍物、retry 等位图

这里不能直接把代码复制到 RX14T 工程里编译,因为底层外设完全不同。STM32 项目里大量使用 RCCGPIOAGPIOBI2C1SysTickADC1 这些 STM32 寄存器;FPB-RX14T 工程里则应继续使用前面已经跑通的 Smart Configurator 生成代码。

因此本章采用“分层移植”的思路:

STM32 Dino 项目

按层拆分

游戏逻辑层

图形绘制层

硬件访问层

保留并改写到 oled_hard.c

保留 framebuffer 和 bitmap 思路

替换为 RX14T SCI6 / P10 / BSP Delay

FPB-RX14T Dino 版本

9.3 移植策略

本章不是从零写游戏,而是把原项目中”与芯片无关”的部分保留下来,把”与 STM32 强绑定”的部分换掉。

保留的内容:

  1. Chrome Dino 的基本玩法:障碍物从右向左移动,按键跳跃,碰撞后失败。
  2. SSD1306 framebuffer 思路:先在 1024 字节显存中画像素,再按页刷新到 OLED。
  3. 位图绘制函数:按 bitmap 中的 bit 决定像素是否点亮。
  4. 恐龙、障碍物、死亡恐龙、retry 等像素资源。

替换的内容:

原 STM32 实现 RX14T 移植实现
I2C1_burstWrite() R_Config_SCI6_IIC_Master_Send()
PB6/PB7 I2C P26/P31,SSCL6/SSDA6
PA0 按键 P10,PORT1.B0
SysTick 延时 R_BSP_SoftwareDelay()
ADC 随机数 简单伪随机数
STM32 寄存器初始化 Smart Configurator 生成代码

这样做的好处是边界清楚:游戏仍然是游戏,OLED 仍然是 SSD1306,但底层 I2C 和按键完全换成了 FPB-RX14T 的实现。

Dino 移植思路

保留

游戏规则

framebuffer

位图资源

碰撞检测

替换

STM32 I2C1

STM32 GPIOA PA0

SysTick

ADC 随机数

接入 RX14T

Config_SCI6

P26/P31 OLED

P10 按键

R_BSP_SoftwareDelay

改造

Chrome 风格 UI

分数和 HI

云朵和地面滚动

I2C 重试

9.4 继续使用 oled_hard 工程

本章没有重新创建工程,而是直接在已经跑通的 oled_hard 工程上继续改。原因很简单:第八章已经证明这个工程的硬件 I2C 链路是可用的,Config_SCI6、P26/P31、OLED 地址和 SSD1306 初始化都已经验证过。继续使用它可以把风险集中在游戏移植本身,而不是重新排查 I2C 配置。

需要保留的 Smart Configurator 配置如下:

项目 配置
Component I2C Master Mode
Config name Config_SCI6
Work mode I2C mode
Resource SCI6
SCL SSCL6 -> P26
SDA SSDA6 -> P31
Baudrate 100 kbps
Data handling ISR 方式

按键使用 P10。代码中将 P10 配成普通 GPIO 输入,并打开内部上拉:

PORT1.PMR.BIT.B0 = 0U;
PORT1.PDR.BIT.B0 = 0U;
PORT1.PCR.BIT.B0 = 1U;

按键逻辑采用低电平有效,也就是按下时读到 0。为了避免一直按住时反复触发,代码用边沿检测,只在“松开 -> 按下”的瞬间触发一次跳跃。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9.5 OLED framebuffer 与位图绘制

SSD1306 是 128 x 64 分辨率,显存大小为:

128 x 64 / 8 = 1024 字节

移植后的代码使用:

static uint8_t g_framebuffer[OLED_FRAME_BYTES];

每一帧先清空 g_framebuffer,再依次画云朵、分数、地平线、障碍物、恐龙,最后统一刷新到 OLED。这样比“画一个像素就发一次 I2C”更适合做动画。

核心流程如下:

game_update 更新游戏状态

fb_clear 清空显存

draw_clouds 画云朵

draw_score 画 HI 和分数

draw_horizon 画滚动地面

draw_tree 画障碍物

draw_dino 画恐龙

fb_flush 刷新到 SSD1306

位图绘制函数的思路是:位图数组中的每一位对应一个像素,bit 为 1 就在 framebuffer 中点亮对应位置。这样可以直接复用原项目里的恐龙、障碍物和 retry 图案。

9.6 游戏状态机与跳跃参数

移植后的游戏状态集中在 game_state_t

typedef struct st_game_state
{
    int16_t dino_y;
    int8_t velocity_y;
    int16_t tree_x;
    uint16_t frame;
    uint16_t score;
    uint8_t jumping;
    uint8_t gravity_tick;
    uint8_t alive;
    uint8_t death_wait;
} game_state_t;

其中最关键的是:

字段 作用
dino_y 恐龙当前纵坐标
velocity_y 跳跃速度,负数表示向上
tree_x 障碍物横坐标
score 当前分数
jumping 是否正在跳跃
alive 是否还活着

P10 被按下时,如果恐龙当前不在跳跃状态,就给它一个初速度:

g_game.jumping = 1U;
g_game.velocity_y = JUMP_VELOCITY;
g_game.gravity_tick = 0U;

为了让一次跳跃更高、滞空更久,本实验没有每一帧都增加重力,而是每两帧增加一次:

#define JUMP_VELOCITY           (-6)
#define GRAVITY_PER_FRAME       (1)
#define GRAVITY_UPDATE_FRAMES   (2U)

这样恐龙能跨过更远的障碍,同时跳跃曲线不会显得特别突兀。

9.7 UI 改造:更接近 Chrome Dino

首次移植成功后,OLED 上已能看到恐龙和障碍物,但画面与 Chrome 离线小游戏仍有差距。因此又进行了一轮 UI 改造:

  1. 顶部右侧增加 HI 和分数。
  2. 背景增加移动云朵。
  3. 地面从一条实线改成断续滚动像素线。
  4. 恐龙和障碍物改为原项目位图。
  5. 死亡后显示 retry 图标,再按 P10 重开。

运行时画面大致由这些元素组成:

HI / 分数

云朵

恐龙

障碍物

断续地平线

retry 重开

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=assets%2Fimages%2Fimage-54.png&pos_id=img-h6bAduCl-1781187671049

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9.8 I2C 稳定性处理

小游戏和静态显示不同。静态显示只需要写几次 OLED,而 Dino 每一帧都要刷新 1024 字节 framebuffer。如果每帧发送次数太多,I2C 偶发 NACK 或总线忙就容易让程序进入错误状态。

实测中出现过”走着走着不动,LED1 开始闪烁”的现象。这个现象不是碰撞检测触发,而是 I2C 刷新过程中发送失败后进入了错误提示。针对这一问题做了以下处理:

  1. 将每次 OLED 数据分包从 16 字节改为 64 字节,减少每帧 I2C 事务数。
  2. 单次 SCI6 I2C 发送失败后最多重试 3 次。
  3. 重试前先 R_Config_SCI6_Stop(),再 R_Config_SCI6_Start(),给外设和总线一次恢复机会。
  4. 帧间隔从 35 ms 放宽到 45 ms,降低刷新压力。

关键参数如下:

#define OLED_TX_CHUNK_SIZE      (64U)
#define SCI6_IIC_RETRY_COUNT    (3U)
#define FRAME_DELAY_MS          (45U)

这一步很重要,因为它说明“游戏能跑”和“游戏能稳定跑”不是一回事。OLED 动画刷新对 I2C 驱动的连续传输能力要求更高,也更容易暴露底层通信细节。

9.9 编译下载与运行现象

代码修改完成后,执行:

Project -> Clean

然后右键 oled_hard 工程,选择:

Build Project

编译通过后进入 Debug 下载,程序停在 main() 时点击 Resume

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

运行正常时,OLED 上会出现接近 Chrome Dino 的画面:顶部有 HI 和分数,中间有云朵,底部有滚动地面,恐龙在左侧奔跑,障碍物从右向左移动。按下 P10 后恐龙跳跃,撞到障碍物后显示 retry 图标,再按 P10 可以重新开始。

验收清单如下:

  1. OLED 能持续显示 Dino 动画。
  2. P10 能触发跳跃。
  3. 碰撞后显示 retry。
  4. retry 状态下再次按 P10 能重开。
  5. 游戏持续运行时 LED1 不应异常快闪。

9.10 本章小结

本章把一个 STM32F411 上的 OLED Dino 小游戏移植到了 FPB-RX14T。移植重点不是简单复制代码,而是识别哪些部分可以复用、哪些部分必须替换:

  • 复用游戏玩法、framebuffer、位图资源和碰撞检测。
  • 替换 STM32 的 I2C、按键、SysTick 和 ADC。
  • 继续使用 Smart Configurator 生成的 Config_SCI6 硬件 I2C 驱动 OLED。
  • 使用 P10 作为跳跃按键。
  • 针对连续动画刷新增加 I2C 分包和重试策略。

到这里,oled_hard 已经不只是一个 OLED 显示验证工程,而是变成了一个包含显示、输入、动画、状态机和错误恢复的小型综合实验。这个实验也为后续做按键菜单、图形界面、实时数据显示甚至电机状态面板打下了基础。


第十章 常见问题排查

10.1 设备管理器没有 E2 Lite

按以下顺序排查:

  • USB 线是否为数据线(非纯充电线)。
  • 开发板是否通电。
  • J7 跳线是否按文档设置。
  • e2 studio 安装时是否包含 RX Debug Support。

10.2 e2 studio 找不到 RX14T

如果新建工程时没有 RX14T 或 FPB-RX14T 选项,需要回到:

Help -> Install New Software...

安装 RX Smart Configurator、RX Common、RX Debug Support 和相关板卡支持。

10.3 LED1 没有亮

按以下顺序排查:

  1. 是否已经成功 Build。
  2. Debug 配置是否选择 E2 Lite。
  3. 目标芯片是否为 R5F514T5。
  4. 程序是否已经下载到板子。
  5. 下载后是否点击了 Resume。
  6. Smart Configurator 中 P32 是否配置为 GPIO Output。
  7. 生成代码后,smc_gen 下是否出现 Config_PORT/Config_PORT.c
  8. r_cg_hardware_setup.c 中是否调用 R_Config_PORT_Create()
  9. test.c 中是否使用 PIN_WRITE(LED1) 翻转 LED1。

如果以上都确认无误,仍然不亮,可以临时用寄存器方式写 P32 做硬件排错。但这只作为排查手段,不作为正式教程主流程。

10.4 呼吸灯没有效果

如果 timer_breathing_led 工程可以下载,但 LED1 没有呼吸效果,按以下顺序排查:

  1. Config_PORT 是否已经生成。
  2. P32 是否已经配置为 GPIO 输出。
  3. r_cmt_rx 是否已经添加并生成。
  4. r_cmt_rx_if.hr_cmt_rx.c 是否存在。
  5. timer_breathing_led.c 是否包含 r_cmt_rx_if.h
  6. R_CMT_CreatePeriodicAssignChannelPriority() 是否返回成功。
  7. 下载后是否点击了 Resume

如果 LED1 变成 100 ms 快速闪烁,说明程序进入了定时器创建失败提示分支,需要回到 CMT 组件和生成代码结果中检查。

10.5 OLED 没有显示

如果 oled_iic 工程可以下载,但 OLED 没有显示,按以下顺序排查:

  1. OLED 的 VCC 是否接到 3V3。
  2. OLED 的 GND 是否和开发板 GND 共地。
  3. SCL 是否接到 PMOD1-SCL / ARDUINO-SCL,对应 P26。
  4. SDA 是否接到 PMOD1-SDA / ARDUINO-SDA,对应 P31。
  5. OLED 模块地址是否为 0x3C0x3D
  6. 下载后是否点击了 Resume
  7. LED1 是否 100 ms 快闪。

如果 LED1 快闪,说明程序没有收到 OLED 的 ACK,优先检查接线、供电和地址。如果 LED1 不快闪但屏幕没有内容,说明通信可能已经通过,需要继续检查 OLED 屏幕型号、初始化参数或屏幕排线方向。

10.6 硬件 I2C OLED 没有显示

如果 oled_hard 工程可以下载,但 OLED 没有显示,按以下顺序排查:

  1. Config_SCI6 是否已经生成,工程中是否存在 src/smc_gen/Config_SCI6
  2. Smart Configurator 中是否选择 I2C Master Mode,Work mode 是否为 I2C mode,Resource 是否为 SCI6
  3. Pins 页面中 SSCL6 是否分配到 P26,SSDA6 是否分配到 P31。
  4. 生成代码里是否能看到 MPC.P26PFS.BYTE = 0x0AU;MPC.P31PFS.BYTE = 0x0AU;,不要停留在默认的 P36/P37。
  5. Transmit data handlingReceive data handling 是否为 ISR 方式,Config_SCI6.c 中是否出现 gp_sci6_tx_address = tx_buf;g_sci6_tx_count = tx_num;
  6. main() 中是否先调用 R_Config_SCI6_Start(),再执行 SSD1306 初始化。
  7. 用户回调是否写在 Config_SCI6_user.c 的 user code 区,Generate Code 后不要被覆盖。
  8. OLED 地址是否按 7-bit 地址使用 0x3C0x3D,调用生成接口时是否发送 (address << 1)

如果这些都正确,硬件 I2C 仍然没有显示,再回到接线和供电检查:VCC 接 3V3,GND 共地,SCL/SDA 没有接反,下载后已经点击 Resume

10.7 Dino 游戏运行一会儿 LED1 快闪

如果 Dino 游戏能运行,但过一会儿画面停止并且 LED1 快闪,通常不是撞到障碍物,而是 OLED I2C 刷新失败后进入了错误提示。按以下顺序排查:

  1. P26/P31 接线是否牢固。
  2. OLED 供电是否稳定,VCC 是否接 3V3。
  3. OLED_TX_CHUNK_SIZE 是否为 64U,不要每次只发 16 字节导致事务过多。
  4. SCI6_IIC_RETRY_COUNT 是否为 3U
  5. FRAME_DELAY_MS 是否为 45U 或更大。

如果仍然偶发失败,可以继续降低刷新压力,例如把 OLED_TX_CHUNK_SIZE 改成 32U,或把 FRAME_DELAY_MS 增大到 55U


第十一章 本章小结

至此,FPB-RX14T 的第一组测评已完成:从开箱检查、安装 e2 studio、创建 RX14T 工程、配置 E2 Lite 下载,到最终点亮 LED1;随后用 CMT 定时器实现了 LED1 呼吸灯,又通过 PMOD1/Arduino IIC 引脚驱动了 0.96 寸 SSD1306 OLED。OLED 部分先用 oled_iic 软件 IIC 跑通接线、地址和 SSD1306 协议,再用 oled_hard 通过 Smart Configurator 的 I2C Master Mode 生成 Config_SCI6,将 P26/P31 配为 SSCL6/SSDA6 实现硬件 I2C 驱动,最后在同一个硬件 I2C 工程上完成了 Dino 小游戏移植。

虽然本次测评未连接电机,但通过 LED 的亮灭、CMT 呼吸灯、OLED 外设通信和 Dino 小游戏移植,已能直观验证 GPIO、定时器、引脚复用、Smart Configurator 生成代码、外部按键输入、OLED 图形刷新和简单状态机的基本使用方式。后续可在此基础上继续进行按键菜单、硬件 PWM 输出和电机控制相关实验。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐