以 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()
測試的結果:


沒有留言:
張貼留言