概述
SSD1306 是一款 OLED 显示屏驱动芯片(OLED = 有机发光二极管显示屏,一种自发光屏幕,每个像素自己发光、不需要背光;像素 = 屏幕最小的「格子」),市面上常见的 0.96 寸 OLED 模块大多使用它。屏幕本质是点阵(用一个个格子拼出图案)结构,本教程通过 I2C 总线(两根线的串行通信:SCL 时钟线定节奏 + SDA 数据线传内容)驱动一块 128×64 分辨率的 OLED 屏幕,显示一行日期时间。
用大白话讲:OLED 屏幕就像一台「小电视」,不过它的每个「像素点」(最小的发光格子)自己会发光,不需要像老式液晶屏那样靠背光照亮。I2C 总线就像「两个人打电话」:SCL 是说话的节奏,SDA 是说话的内容。屏幕在总线上有一个「门牌号」(I2C 地址 0x3C),程序把要显示的内容按门牌号发过去,屏幕就把图案画出来。本教程让屏幕显示一行写死的日期时间。
本教程基于安信可官方 SDK(Ai-Thinker-Open/Ai-Thinker-WB2,版本
release_bl_iot_sdk_1.6.40)的官方示例applications/iot-solution/demo_ssd1306编写,代码可在本地 SDK 中直接找到。
按官方示例接线(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.c中oled_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:年份,如2025MM:月份,1~12dd:日,1~31HH:时,0~23mm:分,0~59ss:秒,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 完整代码
#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

