差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
mp_oled [2021/10/05 17:14]
gongyusu [4. Adafruit关于SSD1306的使用介绍]
mp_oled [2023/08/01 10:49] (当前版本)
group003
行 13: 行 13:
 import utime import utime
  
-sda=machine.Pin(20+sda=machine.Pin(11
-scl=machine.Pin(21)+scl=machine.Pin(10)
  
 i2c=machine.I2C(0,​ sda=sda, scl=scl, freq=400000) i2c=machine.I2C(0,​ sda=sda, scl=scl, freq=400000)
行 107: 行 107:
 </​code>​ </​code>​
  
-### 3. 使用SSD1306 OLED显示+ 
 +### 3. Adafruit关于SSD1306的使用介绍 
 + 
 +#### I2C初始化 
 +<code python>​ 
 +import machine 
 +import ssd1306 
 +i2c = machine.I2C(-1,​ machine.Pin(5),​ machine.Pin(4)) 
 +oled = ssd1306.SSD1306_I2C(128,​ 32, i2c) 
 +</​code>​ 
 + 
 +#### SPI初始化 
 + 
 +<code python>​ 
 +import machine 
 +import ssd1306 
 +spi = machine.SPI(1,​ baudrate=8000000,​ polarity=0, phase=0) 
 +oled = ssd1306.SSD1306_SPI(128,​ 32, spi, machine.Pin(15),​ machine.Pin(0),​ machine.Pin(16) 
 +</​code>​ 
 + 
 +### 4. SSD1306库的调用 
 +[[https://​docs.micropython.org/​en/​latest/​esp8266/​tutorial/​ssd1306.html|Using a SSD1306 OLED display]] 
 SSD1306 OLED显示可以使用SPI或I2C接口,支持不同分辨率(128x64,​ 128x32, 72x40, 64x48)和颜色(白色,​ 黄色, 蓝色, 黄色 + 蓝色). SSD1306 OLED显示可以使用SPI或I2C接口,支持不同分辨率(128x64,​ 128x32, 72x40, 64x48)和颜色(白色,​ 黄色, 蓝色, 黄色 + 蓝色).
  
行 146: 行 168:
 i2c = I2C(sda=Pin(4),​ scl=Pin(5)) i2c = I2C(sda=Pin(4),​ scl=Pin(5))
 display = ssd1306.SSD1306_I2C(128,​ 64, i2c) display = ssd1306.SSD1306_I2C(128,​ 64, i2c)
-</code?+</code>
  
 在第一行打印Hello World: 在第一行打印Hello World:
行 205: 行 227:
  
  
-### 4Adafruit关于SSD1306使用介绍 +### 5MicroPython官方驱动 
- +[[https://​github.com/​micropython/​micropython/​blob/​master/​drivers/​display/​ssd1306.py|MicroPython SSD1306 OLED driver, ​I2C and SPI interfaces]]
-#### I2C初始化+
 <code python> <code python>
-import machine 
-import ssd1306 
-i2c = machine.I2C(-1,​ machine.Pin(5),​ machine.Pin(4)) 
-oled = ssd1306.SSD1306_I2C(128,​ 32, i2c) 
-</​code>​ 
- 
-#### SPI初始化 
- 
-<code python> 
-import machine 
-import ssd1306 
-spi = machine.SPI(1,​ baudrate=8000000,​ polarity=0, phase=0) 
-oled = ssd1306.SSD1306_SPI(128,​ 32, spi, machine.Pin(15),​ machine.Pin(0),​ machine.Pin(16) 
-</​code>​ 
- 
-#### SSD1306.py 
-<code python> 
- 
 # MicroPython SSD1306 OLED driver, I2C and SPI interfaces # MicroPython SSD1306 OLED driver, I2C and SPI interfaces
 +
 from micropython import const from micropython import const
 import framebuf import framebuf
 +
 +
 # register definitions # register definitions
 SET_CONTRAST = const(0x81) SET_CONTRAST = const(0x81)
行 249: 行 255:
 SET_VCOM_DESEL = const(0xDB) SET_VCOM_DESEL = const(0xDB)
 SET_CHARGE_PUMP = const(0x8D) SET_CHARGE_PUMP = const(0x8D)
 +
 # Subclassing FrameBuffer provides support for graphics primitives # Subclassing FrameBuffer provides support for graphics primitives
 # http://​docs.micropython.org/​en/​latest/​pyboard/​library/​framebuf.html # http://​docs.micropython.org/​en/​latest/​pyboard/​library/​framebuf.html
 class SSD1306(framebuf.FrameBuffer):​ class SSD1306(framebuf.FrameBuffer):​
     def __init__(self,​ width, height, external_vcc):​     def __init__(self,​ width, height, external_vcc):​
-      ​self.width = width +        ​self.width = width 
-      self.height = height +        self.height = height 
-      self.external_vcc = external_vcc +        self.external_vcc = external_vcc 
-      self.pages = self.height // 8 +        self.pages = self.height // 8 
-      self.buffer = bytearray(self.pages * self.width) +        self.buffer = bytearray(self.pages * self.width) 
-      super().__init__(self.buffer,​ self.width, self.height,​ framebuf.MONO_VLSB) +        super().__init__(self.buffer,​ self.width, self.height,​ framebuf.MONO_VLSB) 
-      self.init_display()+        self.init_display() 
     def init_display(self):​     def init_display(self):​
-      ​for cmd in ( +        ​for cmd in ( 
-        SET_DISP, # display off +            SET_DISP, ​ # display off 
-        # address setting +            # address setting 
-        SET_MEM_ADDR,​ +            SET_MEM_ADDR,​ 
-        0x00, # horizontal +            0x00,  # horizontal 
-        # resolution and layout +            # resolution and layout 
-        SET_DISP_START_LINE,​ # start at line 0 +            SET_DISP_START_LINE, ​ # start at line 0 
-        SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 +            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0 
-        SET_MUX_RATIO,​ +            SET_MUX_RATIO,​ 
-        self.height - 1, +            self.height - 1, 
-        SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 +            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0 
-        SET_DISP_OFFSET,​ +            SET_DISP_OFFSET,​ 
-        0x00, +            0x00, 
-        SET_COM_PIN_CFG,​ +            SET_COM_PIN_CFG,​ 
-        0x02 if self.width > 2 * self.height else 0x12, +            0x02 if self.width > 2 * self.height else 0x12, 
-        # timing and driving scheme +            # timing and driving scheme 
-        SET_DISP_CLK_DIV,​ +            SET_DISP_CLK_DIV,​ 
-        0x80, +            0x80, 
-        SET_PRECHARGE,​ +            SET_PRECHARGE,​ 
-        0x22 if self.external_vcc else 0xF1, +            0x22 if self.external_vcc else 0xF1, 
-        SET_VCOM_DESEL,​ +            SET_VCOM_DESEL,​ 
-        0x30, # 0.83*Vcc +            0x30,  # 0.83*Vcc 
-        # display +            # display 
-        SET_CONTRAST,​ +            SET_CONTRAST,​ 
-        0xFF, # maximum +            0xFF,  # maximum 
-        SET_ENTIRE_ON,​ # output follows RAM contents +            SET_ENTIRE_ON, ​ # output follows RAM contents 
-        SET_NORM_INV,​ # not inverted +            SET_NORM_INV, ​ # not inverted 
-        SET_IREF_SELECT,​ +            SET_IREF_SELECT,​ 
-        0x30, # enable internal IREF during display on +            0x30,  # enable internal IREF during display on 
-        # charge pump +            # charge pump 
-        SET_CHARGE_PUMP,​ +            SET_CHARGE_PUMP,​ 
-        0x10 if self.external_vcc else 0x14, +            0x10 if self.external_vcc else 0x14, 
-        SET_DISP | 0x01, # display on +            SET_DISP | 0x01,  # display on 
-       ​): # on +        ):  # on 
-        self.write_cmd(cmd) +            self.write_cmd(cmd) 
-      self.fill(0) +        self.fill(0) 
-      self.show()+        self.show() 
     def poweroff(self):​     def poweroff(self):​
-      ​self.write_cmd(SET_DISP)+        ​self.write_cmd(SET_DISP) 
     def poweron(self):​     def poweron(self):​
-      ​self.write_cmd(SET_DISP | 0x01)+        ​self.write_cmd(SET_DISP | 0x01) 
     def contrast(self,​ contrast):     def contrast(self,​ contrast):
-      ​self.write_cmd(SET_CONTRAST) +        ​self.write_cmd(SET_CONTRAST) 
-      self.write_cmd(contrast)+        self.write_cmd(contrast) 
     def invert(self,​ invert):     def invert(self,​ invert):
-      ​self.write_cmd(SET_NORM_INV | (invert & 1))+        ​self.write_cmd(SET_NORM_INV | (invert & 1)) 
     def rotate(self,​ rotate):     def rotate(self,​ rotate):
-      ​self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3)) +        ​self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3)) 
-      self.write_cmd(SET_SEG_REMAP | (rotate & 1))+        self.write_cmd(SET_SEG_REMAP | (rotate & 1)) 
     def show(self):     def show(self):
-      ​x0 = 0 +        ​x0 = 0 
-      x1 = self.width - 1 +        x1 = self.width - 1 
-      if self.width != 128: +        if self.width != 128: 
-      # narrow displays use centred columns +            # narrow displays use centred columns 
-      col_offset = (128 - self.width) // 2 +            col_offset = (128 - self.width) // 2 
-      x0 += col_offset +            x0 += col_offset 
-      x1 += col_offset +            x1 += col_offset 
-      self.write_cmd(SET_COL_ADDR) +        self.write_cmd(SET_COL_ADDR) 
-      self.write_cmd(x0) +        self.write_cmd(x0) 
-      self.write_cmd(x1) +        self.write_cmd(x1) 
-      self.write_cmd(SET_PAGE_ADDR) +        self.write_cmd(SET_PAGE_ADDR) 
-      self.write_cmd(0) +        self.write_cmd(0) 
-      self.write_cmd(self.pages - 1) +        self.write_cmd(self.pages - 1) 
-      self.write_data(self.buffer)+        self.write_data(self.buffer) 
 + 
 class SSD1306_I2C(SSD1306):​ class SSD1306_I2C(SSD1306):​
-  ​def __init__(self,​ width, height, i2c, addr=0x3C, external_vcc=False):​ +    ​def __init__(self,​ width, height, i2c, addr=0x3C, external_vcc=False):​ 
-    self.i2c = i2c +        self.i2c = i2c 
-    self.addr = addr +        self.addr = addr 
-    self.temp = bytearray(2) +        self.temp = bytearray(2) 
-    self.write_list = [b"​\x40",​ None] # Co=0, D/C#=1 +        self.write_list = [b"​\x40",​ None]  # Co=0, D/C#=1 
-    super().__init__(width,​ height, external_vcc) +        super().__init__(width,​ height, external_vcc) 
-  def write_cmd(self,​ cmd): + 
-    self.temp[0] = 0x80 # Co=1, D/C#=0 +    ​def write_cmd(self,​ cmd): 
-    self.temp[1] = cmd +        self.temp[0] = 0x80  # Co=1, D/C#=0 
-    self.i2c.writeto(self.addr,​ self.temp) +        self.temp[1] = cmd 
-  def write_data(self,​ buf): +        self.i2c.writeto(self.addr,​ self.temp) 
-    self.write_list[1] = buf + 
-    self.i2c.writevto(self.addr,​ self.write_list)+    ​def write_data(self,​ buf): 
 +        self.write_list[1] = buf 
 +        self.i2c.writevto(self.addr,​ self.write_list) 
 + 
 class SSD1306_SPI(SSD1306):​ class SSD1306_SPI(SSD1306):​
-  ​def __init__(self,​ width, height, spi, dc, res, cs, external_vcc=False):​ +    ​def __init__(self,​ width, height, spi, dc, res, cs, external_vcc=False):​ 
-    self.rate = 10 * 1024 * 1024 +        self.rate = 10 * 1024 * 1024 
-    dc.init(dc.OUT,​ value=0) +        dc.init(dc.OUT,​ value=0) 
-    res.init(res.OUT,​ value=0) +        res.init(res.OUT,​ value=0) 
-    cs.init(cs.OUT,​ value=1) +        cs.init(cs.OUT,​ value=1) 
-    self.spi = spi +        self.spi = spi 
-    self.dc = dc +        self.dc = dc 
-    self.res = res +        self.res = res 
-    self.cs = cs +        self.cs = cs 
-import time +        import time 
-self.res(1) + 
-time.sleep_ms(1) +        ​self.res(1) 
-self.res(0) +        time.sleep_ms(1) 
-time.sleep_ms(10) +        self.res(0) 
-self.res(1) +        time.sleep_ms(10) 
-super().__init__(width,​ height, external_vcc) +        self.res(1) 
-def write_cmd(self,​ cmd): +        super().__init__(width,​ height, external_vcc) 
-self.spi.init(baudrate=self.rate,​ polarity=0, phase=0) + 
-self.cs(1) +    ​def write_cmd(self,​ cmd): 
-self.dc(0) +        self.spi.init(baudrate=self.rate,​ polarity=0, phase=0) 
-self.cs(0) +        self.cs(1) 
-self.spi.write(bytearray([cmd])) +        self.dc(0) 
-self.cs(1) +        self.cs(0) 
-def write_data(self,​ buf): +        self.spi.write(bytearray([cmd])) 
-self.spi.init(baudrate=self.rate,​ polarity=0, phase=0) +        self.cs(1) 
-self.cs(1) + 
-self.dc(1) +    ​def write_data(self,​ buf): 
-self.cs(0) +        self.spi.init(baudrate=self.rate,​ polarity=0, phase=0) 
-self.spi.write(buf) +        self.cs(1) 
-self.cs(1)+        self.dc(1) 
 +        self.cs(0) 
 +        self.spi.write(buf) 
 +        self.cs(1
 +</​code>​ 
 + 
 +### 6. 汉字的显示 
 +  * 支持英文字号8x8,16x16,24x24,32x32 
 +  * 支持中文字号16x16,24x24,32x32 
 +  * 封装lcd操作常用接口 
 + 
 +#### API 
 +<code python>​ 
 +def init_i2c(scl,​ sda, width, height): 
 +    """​ 
 +    初始化i2c接口 
 +    :param scl: i2c的时钟脚 
 +    :param sda: i2c的数据脚 
 +    :param width: oled屏幕的宽度像素 
 +    :param height: oled屏幕的高度像素 
 +    """​ 
 + 
 +def clear(): 
 +    """​清除屏幕"""​ 
 + 
 +def show(): 
 +    """​屏幕刷新显示"""​ 
 +    
 +def pixel(x, y): 
 +    """​画点"""​ 
 + 
 +def text(string,​ x_axis, y_axis, font_size):​ 
 +    """​显示字符串.注意字符串必须是英文或者数字"""​ 
 + 
 +def set_font(font,​ font_size):​ 
 +    """​ 
 +    设置中文字库.允许设置多个不同大小的字库 
 +    字库必须是字典,​格式示例:​ 
 +    font = { 
 +    0xe4bda0: 
 +        [0x08, 0x08, 0x08, 0x11, 0x11, 0x32, 0x34, 0x50, 0x91, 0x11, 0x12, 0x12, 0x14, 0x10, 0x10, 0x10, 0x80, 0x80, 
 +         0x80, 0xFE, 0x02, 0x04, 0x20, 0x20, 0x28, 0x24, 0x24, 0x22, 0x22, 0x20, 0xA0, 0x40], ​ # 你 
 +    0xe5a5bd: 
 +        [0x10, 0x10, 0x10, 0x10, 0xFC, 0x24, 0x24, 0x25, 0x24, 0x48, 0x28, 0x10, 0x28, 0x44, 0x84, 0x00, 0x00, 0xFC, 
 +         0x04, 0x08, 0x10, 0x20, 0x20, 0xFE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0x40]  # 好 
 +    } 
 +    """​ 
 + 
 +def text_cn(string,​ x_axis, y_axis, font_size):​ 
 +    """​显示中文字符.注意字符必须是utf-8编码"""​ 
 +</​code>​ 
 + 
 +#### 显示英文字符 
 +<code python>​ 
 +import ssd1306py as lcd 
 + 
 + 
 +lcd.init_i2c(22,​ 21, 128, 64) 
 +lcd.text('​font8x8',​ 0, 0, 8) 
 +lcd.text('​font16x16',​ 0, 20, 16) 
 +lcd.show() 
 + 
 +</​code>​ 
 + 
 +<code python>​ 
 +import ssd1306py as lcd 
 + 
 + 
 +lcd.init_i2c(22,​ 21, 128, 64) 
 +lcd.text('​font32x32',​ 0, 0, 32) 
 +lcd.show() 
 + 
 +</​code>​ 
 + 
 +#### 显示汉字 
 +可以使用在线转换工具查询:[[http://​www.mytju.com/​classcode/​tools/​encode_utf8.asp|在线转换工具]] 
 + 
 +比如以下示例,显示汉字“你好”。 
 +<code python>​ 
 +import ssd1306py as lcd 
 + 
 +lcd.init_i2c(22,​ 21, 128, 64) 
 + 
 +font16 = { 
 +    0xe4bda0: 
 +        [0x08, 0x08, 0x08, 0x11, 0x11, 0x32, 0x34, 0x50, 0x91, 0x11, 0x12, 0x12, 0x14, 0x10, 0x10, 0x10, 0x80, 0x80, 
 +         0x80, 0xFE, 0x02, 0x04, 0x20, 0x20, 0x28, 0x24, 0x24, 0x22, 0x22, 0x20, 0xA0, 0x40], ​ # 你 
 +    0xe5a5bd: 
 +        [0x10, 0x10, 0x10, 0x10, 0xFC, 0x24, 0x24, 0x25, 0x24, 0x48, 0x28, 0x10, 0x28, 0x44, 0x84, 0x00, 0x00, 0xFC, 
 +         0x04, 0x08, 0x10, 0x20, 0x20, 0xFE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0x40]  # 好 
 +
 + 
 +font24 = { 
 +    0xe4bda0: 
 +        [0x00, 0x01, 0x01, 0x03, 0x03, 0x02, 0x04, 0x04, 0x0E, 0x1C, 0x14, 0x24, 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 
 +         0x04, 0x05, 0x04, 0x06, 0x04, 0x00, 
 +         0x00, 0x00, 0x8C, 0x0C, 0x08, 0x18, 0x1F, 0x30, 0x21, 0x41, 0x41, 0x91, 0x19, 0x11, 0x31, 0x21, 0x41, 0x41, 
 +         0x81, 0x01, 0x11, 0x0F, 0x02, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x10, 0x00, 0x00, 0x00, 0x20, 0x10, 0x18, 0x0C, 0x0C, 0x06, 
 +         0x04, 0x00, 0x00, 0x00, 0x00, 0x00], ​ # 你 
 +    0xe5a5bd: 
 +        [0x00, 0x00, 0x06, 0x06, 0x06, 0x04, 0x04, 0x7F, 0x0C, 0x0C, 0x08, 0x08, 0x08, 0x18, 0x10, 0x11, 0x0D, 0x03, 
 +         0x02, 0x04, 0x18, 0x20, 0x40, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xC0, 0x40, 0x40, 0xC0, 0x80, 0xBF, 0x80, 0x80, 0x00, 0x00, 0x80, 
 +         0xC0, 0x60, 0x00, 0x07, 0x01, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x20, 0x40, 0x80, 0x80, 0x80, 0x84, 0xFE, 0x80, 0x80, 0x80, 0x80, 0x80, 
 +         0x80, 0x80, 0x80, 0x80, 0x00, 0x00]  # 好 
 +
 + 
 +font32 = { 
 +    0xe4bda0: 
 +        [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0D, 0x09, 0x11, 0x11, 0x21, 
 +         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
 +         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x40, 0x70, 0x60, 0xE0, 0xC0, 0xC1, 0x81, 0x03, 
 +         0x03, 0x86, 0x84, 0x8C, 0x88, 0x90, 
 +         0x81, 0x83, 0x83, 0x83, 0x86, 0x86, 0x8C, 0x88, 0x90, 0x90, 0xA0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 
 +         0x00, 0x60, 0xE0, 0xC0, 0xC0, 0x80, 
 +         0x80, 0xFF, 0x00, 0x10, 0x0C, 0x08, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
 +         0x08, 0x08, 0xF8, 0x38, 0x10, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFC, 0x18, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x80, 
 +         0x40, 0x20, 0x30, 0x18, 0x1C, 0x0C, 
 +         0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], ​ # 你 
 +    0xe5a5bd: 
 +        [0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x3F, 0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x04, 0x0C, 
 +         0x0C, 0x08, 0x08, 0x0E, 0x01, 0x00, 
 +         0x00, 0x01, 0x03, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x81, 0x80, 0x00, 0x08, 0xFC, 
 +         0x08, 0x08, 0x18, 0x18, 0x18, 0x18, 
 +         0x17, 0x30, 0x30, 0x30, 0x60, 0x60, 0xC0, 0xF0, 0xBC, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 +         0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 
 +         0x00, 0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFF, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
 +         0x06, 0x06, 0xFC, 0x1C, 0x08, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x70, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFC, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]  # 好 
 +
 + 
 +lcd.init_i2c(22,​ 21, 128, 64) 
 +lcd.set_font(font16,​ 16) 
 +lcd.set_font(font24,​ 24) 
 +lcd.set_font(font32,​ 32) 
 +lcd.text_cn('​你好',​ 0, 0, 16) 
 +lcd.text_cn('​你好',​ 40, 00, 24) 
 +lcd.text_cn('​你好',​ 0, 30, 32) 
 +lcd.show() 
 + 
 +</​code>​ 
 + 
 +### 7. 滚动屏幕的程序 
 +[[https://​randomnerdtutorials.com/​micropython-ssd1306-oled-scroll-shapes-esp32-esp8266/​|滚动屏幕]] 
 +<code python>​ 
 +oled_width = 128 
 +oled_height = 64 
 +oled = ssd1306.SSD1306_I2C(oled_width,​ oled_height,​ i2c) 
 + 
 +screen1_row1 = "​Screen 1, row 1" 
 +screen1_row2 = "​Screen 1, row 2" 
 +screen1_row3 = "​Screen 1, row 3" 
 + 
 +screen2_row1 = "​Screen 2, row 1" 
 +screen2_row2 = "​Screen 2, row 2" 
 + 
 +screen3_row1 = "​Screen 3, row 1" 
 + 
 +screen1 = [[0, 0 , screen1_row1],​ [0, 16, screen1_row2],​ [0, 32, screen1_row3]] 
 +screen2 = [[0, 0 , screen2_row1],​ [0, 16, screen2_row2]] 
 +screen3 = [[0, 40 , screen3_row1]] 
 + 
 +# Scroll in screen horizontally from left to right 
 +def scroll_in_screen(screen):​ 
 +  for i in range (0, oled_width+1,​ 4): 
 +    for line in screen: 
 +      oled.text(line[2],​ -oled_width+i,​ line[1]) 
 +    oled.show() 
 +    if i!= oled_width:​ 
 +      oled.fill(0) 
 + 
 +# Scroll out screen horizontally from left to right 
 +def scroll_out_screen(speed):​ 
 +  for i in range ((oled_width+1)/​speed):​ 
 +    for j in range (oled_height):​ 
 +      oled.pixel(i,​ j, 0) 
 +    oled.scroll(speed,​0) 
 +    oled.show() 
 + 
 +# Continuous horizontal scroll 
 +def scroll_screen_in_out(screen):​ 
 +  for i in range (0, (oled_width+1)*2,​ 1): 
 +    for line in screen: 
 +      oled.text(line[2],​ -oled_width+i,​ line[1]) 
 +    oled.show() 
 +    if i!= oled_width:​ 
 +      oled.fill(0) 
 + 
 +# Scroll in screen vertically 
 +def scroll_in_screen_v(screen):​ 
 +  for i in range (0, (oled_height+1),​ 1): 
 +    for line in screen: 
 +      oled.text(line[2],​ line[0], -oled_height+i+line[1]) 
 +    oled.show() 
 +    if i!= oled_height:​ 
 +      oled.fill(0) 
 + 
 +# Scroll out screen vertically 
 +def scroll_out_screen_v(speed):​ 
 +  for i in range ((oled_height+1)/​speed):​ 
 +    for j in range (oled_width):​ 
 +      oled.pixel(j,​ i, 0) 
 +    oled.scroll(0,​speed) 
 +    oled.show() 
 + 
 +# Continous vertical scroll 
 +def scroll_screen_in_out_v(screen):​ 
 +  for i in range (0, (oled_height*2+1),​ 1): 
 +    for line in screen: 
 +      oled.text(line[2],​ line[0], -oled_height+i+line[1]) 
 +    oled.show() 
 +    if i!= oled_height:​ 
 +      oled.fill(0) 
 + 
 +while True: 
 + 
 +  # Scroll in, stop, scroll out (horizontal) 
 +  scroll_in_screen(screen1) 
 +  sleep(2) 
 +  scroll_out_screen(4) 
 + 
 +  scroll_in_screen(screen2) 
 +  sleep(2) 
 +  scroll_out_screen(4) 
 + 
 +  scroll_in_screen(screen3) 
 +  sleep(2) 
 +  scroll_out_screen(4) 
 + 
 +  # Continuous horizontal scroll 
 +  scroll_screen_in_out(screen1) 
 +  scroll_screen_in_out(screen2) 
 +  scroll_screen_in_out(screen3) 
 + 
 +  # Scroll in, stop, scroll out (vertical) 
 +  scroll_in_screen_v(screen1) 
 +  sleep(2) 
 +  scroll_out_screen_v(4) 
 + 
 +  scroll_in_screen_v(screen2) 
 +  sleep(2) 
 +  scroll_out_screen_v(4) 
 + 
 +  scroll_in_screen_v(screen3) 
 +  sleep(2) 
 +  scroll_out_screen_v(4) 
 + 
 +  # Continuous verticall scroll 
 +  scroll_screen_in_out_v(screen1) 
 +  scroll_screen_in_out_v(screen2) 
 +  scroll_screen_in_out_v(screen3) 
 +</​code>​ 
 + 
 +### 8. 绘图 
 +使用[[https://​github.com/​adafruit/​micropython-adafruit-gfx/​blob/​master/​gfx.py|Adafruit GFX Arduino library to MicroPython]] 
 + 
 +<code python>​ 
 +# Port of Adafruit GFX Arduino library to MicroPython. 
 +# Based on: https://​github.com/​adafruit/​Adafruit-GFX-Library 
 +# Author: Tony DiCola (original GFX author Phil Burgess) 
 +# License: MIT License (https://​opensource.org/​licenses/​MIT) 
 + 
 + 
 +class GFX: 
 + 
 +    def __init__(self,​ width, height, pixel, hline=None, vline=None):​ 
 +        # Create an instance of the GFX drawing class. ​ You must pass in the 
 +        # following parameters:​ 
 +        #  - width = The width of the drawing area in pixels. 
 +        #  - height = The height of the drawing area in pixels. 
 +        #  - pixel = A function to call when a pixel is drawn on the display. 
 +        #            This function should take at least an x and y position 
 +        #            and then any number of optional color or other parameters. 
 +        #  You can also provide the following optional keyword argument to 
 +        #  improve the performance of drawing: 
 +        #  - hline = A function to quickly draw a horizontal line on the display. 
 +        #            This should take at least an x, y, and width parameter and 
 +        #            any number of optional color or other parameters. 
 +        #  - vline = A function to quickly draw a vertical line on the display. 
 +        #            This should take at least an x, y, and height paraemter and 
 +        #            any number of optional color or other parameters. 
 +        self.width = width 
 +        self.height = height 
 +        self._pixel = pixel 
 +        # Default to slow horizontal & vertical line implementations if no 
 +        # faster versions are provided. 
 +        if hline is None: 
 +            self.hline = self._slow_hline 
 +        else: 
 +            self.hline = hline 
 +        if vline is None: 
 +            self.vline = self._slow_vline 
 +        else: 
 +            self.vline = vline 
 + 
 +    def _slow_hline(self,​ x0, y0, width, *args, **kwargs):​ 
 +        # Slow implementation of a horizontal line using pixel drawing. 
 +        # This is used as the default horizontal line if no faster override 
 +        # is provided. 
 +        if y0 < 0 or y0 > self.height or x0 < -width or x0 > self.width:​ 
 +            return 
 +        for i in range(width):​ 
 +            self._pixel(x0+i,​ y0, *args, **kwargs) 
 + 
 +    def _slow_vline(self,​ x0, y0, height, *args, **kwargs):​ 
 +        # Slow implementation of a vertical line using pixel drawing. 
 +        # This is used as the default vertical line if no faster override 
 +        # is provided. 
 +        if y0 < -height or y0 > self.height or x0 < 0 or x0 > self.width:​ 
 +            return 
 +        for i in range(height):​ 
 +            self._pixel(x0,​ y0+i, *args, **kwargs) 
 + 
 +    def rect(self, x0, y0, width, height, *args, **kwargs):​ 
 +        # Rectangle drawing function. ​ Will draw a single pixel wide rectangle 
 +        # starting in the upper left x0, y0 position and width, height pixels in 
 +        # size. 
 +        if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width:​ 
 +            return 
 +        self.hline(x0,​ y0, width, *args, **kwargs) 
 +        self.hline(x0,​ y0+height-1,​ width, *args, **kwargs) 
 +        self.vline(x0,​ y0, height, *args, **kwargs) 
 +        self.vline(x0+width-1,​ y0, height, *args, **kwargs) 
 + 
 +    def fill_rect(self,​ x0, y0, width, height, *args, **kwargs):​ 
 +        # Filled rectangle drawing function. ​ Will draw a single pixel wide 
 +        # rectangle starting in the upper left x0, y0 position and width, height 
 +        # pixels in size. 
 +        if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width:​ 
 +            return 
 +        for i in range(x0, x0+width):​ 
 +            self.vline(i,​ y0, height, *args, **kwargs) 
 + 
 +    def line(self, x0, y0, x1, y1, *args, **kwargs):​ 
 +        # Line drawing function. ​ Will draw a single pixel wide line starting at 
 +        # x0, y0 and ending at x1, y1. 
 +        steep = abs(y1 - y0) > abs(x1 - x0) 
 +        if steep: 
 +            x0, y0 = y0, x0 
 +            x1, y1 = y1, x1 
 +        if x0 > x1: 
 +            x0, x1 = x1, x0 
 +            y0, y1 = y1, y0 
 +        dx = x1 - x0 
 +        dy = abs(y1 - y0) 
 +        err = dx // 2 
 +        ystep = 0 
 +        if y0 < y1: 
 +            ystep = 1 
 +        else: 
 +            ystep = -1 
 +        while x0 <= x1: 
 +            if steep: 
 +                self._pixel(y0,​ x0, *args, **kwargs) 
 +            else: 
 +                self._pixel(x0,​ y0, *args, **kwargs) 
 +            err -= dy 
 +            if err < 0: 
 +                y0 += ystep 
 +                err += dx 
 +            x0 += 1 
 + 
 +    def circle(self,​ x0, y0, radius, *args, **kwargs):​ 
 +        # Circle drawing function. ​ Will draw a single pixel wide circle with 
 +        # center at x0, y0 and the specified radius. 
 +        f = 1 - radius 
 +        ddF_x = 1 
 +        ddF_y = -2 * radius 
 +        x = 0 
 +        y = radius 
 +        self._pixel(x0,​ y0 + radius, *args, **kwargs) 
 +        self._pixel(x0,​ y0 - radius, *args, **kwargs) 
 +        self._pixel(x0 + radius, y0, *args, **kwargs) 
 +        self._pixel(x0 - radius, y0, *args, **kwargs) 
 +        while x < y: 
 +            if f >= 0: 
 +                y -= 1 
 +                ddF_y += 2 
 +                f += ddF_y 
 +            x += 1 
 +            ddF_x += 2 
 +            f += ddF_x 
 +            self._pixel(x0 + x, y0 + y, *args, **kwargs) 
 +            self._pixel(x0 - x, y0 + y, *args, **kwargs) 
 +            self._pixel(x0 + x, y0 - y, *args, **kwargs) 
 +            self._pixel(x0 - x, y0 - y, *args, **kwargs) 
 +            self._pixel(x0 + y, y0 + x, *args, **kwargs) 
 +            self._pixel(x0 - y, y0 + x, *args, **kwargs) 
 +            self._pixel(x0 + y, y0 - x, *args, **kwargs) 
 +            self._pixel(x0 - y, y0 - x, *args, **kwargs) 
 + 
 +    def fill_circle(self,​ x0, y0, radius, *args, **kwargs):​ 
 +        # Filled circle drawing function. ​ Will draw a filled circule with 
 +        # center at x0, y0 and the specified radius. 
 +        self.vline(x0,​ y0 - radius, 2*radius + 1, *args, **kwargs) 
 +        f = 1 - radius 
 +        ddF_x = 1 
 +        ddF_y = -2 * radius 
 +        x = 0 
 +        y = radius 
 +        while x < y: 
 +            if f >= 0: 
 +                y -= 1 
 +                ddF_y += 2 
 +                f += ddF_y 
 +            x += 1 
 +            ddF_x += 2 
 +            f += ddF_x 
 +            self.vline(x0 + x, y0 - y, 2*y + 1, *args, **kwargs) 
 +            self.vline(x0 + y, y0 - x, 2*x + 1, *args, **kwargs) 
 +            self.vline(x0 - x, y0 - y, 2*y + 1, *args, **kwargs) 
 +            self.vline(x0 - y, y0 - x, 2*x + 1, *args, **kwargs) 
 + 
 +    def triangle(self,​ x0, y0, x1, y1, x2, y2, *args, **kwargs):​ 
 +        # Triangle drawing function. ​ Will draw a single pixel wide triangle 
 +        # around the points (x0, y0), (x1, y1), and (x2, y2). 
 +        self.line(x0,​ y0, x1, y1, *args, **kwargs) 
 +        self.line(x1,​ y1, x2, y2, *args, **kwargs) 
 +        self.line(x2,​ y2, x0, y0, *args, **kwargs) 
 + 
 +    def fill_triangle(self,​ x0, y0, x1, y1, x2, y2, *args, **kwargs):​ 
 +        # Filled triangle drawing function. ​ Will draw a filled triangle around 
 +        # the points (x0, y0), (x1, y1), and (x2, y2). 
 +        if y0 > y1: 
 +            y0, y1 = y1, y0 
 +            x0, x1 = x1, x0 
 +        if y1 > y2: 
 +            y2, y1 = y1, y2 
 +            x2, x1 = x1, x2 
 +        if y0 > y1: 
 +            y0, y1 = y1, y0 
 +            x0, x1 = x1, x0 
 +        a = 0 
 +        b = 0 
 +        y = 0 
 +        last = 0 
 +        if y0 == y2: 
 +            a = x0 
 +            b = x0 
 +            if x1 < a: 
 +                a = x1 
 +            elif x1 > b: 
 +                b = x1 
 +            if x2 < a: 
 +                a = x2 
 +            elif x2 > b: 
 +                b = x2 
 +            self.hline(a,​ y0, b-a+1, *args, **kwargs) 
 +            return 
 +        dx01 = x1 - x0 
 +        dy01 = y1 - y0 
 +        dx02 = x2 - x0 
 +        dy02 = y2 - y0 
 +        dx12 = x2 - x1 
 +        dy12 = y2 - y1 
 +        if dy01 == 0: 
 +            dy01 = 1 
 +        if dy02 == 0: 
 +            dy02 = 1 
 +        if dy12 == 0: 
 +            dy12 = 1 
 +        sa = 0 
 +        sb = 0 
 +        if y1 == y2: 
 +            last = y1 
 +        else: 
 +            last = y1-1 
 +        for y in range(y0, last+1): 
 +            a = x0 + sa // dy01 
 +            b = x0 + sb // dy02 
 +            sa += dx01 
 +            sb += dx02 
 +            if a > b: 
 +                a, b = b, a 
 +            self.hline(a,​ y, b-a+1, *args, **kwargs) 
 +        sa = dx12 * (y - y1) 
 +        sb = dx02 * (y - y0) 
 +        while y <= y2: 
 +            a = x1 + sa // dy12 
 +            b = x0 + sb // dy02 
 +            sa += dx12 
 +            sb += dx02 
 +            if a > b: 
 +                a, b = b, a 
 +            self.hline(a,​ y, b-a+1, *args, **kwargs) 
 +            y += 1 
 +</​code>​ 
 + 
 + 
 +绘图示例: 
 +<code python>​ 
 +oled_width = 128 
 +oled_height = 64 
 +oled = ssd1306.SSD1306_I2C(oled_width,​ oled_height,​ i2c) 
 + 
 +graphics = gfx.GFX(oled_width,​ oled_height,​ oled.pixel) 
 + 
 +while True: 
 + 
 +  graphics.line(0,​ 0, 127, 20, 1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 +  graphics.rect(10,​ 10, 50, 30, 1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 +  graphics.fill_rect(10,​ 10, 50, 30, 1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 + 
 +  graphics.circle(64,​ 32, 10, 1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 +  graphics.fill_circle(64,​ 32, 10, 1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 +  graphics.triangle(10,​10,​55,​20,​5,​40,​1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0) 
 + 
 +  graphics.fill_triangle(10,​10,​55,​20,​5,​40,​1) 
 +  oled.show() 
 +  sleep(1) 
 +  oled.fill(0)
 </​code>​ </​code>​