以 Raspberry Pi 的使用 (Python) 為例,可參考 Interfacing SSD1306 OLED Display with Raspberry Pi 的內容,該例引用了 Adafruit_SSD1306 程式模組。一般上,參照網路上的現有資源也就足夠,但本文興趣在如何綜合這些資源簡易的自訂一個驅動程式。
SSD1306 I2C bus data format |
查看命令表 (Command Table) 決定晶片的初始設定命令集,初步先定義一個 class 如下:
# SSD1306 class class SSD1306: DEV_ADDR = 0x3c CMDSET_INIT = (0xae, #display off 0x20,0, #horizontal addressing mode 0x40, #display start line from 0 0xa0, #column address 0 mapped to seg0 0xa8,0x3f, #set multiplex ratio to 64 0xc0, #scan from com0 0xd3,0, #vertical shift by com0 0xda,0x12, #alternative com pin configuration 0xd5,0x80, #display clock divide ratio, oscillator frequency 0xd9,0xf1, #pre-charge period 0xdb,0x30, #Vcomh deselect level 0x81,0x7f, #contrast control 0xa4, #output follows ram content 0xa6, #normal display 0x8d,0x14, #enable charge pump 0xaf) #display on def __init__(self): self.dev = i2c(self.DEV_ADDR, 1) self.command(self.CMDSET_INIT) def command(self, cmdset): d = [] for c in cmdset: d.extend((0x80,c)) self.dev.write(d)
若想使用 smbus 模組來傳送 I2C 介面資料會遇到 32 bytes 限制的問題,可參考 smbus i2c read/write more than 32 bytes 內所提及的方法。
處理圖形顯示資料可引用 PIL 模組的諸多功能:
from PIL import Image,ImageDraw,ImageFont在初始時中添加相關的物件:
# self.img = Image.new('1',(128,64)) self.draw = ImageDraw.Draw(self.img) self.font = ImageFont.load_default() self.tfont = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc',16)
實作有關顯示功能的程式:
# def display(self, on=None): if on: self.command([0xaf]) return elif on is False: self.command([0xae]) return gd = [0x40] gd.extend([0] *(128*8)) p = self.img.load() for pg in range(8): for col in range(128): b = 0 for i in range(8): b = b >> 1 b |= 0 if p[(col, pg*8 +i)] == 0 else 0x80 gd[pg*128 +col+1] = b self.command([0x21,0,127,0x22,0,7]) self.dev.write(gd) def clear(self): self.draw.rectangle((0,0,127,63),outline=0,fill=0) self.display() def text(self,pos,msg,ttc=False): self.draw.text(pos,msg,font=self.tfont if ttc else self.font, fill=255) def close(self): self.display(on=False) self.dev.close()
嘗試做捲動功能:
# def start_scroll(self,dir,pg_start,pg_end,rows=None): cmd = [0x29] if rows else [0x26] cmd[0] += dir cmd.extend([0,pg_start,0,pg_end,rows,0x2f] if rows else [0,pg_start,0,pg_end,0,0xff,0x2f]) self.stop_scroll() self.command(cmd) def stop_scroll(self): self.command([0x2e]) self.display()
此時,可以來一個簡易的測試:
# disp = SSD1306() time.sleep(3) disp.draw.rectangle((0,0,127,63),outline=1,fill=0) disp.text((8,8),'SSD1306 Testing...') disp.display() time.sleep(5) disp.draw.rectangle((0,0,127,63),outline=0,fill=0) disp.text((8,0),u'三山半落青天外',ttc=True) disp.text((8,16),u'二水中分白鷺洲',ttc=True) disp.text((8,32),u'總為浮雲能蔽日',ttc=True) disp.text((8,48),u'長安不見使人愁',ttc=True) disp.display() time.sleep(5) disp.start_scroll(0, 0, 7) time.sleep(10) disp.start_scroll(1, 0, 7, 1) time.sleep(10) disp.stop_scroll() time.sleep(10) disp.close()
測試的結果:
沒有留言:
張貼留言