MicroPython 驱动 SSD1306 OLED 显示屏实战指南:SPI / I2C 接线、驱动与绘图
嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载SSD1306 是市面上最常见的单色 OLED 控制器之一广泛出现在 128x64、128x32 等小尺寸显示屏模块中。本文以 MicroPython 官方 ESP8266 教程中的 SSD1306 章节 为核心骨架完整讲解从硬件 SPI、软件 SPI、I2C 三种接口的接线与初始化到ssd1306驱动模块的显示控制再到基于framebuf的图形绘制 API并辅以仓库内 nRF 移植示例、ESP8266 板级清单与framebuf官方文档的源码级佐证帮助读者一次掌握在资源受限的嵌入式平台上驱动 OLED 的完整方案。一、SSD1306 显示屏与 MicroPython 的ssd1306驱动SSD1306 OLED 显示屏使用 SPI 或 I2C 接口与主控通信市场上有多种尺寸与颜色组合可选常见尺寸128x64、128x32、72x40、64x48常见颜色白色、黄色、蓝色以及黄蓝双色上半部分黄色、下半部分蓝色等。在 MicroPython 中ssd1306驱动模块是一个通用的、跨移植的显示驱动它派生自framebuf.FrameBuffer因此天然继承了framebuf提供的全部图形原语画点、画线、矩形、文字、滚动、blit 等。在 ESP8266 移植版的板级清单中官方已经将ssd1306作为可选驱动预置进固件——见 ports/esp8266/boards/ESP8266_GENERIC/manifest_2MiB.py其中require(ssd1306)一行即从 micropython-lib 拉取该驱动因此 2MiB Flash 版本的 ESP8266 固件可直接import ssd1306使用。驱动模块对外暴露两个类SSD1306_SPI(width, height, spi, dc, rst, cs)用于 SPI 接口的显示屏SSD1306_I2C(width, height, i2c)用于 I2C 接口的显示屏默认器件地址 0x3C。两者都在构造时把屏幕尺寸宽 x 高单位像素作为前两个参数传入且都继承framebuf.FrameBuffer这意味着不管用哪种接口后续的绘图代码完全一致。二、三种接口的接线与初始化2.1 硬件 SPI 接口ESP8266 的硬件 SPI 通道速度更快最高可达 80 MHz但引脚是固定的SCKGPIO14、MOSIGPIO13、MISOGPIO12OLED 只写不读MISO 闲置。官方教程的初始化代码from machine import Pin, SPI import ssd1306 hspi SPI(1) # sck14 (scl), mosi13 (sda), miso12 (unused) dc Pin(4) # data/command rst Pin(5) # reset cs Pin(15) # chip select, some modules do not have a pin for this display ssd1306.SSD1306_SPI(128, 64, hspi, dc, rst, cs)要点SPI(1)在 ESP8266 上对应硬件 SPI 总线SPI(0)被 Flash 占用、用户不可用见 docs/esp8266/quickref.rst 中 Hardware SPI bus 一节dc数据/命令选择、rst复位、cs片选由普通 GPIO 控制部分模块把cs直接接地固定选通这类模块可以不接该引脚如果你的模块自带复位电路rst引脚也可省去但驱动初始化时仍需传参。2.2 软件 SPI 接口软件 SPI 通过位操作bit-banging实现可以在任意 GPIO 上工作适合对速率不敏感、希望自由选择引脚的场景from machine import Pin, SoftSPI import ssd1306 spi SoftSPI(baudrate500000, polarity1, phase0, sckPin(14), mosiPin(13), misoPin(12)) dc Pin(4) # data/command rst Pin(5) # reset cs Pin(15) # chip select, some modules do not have a pin for this display ssd1306.SSD1306_SPI(128, 64, spi, dc, rst, cs)关于polarity与phase的语义docs/esp8266/quickref.rst 的 Software SPI bus 一节有明确说明polarity是 SCK 空闲时的电平phase0表示在 SCK 的第一个边沿采样、phase1表示在第二个边沿采样。SSD1306 的 SPI 模式为 CPOL1、CPHA0因此上例中固定使用polarity1, phase0baudrate可适当提高例如 1 MHz以获得更流畅的刷新。2.3 I2C 接口I2C 接线最简单只需两根数据线SDA SCL驱动默认使用器件地址0x3Cfrom machine import Pin, I2C import ssd1306 # using default address 0x3C i2c I2C(sdaPin(4), sclPin(5)) display ssd1306.SSD1306_I2C(128, 64, i2c)在 ESP8266 上machine.I2C是软件 I2C 实现等价于SoftI2C可在任意 GPIO 上工作参考 docs/esp8266/quickref.rst 的 I2C bus 一节i2c I2C(sclPin(5), sdaPin(4), freq100000)也就是说SDA/SCL 引脚完全可自由选择freq100000100 kHz是常见的默认速率部分模块的 I2C 地址也可通过背面电阻配置为0x3D此时驱动初始化需要传第三个参数addr如SSD1306_I2C(128, 64, i2c, addr0x3D)具体以所用固件/驱动版本为准。从移植代码来看I2C 驱动的数据传输可以做到“一次写一整块显示缓冲”例如 ports/nrf/examples/ssd1306_mod.py 中展示了把 128x64 的显示缓冲按 254 字节分块、逐块write_data的写屏策略并针对 64 像素宽的屏幕自动把列地址平移 32 像素。这解释了为什么 I2C 接口虽然带宽有限仍能获得可用的刷新率。三、显示控制Hello World 与基础控制方法在完成初始化后第一行文字可以通过text()show()显示display.text(Hello, World!, 0, 0, 1) display.show()text(s, x, y, c)把字符串绘制到帧缓冲的 (x, y) 处左上角对齐最后一个参数是颜色注意此时内容还只在内存帧缓冲中必须调用show()才会真正写入显示屏的显存。驱动还提供一组屏幕控制方法display.poweroff() # power off the display, pixels persist in memory display.poweron() # power on the display, pixels redrawn display.contrast(0) # dim display.contrast(255) # bright display.invert(1) # display inverted display.invert(0) # display normal display.rotate(True) # rotate 180 degrees display.rotate(False) # rotate 0 degrees display.show() # write the contents of the FrameBuffer to display memory各方法的含义poweroff()/poweron()关闭/打开显示面板电源帧缓冲中的像素数据保持不变重新poweron()后画面原样恢复contrast(0~255)调节对比度亮度0 最暗、255 最亮可用来实现背光调节或省电invert(1)/invert(0)反转/恢复显示黑底白字与白底黑字切换rotate(True)/rotate(False)将画面旋转 180 度 / 恢复正常方向适合屏幕安装方向与预期不符的场景show()把FrameBuffer内容整体写入显示器的显存所有绘图操作都必须以它收尾才会呈现。四、基于framebuf的图形绘制 APISSD1306_SPI与SSD1306_I2C都继承framebuf.FrameBuffer因此可以调用framebuf的全部绘图原语。官方教程给出的示例display.fill(0) # fill entire screen with colour0 display.pixel(0, 10) # get pixel at x0, y10 display.pixel(0, 10, 1) # set pixel at x0, y10 to colour1 display.hline(0, 8, 4, 1) # draw horizontal line x0, y8, width4, colour1 display.vline(0, 8, 4, 1) # draw vertical line x0, y8, height4, colour1 display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63 display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 117,53, colour1 display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 117,53, colour1 display.text(Hello World, 0, 0, 1) # draw some text at x0, y0, colour1 display.scroll(20, 0) # scroll 20 pixels to the right # draw another FrameBuffer on top of the current one at the given coordinates import framebuf fbuf framebuf.FrameBuffer(bytearray(8 * 8 * 1), 8, 8, framebuf.MONO_VLSB) fbuf.line(0, 0, 7, 7, 1) display.blit(fbuf, 10, 10, 0) # draw on top at x10, y10, key0 display.show()各 API 的作用与细节详见 docs/library/framebuf.rstfill(c)用颜色 c 填满整个屏幕pixel(x, y)读取 (x, y) 处像素颜色pixel(x, y, c)设置该像素颜色hline(x, y, w, c)/vline(x, y, h, c)/line(x1, y1, x2, y2, c)画水平线、垂直线、任意斜线线宽均为 1 像素rect(x, y, w, h, c)画矩形边框fill_rect(x, y, w, h, c)画实心矩形text(s, x, y, c)以 (x, y) 为左上角绘制文本所有字符尺寸固定为 8x8 像素目前无法更换字体scroll(xstep, ystep)将帧缓冲内容按向量平移平移后可能在边缘留下旧颜色痕迹blit(fbuf, x, y, key)把另一个 FrameBuffer 叠加绘制到当前缓冲的 (x, y) 处key为透明色——当key指定后源帧缓冲中颜色值等于key的像素不会被绘制。上面的例子中key0表示源图中黑色0像素透明从而只把斜线叠加到画面上。关于示例中的framebuf.MONO_VLSB格式这是 1-bit 单色格式字节中的位按“垂直”方向映射bit 0 靠近屏幕顶部每个字节覆盖 8 个垂直像素bytearray(8 * 8 * 1)即为 8x8 像素、每像素 1 bit 的缓冲大小。SSD1306 内部页缓冲布局正是这种“每字节 8 个垂直像素”的结构因此MONO_VLSB与 SSD1306 的显存布局天然匹配无需额外的像素格式转换。五、完整示例绘制 MicroPython 徽标官方教程最后给出一个综合示例组合了矩形、垂直直线与文字在 128x64 屏幕上重现 MicroPython 徽标图案display.fill(0) display.fill_rect(0, 0, 32, 32, 1) display.fill_rect(2, 2, 28, 28, 0) display.vline(9, 8, 22, 1) display.vline(16, 2, 22, 1) display.vline(23, 8, 22, 1) display.fill_rect(26, 24, 2, 4, 1) display.text(MicroPython, 40, 0, 1) display.text(SSD1306, 40, 12, 1) display.text(OLED 128x64, 40, 24, 1) display.show()绘制思路先用fill_rect在左上角画出 32x32 的白色方块作为徽标底再用fill_rect挖出内部 28x28 的黑色区域形成边框三条vline勾勒出 MicroPython 徽标特有的三条竖线造型最后一段小竖条作为落款右侧三行文字分别显示 MicroPython、SSD1306、OLED 128x64。运行后即完成整个徽标与文字的组合显示。六、跨移植可用性与固件集成ssd1306驱动并非 ESP8266 专属只要固件中包含该驱动同样的初始化与绘图代码可以平滑迁移到其他移植。仓库中可以找到的佐证ESP32 移植的多个官方开发板把ssd1306驱动直接打包进固件例如 LOLIN S2 PICO见 ports/esp32/boards/LOLIN_S2_PICO/manifest.py与 LILYGO TTGO LoRa32见 ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py其板载 OLED 应用代码如 ports/esp32/boards/LOLIN_S2_PICO/modules/s2pico_oled.py即调用SSD1306_I2C实现屏幕显示STM32 移植的 GARATRONIC PYBSTICK26 F411 板同样在固件清单中引入ssd1306见 ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.pynRF 移植的示例 ports/nrf/examples/ssd1306_mod.py 在驱动之上演示了 I2C 分块写屏与 64 像素宽屏幕的列偏移适配。因此如果你使用的固件没有预置该驱动可以通过 MicroPython 的 manifest / 冻结机制把 micropython-lib 中的ssd1306模块打入固件否则需要手动将ssd1306.py上传到设备文件系统后再import。七、常见问题与实用建议屏幕无显示先确认供电3.3V与 GND 接线I2C 模式检查地址是否为 0x3C可用i2c.scan()扫描总线SPI 模式检查dc/rst/cs三个控制引脚是否与代码一致并确认模块是否需要外接上拉电阻。画面闪烁或刷新慢I2C 带宽有限可减少不必要的整屏刷新SPI 模式可提高baudrate硬件 SPI 最高 80 MHz。显示方向不对用display.rotate(True)旋转 180 度即可无需改接线。显示反色确认是否需要display.invert(1)新屏幕首次上电可能出现全亮或全暗的默认状态调用fill(0)show()即可清屏。自定义图形framebuf还支持ellipse()椭圆/圆可限制象限与poly()多边形coords需为整数数组如array(h, [x0, y0, x1, y1, ...])等更多原语均可直接作用于 SSD1306 显示对象。参考资料本教程官方出处docs/esp8266/tutorial/ssd1306.rstESP8266 快速参考SPI / SoftSPI / I2C 引脚与用法docs/esp8266/quickref.rstframebuf模块完整 API 文档docs/library/framebuf.rst官方板级固件清单含require(ssd1306)ports/esp8266/boards/ESP8266_GENERIC/manifest_2MiB.pynRF 移植的 I2C 分块写屏示例ports/nrf/examples/ssd1306_mod.py赞分享嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载相关推荐GitHub_Trending/aig/ai-guide 小程序开发TRAE 框架快速构建 AI 应用GitHub_Trending/aig/ai guide 小程序开发TRAE 框架快速构建 AI 应用 GitHub_Trending/aig/ai guid文档教程知识库人工智能ESP32 OLED显示实战SSD1306驱动完全指南想要在ESP32项目中添加OLED显示屏却不知从何入手SSD1306作为物联网设备中最常用的OLED显示方案能够为你的项目提供清晰直观的视觉反馈。本文将带你嵌入式驱动开发物联网嵌入式GUISSD1306 OLED显示屏驱动库完整使用指南SSD1306 OLED显示屏驱动库完整使用指南 SSD1306是一款专为有机/聚合物发光二极管点阵图形显示系统设计的单芯片CMOS OLED/PLED驱动控制嵌入式驱动开发物联网上一篇LiveAutoRecord核心组件分析autorecord/manager调度引擎详解下一篇HumHub国际化解决方案30语言支持与多语言内容管理终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考