RA-Eco-RA6M4开发板实战:基于I2C驱动OLED与u8g2图形库移植实现
在嵌入式开发中,OLED屏幕因功耗低、对比度高、响应速度快等优势,常被用于设备状态显示、数据可视化等场景。RA-Eco-RA6M4开发板集成了丰富的外设接口,其中I2C接口为驱动OLED等外设提供了便捷条件。本文将详细介绍如何通过RA6M4的I2C外设驱动SeedStudio SSD1315 OLED屏幕,并完成u8g2图形库的移植,最终实现文字显示功能。
一、硬件准备与连接设计
1.1 核心硬件选型
- 主控板:RA-Eco-RA6M4开发板(搭载瑞萨RA6M4 MCU,支持I2C、SPI等多种外设接口);
- OLED屏幕:SeedStudio Grove-OLED-Display-0.96(驱动芯片为SSD1315,兼容SSD1306指令集,分辨率128x64,I2C通信方式);
- 辅助元件:2个10KΩ上拉电阻(用于稳定I2C总线信号,避免信号衰减)。
1.2 硬件连接方案
RA6M4的I2C0接口为驱动OLED的核心通道,具体引脚定义与连接关系如下表所示:
| RA6M4引脚 |
功能 |
OLED引脚 |
辅助电路 |
|---|
| P100 |
I2C0_SCL |
SCL |
串联10KΩ上拉至3.3V |
| P101 |
I2C0_SDA |
SDA |
串联10KΩ上拉至3.3V |
| 3.3V |
电源 |
VCC |
直接连接 |
| GND |
接地 |
GND |
直接连接 |
连接说明:I2C总线的SCL和SDA线必须添加上拉电阻,这是因为I2C器件通常为开漏输出,上拉电阻可将信号拉高至3.3V,保证总线通信的稳定性;此外,需确保电源与地的连接无误,避免因电源反接损坏器件。
二、u8g2图形库移植核心原理
u8g2是一款开源的单色图形库,支持几乎所有主流单色OLED/LCD控制器,其移植的核心在于实现硬件抽象层(HAL)的接口适配——即根据目标MCU的硬件特性,实现u8g2所需的两个关键回调函数。
2.1 u8g2 HAL层接口需求
u8g2通过回调函数与MCU硬件交互,移植时必须实现以下两类接口:
- GPIO与Delay回调函数:负责GPIO引脚电平控制(如软件I2C的SCL/SDA切换)和延时功能(满足通信时序要求);
- 通信接口回调函数:负责实现I2C/SPI等物理层通信,完成数据向OLED控制器的传输。
这两类函数需遵循u8g2定义的函数原型:typedef uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr),其中msg参数为u8g2发送的指令(如延时、GPIO控制、数据发送等),arg_int和arg_ptr为指令参数。
三、开发环境配置(基于RASC与Keil)
本文采用瑞萨RA Smart Configurator(RASC)配置硬件外设,结合Keil MDK编写代码,具体配置步骤如下:
3.1 外设栈配置(RASC)
- 创建工程与添加I2C栈:
- 打开RASC,新建基于RA6M4的工程,在“Stacks”标签页点击“Add”,选择“HAL/Common”下的“I2C Master (r_sci_i2c)”,命名为
g_i2c0;
- 配置I2C核心参数:通道设为0,从站地址0x3C(SSD1315默认I2C地址),地址模式7位,通信速率为标准模式(100KHz),SDA输出延时300ns。
- 引脚映射:
- 在“Pins”标签页,将
g_i2c0的SCL映射至P100,SDA映射至P101,确保引脚方向设为“Output Open Drain”(符合I2C总线要求)。
- 中断配置:
- 启用I2C中断,回调函数命名为
sci_i2c_master_callback,中断优先级设为12(根据系统需求调整,需高于普通任务)。
3.2 u8g2源码集成
- 源码获取与复制:从u8g2官方仓库下载源码,将
csrc文件夹复制到工程的“Drivers/u8g2”目录下;
- Keil工程配置:
- 打开Keil工程,在“Manage Project Items”中新建“u8g2”分组,添加“Drivers/u8g2”下的所有
.c文件;
- 在“Options for Target”的“C/C++”标签页,添加包含路径“Drivers/u8g2”,确保编译器能找到u8g2头文件。
四、核心代码实现
4.1 GPIO与Delay回调函数实现
该函数主要处理u8g2的延时指令和GPIO初始化,针对RA6M4的BSP函数设计如下:
#include "u8g2.h"
#include "hal_data.h"
static volatile i2c_master_event_t g_master_event = I2C_MASTER_EVENT_ABORTED;
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT:
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
break;
case U8X8_MSG_DELAY_MILLI:
R_BSP_SoftwareDelay(arg_int, BSP_DELAY_UNITS_MILLISECONDS);
break;
default:
return 0;
}
return 1;
}
4.2 I2C通信回调函数实现
该函数负责将u8g2的待发送数据通过RA6M4的硬件I2C发送至OLED,利用32字节缓冲区适配u8g2的传输限制:
uint8_t u8x8_i2c_transfer(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t i2c_buf[32];
static uint8_t buf_idx = 0;
uint8_t *data = (uint8_t *)arg_ptr;
fsp_err_t err = FSP_SUCCESS;
uint32_t timeout = 100;
switch (msg)
{
case U8X8_MSG_BYTE_SEND:
while (arg_int-- > 0)
{
i2c_buf[buf_idx++] = *data++;
}
break;
case U8X8_MSG_BYTE_INIT:
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
buf_idx = 0;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
err = R_SCI_I2C_Write(&g_i2c0_ctrl, i2c_buf, buf_idx, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != g_master_event) && (timeout-- > 0))
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
}
if (I2C_MASTER_EVENT_ABORTED == g_master_event)
{
__BKPT(0);
}
g_master_event = I2C_MASTER_EVENT_ABORTED;
break;
default:
return 0;
}
return 1;
}
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
if (NULL != p_args)
{
g_master_event = p_args->event;
}
}
4.3 OLED初始化与显示逻辑
在hal_entry函数中完成u8g2初始化、OLED启动,并实现文字显示功能:
void hal_entry(void)
{
u8g2_t u8g2;
u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f(
&u8g2,
U8G2_R0,
u8x8_i2c_transfer,
u8x8_gpio_and_delay
);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
u8g2_ClearDisplay(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312);
u8g2_DrawUTF8(&u8g2, 10, 20, "电子发烧友 2025");
u8g2_DrawUTF8(&u8g2, 10, 40, "RA6M4 OLED Demo");
u8g2_SendBuffer(&u8g2);
while (1)
{
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
}
}
五、测试与问题排查
5.1 测试效果
编译下载程序后,OLED屏幕成功点亮,清晰显示“电子发烧友 2025”和“RA6M4 OLED Demo”两行文字,无闪烁、错位现象,说明I2C通信正常,u8g2移植成功。
5.2 常见问题与解决方法
-
屏幕无反应:
- 检查I2C引脚连接是否与配置一致(P100=SCL,P101=SDA);
- 确认上拉电阻是否焊接(无电阻可能导致I2C信号无法拉高);
- 验证u8g2初始化函数是否正确(需使用
vcomh0版本,其他函数可能不兼容SSD1315)。
-
文字显示乱码:
- 检查字体文件是否正确添加(
u8g2_font_wqy16_t_gb2312需依赖u8g2_fonts.c);
- 确认
u8g2_DrawUTF8的坐标是否超出屏幕范围(128x64屏幕,X最大127,Y最大63)。
-
I2C传输失败:
- 查看中断回调函数是否正确注册(RASC中需关联
sci_i2c_master_callback);
- 增加超时时间(若总线干扰大,可将超时调整至200ms)。
六、总结与扩展
本文通过RA-Eco-RA6M4的I2C外设实现了SSD1315 OLED的驱动,核心在于理解u8g2的HAL层设计思想,通过两个回调函数完成硬件适配。该方案的优势在于u8g2的跨平台特性——只需修改回调函数中的硬件操作部分,即可快速移植到其他MCU(如STM32、ESP32)。
后续可基于此方案扩展功能:
- 图形绘制:利用u8g2的
u8g2_DrawLine、u8g2_DrawCircle等函数绘制波形、图标;
- 动态显示:通过定时器更新显示内容,实现数据实时刷新;
- 多设备兼容:基于同一I2C总线连接温湿度传感器、EEPROM等外设,实现多设备协同工作。