Skip to content

概述

SSD1306 是一款 OLED 显示屏驱动芯片(OLED = 有机发光二极管显示屏,一种自发光屏幕,每个像素自己发光、不需要背光;像素 = 屏幕最小的「格子」),市面上常见的 0.96 寸 OLED 模块大多使用它。屏幕本质是点阵(用一个个格子拼出图案)结构,本教程通过 I2C 总线(两根线的串行通信:SCL 时钟线定节奏 + SDA 数据线传内容)驱动一块 128×64 分辨率的 OLED 屏幕,显示一行日期时间。

用大白话讲:OLED 屏幕就像一台「小电视」,不过它的每个「像素点」(最小的发光格子)自己会发光,不需要像老式液晶屏那样靠背光照亮。I2C 总线就像「两个人打电话」:SCL 是说话的节奏,SDA 是说话的内容。屏幕在总线上有一个「门牌号」(I2C 地址 0x3C),程序把要显示的内容按门牌号发过去,屏幕就把图案画出来。本教程让屏幕显示一行写死的日期时间。

本教程基于安信可官方 SDKAi-Thinker-Open/Ai-Thinker-WB2,版本 release_bl_iot_sdk_1.6.40)的官方示例 applications/iot-solution/demo_ssd1306 编写,代码可在本地 SDK 中直接找到。

🎯本页目标通过 I2C 总线驱动 SSD1306 OLED 屏幕显示日期时间,并认识点阵屏的驱动思路。
🧰前置条件① Ai-WB2 开发板、0.96 寸 SSD1306 OLED 模块、杜邦线 ② 已按 [SDK 安装](../sdk/sdk_intro) 完成开发环境搭建。
🔗相关章节I2C 总线原理见 [I2C 协议](../basic/i2c);显示类继续学习 [WS2812 RGB 灯](./ws2812)。

硬件接线

按官方示例接线(I2C 地址 0x3C,对应数据手册上的 7 位地址):

Ai-WB2 引脚 SSD1306 模块
IO12 SCL(时钟线)
IO3 SDA(数据线)
3V3 VCC
GND GND

💡 常见 0.96 寸 OLED 模块是 4 个引脚(VCC / GND / SCL / SDA),用杜邦线(两端带插针的连接线)一一接好即可。I2C 地址 = 设备在总线上的「门牌号」,程序就是按 0x3C 找到这块屏幕的,接线之前先确认你的模块地址是 0x3C(背面丝印或卖家资料里会写)。

进入示例工程

本教程直接使用官方 SDK 自带的 demo_ssd1306 示例工程,打开终端进入工程目录:

cd ~/Ai-Thinker-WB2/applications/iot-solution/demo_ssd1306

说明:cd 是「进入目录」命令,这里进入 demo_ssd1306 工程目录;后续的 make 编译、make flash 烧录命令都必须先在这个目录里执行。

📌 这是一个多文件工程:工程根目录下还有一层 demo_ssd1306/ 子目录,源码都在里面(main.c + 屏幕驱动 ssd1306_drive.c/h)。驱动代码单独成文件的好处是:以后想复用这块屏幕,直接把驱动文件拷走就行。

工程目录结构说明:

文件 作用
demo_ssd1306/main.c 主程序源码,本教程主要修改的文件
demo_ssd1306/ssd1306_drive.c / .h SSD1306 屏幕驱动(自研),封装了 I2C 初始化、显示字符/数字等接口
Makefile 编译入口,一般无需修改
编写代码

打开 demo_ssd1306/demo_ssd1306/main.c,本步完整代码已移至文末,见:

📜 完整代码 — 位于本页「完整代码」章节,默认折叠,点击展开,与官方示例(applications/iot-solution/demo_ssd1306/demo_ssd1306/main.c)完全一致。

代码要点:

代码 作用
oled_i2c_driver_init(12, 3) 用 IO12/IO3 初始化 I2C 并连接地址 0x3C 的屏幕,不初始化屏幕永远收不到数据
oled_time_output(2025, 4, 2, 12, 34, 56) 把日期时间画到屏幕点阵上(年月日时分秒),参数顺序错了显示就乱
vTaskDelay(portTICK_RATE_MS * 1000) 每 1 秒刷新一次显示,没有它时间只在开机瞬间刷一次、之后不变
编译工程

在工程目录执行编译:

make -j8

说明:make 是「编译工程」命令,把代码变成开发板能运行的固件(程序文件);-j8 表示用 8 个核并行编译,速度更快。

编译成功后生成固件 build_out/demo_ssd1306.bin

⚠️ 若提示 riscv64-unknown-elf-gcc: command not found,说明工具链权限未配置,先执行 cd toolchain/riscv/Linux && . chmod755.sh 再重新编译。

烧录固件

开发板保持 USB 连接,确认串口设备号(Linux 下通常为 /dev/ttyUSB0),执行烧录:

make flash p=/dev/ttyUSB0 b=921600

说明:make flash 是「烧录」命令,把编译好的固件写进开发板芯片。p= 后面是串口设备号(要改成你电脑上实际的串口,可用 ls /dev/ttyUSB* 查看),b= 是烧录波特率(传输速度)。

⏳ 烧录过程中按提示长按开发板 EN 键进入下载模式(部分开发板自动进入),等待进度条完成即烧录成功。

运行验证

烧录完成后开发板自动重启运行,观察 OLED 屏幕:

屏幕应显示 「时间」 字样、第二行 2025年4月2日、第三行 12:34:56(时间每秒刷新一次)。

💡 屏幕显示的是示例代码里写死的日期时间:想改成你自己的时间,就修改 main.coled_time_output(2025, 4, 2, 12, 34, 56) 的 6 个参数(顺序:年、月、日、时、分、秒),重新编译烧录即可。想点亮单个像素可以调用驱动里的 oled_drive_set_pixels(x, y, color)(见 ssd1306_drive.h)。

看到屏幕按「时间 / 年月日 / 时分秒」三行正常显示即为成功;如果屏幕完全不亮(白屏)或只有部分内容,说明还没成功,对照文末「常见问题与踩坑提示」排查。

代码执行流程

例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):


本文 API 汇总

oled_i2c_driver_init(oled_scl, oled_sda)

初始化 I2C 控制器并连接 SSD1306 屏幕(驱动自研接口,源码见 ssd1306_drive.c)。内部以 7 位地址 0x3C、400KHz 速率、主机模式初始化 I2C,并向屏幕发送一整套初始化命令(开显示、设置对比度等)。

参数

  • oled_scl:I2C 时钟引脚号,本教程传 12(IO12)
  • oled_sda:I2C 数据引脚号,本教程传 3(IO3)

返回值hosal_i2c_dev_t* 类型的 I2C 设备句柄;初始化失败返回 NULL

oled_time_output(yyyy, MM, dd, HH, mm, ss)

把日期时间按「时间 / 年月日 / 时分秒」三行画到屏幕上(驱动自研接口,源码见 ssd1306_drive.c)。内部调用 oled_output_char_num 等函数把每个数字拆成 8×16 的点阵字模(点阵 = 用格子拼出图案),写完调用 oled_refresh_screen 刷新屏幕。

参数

  • yyyy:年份,如 2025
  • MM:月份,1~12
  • dd:日,1~31
  • HH:时,0~23
  • mm:分,0~59
  • ss:秒,0~59

返回值:成功返回 0

vTaskDelay(ms)

让当前任务挂起指定毫秒数,期间让出 CPU 给其他任务(FreeRTOS 系统 API)。

参数

  • ms:延时毫秒数,可选值:任意非负整数(本教程用 portTICK_RATE_MS * 1000 表示 1 秒)

返回值:无


完整代码

以下为 demo_ssd1306/demo_ssd1306/main.c 完整源码,与官方示例(applications/iot-solution/demo_ssd1306/demo_ssd1306/main.c)完全一致:

📜 点击展开 demo_ssd1306/demo_ssd1306/main.c 完整代码
c
#include <stdio.h>

#include <FreeRTOS.h>
#include <task.h>

#include <hosal_i2c.h>
#include <bl_gpio.h>
#include <blog.h>

#include "ssd1306_drive.h"



int main(void)
{

    oled_i2c_driver_init(12, 3);

    for (;;) {
        
        oled_time_output(2025, 4, 2, 12, 34, 56);
        
        vTaskDelay(portTICK_RATE_MS * 1000);
    }

    return 0;
}

常见问题与踩坑提示

⚠️ 屏幕完全不亮(白屏)
原因:SCL/SDA 接反、I2C 地址不是 0x3C、模块供电不足
解决:检查接线 IO12=SCL、IO3=SDA(接反必白屏);地址 0x3C 是 7 位地址写法,有些模块标 0x78(8 位写法,两者是同一个地址),确认模块丝印

⚠️ 屏幕亮但显示乱码或闪烁
原因:杜邦线接触不良、线太长或 3V3 供电不稳
解决:重新插紧所有杜邦线,缩短连接线;确认模块 VCC 接 3V3(接 5V 可能烧坏模块)

⚠️ 编译报 No such file or directory(找不到 main.c)
原因:本工程是多文件工程,源码在二级目录 demo_ssd1306/demo_ssd1306/
解决:编译命令要在工程根目录 ~/Ai-Thinker-WB2/applications/iot-solution/demo_ssd1306 执行,make 会自动找源码,不要自己 cd 进二级目录

⚠️ 烧录时提示无法打开串口
原因:串口设备号不对或权限不足
解决:确认设备号 ls /dev/ttyUSB*;权限不足执行 sudo usermod -aG dialout $USER 后重新登录

⚠️ 烧录一直卡住等待,进度条不动
原因:未进入下载模式,或数据线只能充电不能传数据
解决:烧录时按提示长按 EN 键进入下载模式;换一根能传数据的 Type-C 数据线后重试

运行自检

OLED 屏幕正常显示「时间 / 2025年4月2日 / 12:34:56」三行内容且时间每秒刷新,即 SSD1306 驱动验证通过。

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23