SSD1306 OLED 屏幕模块配备 0.9 英寸迷你单色屏,128×32 分辨率,白光像素点。拥有极高的对比度,显示清晰极易辨识。OLED 仅使用树莓派的 I2C 和电源引脚,无需独立供电,即插即用。
接线
屏幕模块的 VCC 接树莓派 Pico 的 3V3 引脚
屏幕模块的 GND 接树莓派 Pico 的 GND 引脚
屏幕模块的 SDA 引脚接树莓派 Pico 的 GP14 引脚
屏幕模块的 SCL 引脚接树莓派 Pico 的 SCL 引脚
代码
这里使用开源的 MicroPython ssd1306 库。将下面的代码保存在 Pico 上,命名为 ssd1306.py。
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces from micropython import const import framebuf # register definitions SET_CONTRAST = const(0x81) SET_ENTIRE_ON = const(0xA4) SET_NORM_INV = const(0xA6) SET_DISP = const(0xAE) SET_MEM_ADDR = const(0x20) SET_COL_ADDR = const(0x21) SET_PAGE_ADDR = const(0x22) SET_DISP_START_LINE = const(0x40) SET_SEG_REMAP = const(0xA0) SET_MUX_RATIO = const(0xA8) SET_IREF_SELECT = const(0xAD) SET_COM_OUT_DIR = const(0xC0) SET_DISP_OFFSET = const(0xD3) SET_COM_PIN_CFG = const(0xDA) SET_DISP_CLK_DIV = const(0xD5) SET_PRECHARGE = const(0xD9) SET_VCOM_DESEL = const(0xDB) SET_CHARGE_PUMP = const(0x8D) # Subclassing FrameBuffer provides support for graphics primitives # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html class SSD1306(framebuf.FrameBuffer): def __init__(self, width, height, external_vcc): self.width = width self.height = height self.external_vcc = external_vcc self.pages = self.height // 8 self.buffer = bytearray(self.pages * self.width) super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) self.init_display() def init_display(self): for cmd in ( SET_DISP, # display off # address setting SET_MEM_ADDR, 0x00, # horizontal # resolution and layout SET_DISP_START_LINE, # start at line 0 SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 SET_MUX_RATIO, self.height - 1, SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 SET_DISP_OFFSET, 0x00, SET_COM_PIN_CFG, 0x02 if self.width > 2 * self.height else 0x12, # timing and driving scheme SET_DISP_CLK_DIV, 0x80, SET_PRECHARGE, 0x22 if self.external_vcc else 0xF1, SET_VCOM_DESEL, 0x30, # 0.83*Vcc # display SET_CONTRAST, 0xFF, # maximum SET_ENTIRE_ON, # output follows RAM contents SET_NORM_INV, # not inverted SET_IREF_SELECT, 0x30, # enable internal IREF during display on # charge pump SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, SET_DISP | 0x01, # display on ): # on self.write_cmd(cmd) self.fill(0) self.show() def poweroff(self): self.write_cmd(SET_DISP) def poweron(self): self.write_cmd(SET_DISP | 0x01) def contrast(self, contrast): self.write_cmd(SET_CONTRAST) self.write_cmd(contrast) def invert(self, invert): self.write_cmd(SET_NORM_INV | (invert & 1)) def rotate(self, rotate): self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3)) self.write_cmd(SET_SEG_REMAP | (rotate & 1)) def show(self): x0 = 0 x1 = self.width - 1 if self.width != 128: # narrow displays use centred columns col_offset = (128 - self.width) // 2 x0 += col_offset x1 += col_offset self.write_cmd(SET_COL_ADDR) self.write_cmd(x0) self.write_cmd(x1) self.write_cmd(SET_PAGE_ADDR) self.write_cmd(0) self.write_cmd(self.pages - 1) self.write_data(self.buffer) class SSD1306_I2C(SSD1306): def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False): self.i2c = i2c self.addr = addr self.temp = bytearray(2) self.write_list = [b"\x40", None] # Co=0, D/C#=1 super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.temp[0] = 0x80 # Co=1, D/C#=0 self.temp[1] = cmd self.i2c.writeto(self.addr, self.temp) def write_data(self, buf): self.write_list[1] = buf self.i2c.writevto(self.addr, self.write_list) class SSD1306_SPI(SSD1306): def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): self.rate = 10 * 1024 * 1024 dc.init(dc.OUT, value=0) res.init(res.OUT, value=0) cs.init(cs.OUT, value=1) self.spi = spi self.dc = dc self.res = res self.cs = cs import time self.res(1) time.sleep_ms(1) self.res(0) time.sleep_ms(10) self.res(1) super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(0) self.cs(0) self.spi.write(bytearray([cmd])) self.cs(1) def write_data(self, buf): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(1) self.cs(0) self.spi.write(buf) self.cs(1)
该库使用了 MicroPython 的 framebuf 库。关于 framebuf 库的用法可以参考文档,也可以通过这篇文章快速了解一下「MicroPython 帧缓冲区库 framebuf 的使用方法」。
下面是示例代码,在屏幕上输出指定的信息,将代码保存在 Pico 上,命名为 main.py。
import machine import ssd1306 i2c = machine.I2C(1, sda=machine.Pin(14), scl=machine.Pin(15), freq=400_000) print("I2C device: " + str(i2c.scan()[0])) oled = ssd1306.SSD1306_I2C(128, 64, i2c) oled.text("PICO LAB", 0, 0) oled.hline(0, 10, 128, 1) oled.text("Hello World!", 0, 26) oled.hline(0, 48, 128, 1) oled.text("PICO.NXEZ.COM", 0, 52) oled.show()
显示效果如图。
下面的示例代码来画一个树莓派 Logo 并显示在屏幕上。将代码保存在 Pico 上,命名为 main.py。
import ssd1306 import framebuf i2c = machine.I2C(1, sda=machine.Pin(14), scl=machine.Pin(15), freq=400_000) oled = ssd1306.SSD1306_I2C(128, 64, i2c) data = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x3E,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x07,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x03,0x80,0x00,0x01,0xF7,0xC0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0xFF,0x80,0x01,0xF8,0x00,0x0F,0x90,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xE0,0x01,0xFF,0x00,0x0E,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x01,0xF8,0x01,0xFF,0xC0,0x3C,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0xFF,0xFF,0xE1,0xE0,0x70,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x38,0x00,0xFF,0xFF,0xE0,0x70,0x70,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0xFF,0xFF,0xF0,0x39,0xC0,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xFF,0xDF,0xF0,0x1D,0xC0,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0xFE,0x01,0xF8,0x0F,0x80,0x00,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xC0,0x01,0xF8,0x00,0x7C,0x0F,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xF8,0x00,0x3E,0x0F,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xF0,0x00,0x1F,0x06,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xE0,0x00,0x1F,0x86,0x00,0x20,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0xC0,0x3F,0xE0,0x00,0x0F,0x86,0x00,0x20,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x7F,0xE0,0x00,0x0F,0xC6,0x00,0x40,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x0F,0xF7,0x00,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0x00,0x80,0x60,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0x01,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0x80,0xF0,0x00,0x0F,0x9F,0x83,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFE,0x00,0x78,0x00,0x0F,0x0F,0xC6,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFE,0x00,0x3C,0x00,0x0E,0x07,0xFC,0x00,0xC0,0x00,0x00,0x00, 0x00,0x00,0x00,0xE0,0x7C,0x00,0x1E,0x00,0x1E,0x03,0xFC,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x78,0x00,0x1F,0x00,0x3C,0x03,0xFC,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x78,0x00,0x0F,0xE0,0xFC,0x03,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x78,0x00,0x0F,0xFF,0xFC,0x01,0xFF,0xFC,0x00,0x00,0x00,0x00, 0x00,0x00,0x01,0xC0,0x78,0x00,0x0F,0xFF,0xFC,0x01,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x78,0x00,0x0F,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x78,0x00,0x0F,0xFF,0xFC,0x03,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x78,0x00,0x0F,0xE0,0xFC,0x03,0xFE,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xC0,0x78,0x00,0x0F,0x00,0x3C,0x03,0xFC,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7C,0x00,0x1E,0x00,0x1E,0x07,0xF8,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x7E,0x00,0x3C,0x00,0x0E,0x07,0xFC,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFE,0x00,0x38,0x00,0x0F,0x0F,0xC6,0x00,0xE0,0x00,0x00,0x00, 0x00,0x00,0x00,0x38,0xFF,0x80,0xF8,0x00,0x07,0x9F,0x83,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xE3,0xF0,0x00,0x07,0xFF,0x01,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x07,0xF7,0x00,0x80,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0xFF,0xF0,0x00,0x07,0xE7,0x00,0xC0,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0xC0,0x3F,0xF0,0x00,0x0F,0x86,0x00,0x40,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xF0,0x00,0x0F,0x86,0x00,0x20,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xF0,0x00,0x1F,0x0E,0x00,0x20,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xF0,0x00,0x3E,0x0E,0x00,0x10,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0xC0,0x01,0xF8,0x00,0x7C,0x4F,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xFC,0x00,0xF8,0x1F,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xFF,0x03,0xF8,0x1D,0x80,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x7F,0xFF,0xF0,0x39,0xC0,0x00,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x70,0x00,0x7F,0xFF,0xE0,0xF1,0xC0,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x7F,0xFF,0xE1,0xE0,0x70,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x7F,0x00,0xFF,0xC0,0x70,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x01,0xF0,0x00,0xFF,0x00,0x3C,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x07,0xFF,0xC0,0x01,0xF8,0x00,0x0E,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x80,0x03,0xC0,0x00,0x07,0x90,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x07,0x80,0x00,0x01,0xF7,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] buf = framebuf.FrameBuffer(bytearray(data), 128, 64, framebuf.MONO_HLSB) oled.blit(buf, 0, 0) oled.show()
运行效果如图。
这个例程 在PICO 上不能正常运行 做了修改后可以显示代码如下:
from machine import I2C
from ssd1306 import SSD1306_I2C
import utime
machine.freq(280000000) #set cpu croe freq
#——I2C Pin ——
#machine.I2C(1,freq = 10)
i2c = machine.I2C(1,sda=machine.Pin(2), scl=machine.Pin(3)) #100K
oled = SSD1306_I2C(128, 64, i2c )# 创建OLED显示屏的实例,128×64分辨率
temperature = 27 – ((machine.ADC(4).read_u16() * (3.3/65535) – 0.706)/0.001721)
print(“ID_I2C device: ” + str(i2c.scan()[0]))
print(“CPU Temperautre :”,temperature,” C”)
print(“CPU Frequency: {:.2f} MHz”.format(machine.freq()/1000000))
print(“—————————“)
oled.text(“PICO LAB”, 0, 0)
oled.hline(0, 10, 128, 1)
oled.text(“Hello World!”, 0, 26)
oled.hline(0, 48, 128, 1)
oled.text(“PICO.NXEZ.COM”, 0, 52)
oled.show()