在嵌入式开发中,OLED屏幕因功耗低、对比度高、响应速度快等优势,常被用于设备状态显示、数据可视化等场景。RA-Eco-RA6M4开发板集成了丰富的外设接口,其中I2C接口为驱动OLED等外设提供了便捷条件。本文将详细介绍如何通过RA6M4的I2C外设驱动SeedStudio SSD1315 OLED屏幕,并完成u8g2图形库的移植,最终实现文字显示功能。
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是一款开源的单色图形库,支持几乎所有主流单色OLED/LCD控制器,其移植的核心在于实现硬件抽象层(HAL)的接口适配——即根据目标MCU的硬件特性,实现u8g2所需的两个关键回调函数。
u8g2通过回调函数与MCU硬件交互,移植时必须实现以下两类接口:
这两类函数需遵循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为指令参数。
本文采用瑞萨RA Smart Configurator(RASC)配置硬件外设,结合Keil MDK编写代码,具体配置步骤如下:
g_i2c0;g_i2c0的SCL映射至P100,SDA映射至P101,确保引脚方向设为“Output Open Drain”(符合I2C总线要求)。sci_i2c_master_callback,中断优先级设为12(根据系统需求调整,需高于普通任务)。csrc文件夹复制到工程的“Drivers/u8g2”目录下;.c文件;该函数主要处理u8g2的延时指令和GPIO初始化,针对RA6M4的BSP函数设计如下:
#include "u8g2.h"
#include "hal_data.h"
// 全局I2C事件标志,用于中断回调同步
static volatile i2c_master_event_t g_master_event = I2C_MASTER_EVENT_ABORTED;
/**
* [url=home.php?mod=space&uid=2666770]@Brief[/url] u8g2 GPIO与延时回调函数
* [url=home.php?mod=space&uid=3142012]@param[/url] u8x8:u8g2设备句柄
* @param msg:u8g2指令类型
* @param arg_int:指令整数参数
* @param arg_ptr:指令指针参数
* [url=home.php?mod=space&uid=1141835]@Return[/url] 1:处理成功;0:未处理
*/
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
// 初始化阶段延时(确保OLED上电稳定)
case U8X8_MSG_GPIO_AND_DELAY_INIT:
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
break;
// 毫秒级延时(满足I2C时序要求)
case U8X8_MSG_DELAY_MILLI:
R_BSP_SoftwareDelay(arg_int, BSP_DELAY_UNITS_MILLISECONDS);
break;
// 其他未使用指令默认返回0
default:
return 0;
}
return 1;
}
该函数负责将u8g2的待发送数据通过RA6M4的硬件I2C发送至OLED,利用32字节缓冲区适配u8g2的传输限制:
/**
* @brief u8g2 I2C通信回调函数
* @param u8x8:u8g2设备句柄
* @param msg:u8g2通信指令
* @param arg_int:数据长度
* @param arg_ptr:数据指针
* @return 1:处理成功;0:未处理
*/
uint8_t u8x8_i2c_transfer(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t i2c_buf[32]; // u8g2单次传输不超过32字节
static uint8_t buf_idx = 0; // 缓冲区索引
uint8_t *data = (uint8_t *)arg_ptr;
fsp_err_t err = FSP_SUCCESS;
uint32_t timeout = 100; // 超时时间100ms
switch (msg)
{
// 接收u8g2待发送数据,存入缓冲区
case U8X8_MSG_BYTE_SEND:
while (arg_int-- > 0)
{
i2c_buf[buf_idx++] = *data++;
}
break;
// 初始化阶段(此处I2C已由RASC配置,无需额外初始化)
case U8X8_MSG_BYTE_INIT:
break;
// I2C无DC引脚,忽略该指令
case U8X8_MSG_BYTE_SET_DC:
break;
// 开始传输:重置缓冲区索引
case U8X8_MSG_BYTE_START_TRANSFER:
buf_idx = 0;
break;
// 结束传输:通过硬件I2C发送缓冲区数据
case U8X8_MSG_BYTE_END_TRANSFER:
// 发送I2C数据(非阻塞模式,通过中断确认完成)
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;
}
/**
* @brief I2C中断回调函数(同步传输状态)
*/
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
if (NULL != p_args)
{
g_master_event = p_args->event;
}
}
在hal_entry函数中完成u8g2初始化、OLED启动,并实现文字显示功能:
void hal_entry(void)
{
u8g2_t u8g2; // 定义u8g2设备实例
/* 1. 初始化u8g2:适配SSD1315(兼容SSD1306 vcomh0配置) */
u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f(
&u8g2, // 设备实例
U8G2_R0, // 屏幕旋转方向(0度)
u8x8_i2c_transfer, // 通信回调函数
u8x8_gpio_and_delay // GPIO与延时回调函数
);
/* 2. 初始化OLED屏幕 */
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0); // 关闭省电模式(点亮屏幕)
u8g2_ClearDisplay(&u8g2); // 清屏
/* 3. 配置显示内容:设置字体并显示文字 */
u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312); // 16号中文宋体
u8g2_DrawUTF8(&u8g2, 10, 20, "电子发烧友 2025"); // 坐标(10,20)显示中文
u8g2_DrawUTF8(&u8g2, 10, 40, "RA6M4 OLED Demo"); // 坐标(10,40)显示英文
u8g2_SendBuffer(&u8g2); // 将缓冲区数据发送至OLED
/* 4. 主循环:保持程序运行 */
while (1)
{
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
}
}
编译下载程序后,OLED屏幕成功点亮,清晰显示“电子发烧友 2025”和“RA6M4 OLED Demo”两行文字,无闪烁、错位现象,说明I2C通信正常,u8g2移植成功。
屏幕无反应:
vcomh0版本,其他函数可能不兼容SSD1315)。文字显示乱码:
u8g2_font_wqy16_t_gb2312需依赖u8g2_fonts.c);u8g2_DrawUTF8的坐标是否超出屏幕范围(128x64屏幕,X最大127,Y最大63)。I2C传输失败:
sci_i2c_master_callback);本文通过RA-Eco-RA6M4的I2C外设实现了SSD1315 OLED的驱动,核心在于理解u8g2的HAL层设计思想,通过两个回调函数完成硬件适配。该方案的优势在于u8g2的跨平台特性——只需修改回调函数中的硬件操作部分,即可快速移植到其他MCU(如STM32、ESP32)。
后续可基于此方案扩展功能:
u8g2_DrawLine、u8g2_DrawCircle等函数绘制波形、图标;更多回帖