Raspberry Pi Pico の SPI
RP2040 には、2チャンネルの独立した SPI コントローラ(SPI0 / SPI1)を持っており、Raspberry Pi Pico では GP[0] ~ GP[27] の各端子から利用可能になっています. 今回はこの機能を使って、液晶ディスプレイの接続と EEPROM の読み書きを試してみました.ATM0130B3 液晶ディスプレイを接続する
ATM0130B3 は、240x(RGB)x240 1.3インチサイズのフルカラーグラフィック液晶ディスプレイです.今回は秋月電子の2.54mm ピッチ変換基板付きのコントロールキットを使用して接続します.ピッチ変換基板上にはレベル変換の回路も搭載されているため、Raspberry Pi Pico とそのまま接続可能です.ハードウェア接続
下に Raspberry Pi Pico の I/O 端子と ATM0130B3 変換基板間の配線を示します.必要部品はすべて変換基板上に実装されていますので、SPI の4端子 /CS, D/C, RES の各信号線、電源・GND 端子をそれぞれ接続します.ソフトウェア(Micro Python コード)
これまでと同様、Micro Python を使用します. MicroPython ライブラリのドキュメントを参照し、シリアルペリフェラルインタフェース バスプロトコル(SPI)に使う SPI クラスの使用例を確認しながらコーディングしていきます.# SPI の設定 spi = SPI(0, baudrate=8000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3)) # buf に含まれる bytes 型オブジェクトをデバイスに書き込む spi.write(buff) # read_buf に読込みながら write_buf の bytes 型オブジェクトを書き込む # 両バッファは同じでも異なっていても良いが、同じ長さでなければならない spi.write_readinto(buff, buff)
秋月電子のサイトにあるサンプルコードを参考に Micro Python で記述していきます./CS, D/C, RES の各信号線は GPIO として制御します.
from machine import Pin from machine import SPI import time chars = [0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x40, 0x10, 0x00, 0x52, 0x94, 0x00, 0x00, 0x00, 0x52, 0x95, 0xF5, 0x7D, 0x4A, 0x23, 0xE8, 0xE2, 0xF8, 0x80, 0xC6, 0x44, 0x44, 0x4C, 0x60, 0x64, 0xA8, 0x8A, 0xC9, 0xA0, 0x61, 0x10, 0x00, 0x00, 0x00, 0x11, 0x10, 0x84, 0x10, 0x40, 0x41, 0x04, 0x21, 0x11, 0x00, 0x01, 0x2A, 0xEA, 0x90, 0x00, 0x01, 0x08, 0xE2, 0x10, 0x00, 0x00, 0x00, 0x06, 0x11, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x44, 0x44, 0x40, 0x00, 0x74, 0x67, 0x5C, 0xC5, 0xC0, 0x23, 0x08, 0x42, 0x11, 0xC0, 0x74, 0x42, 0x22, 0x23, 0xE0, 0xF8, 0x88, 0x20, 0xC5, 0xC0, 0x11, 0x95, 0x2F, 0x88, 0x40, 0xFC, 0x3C, 0x10, 0xC5, 0xC0, 0x32, 0x11, 0xE8, 0xC5, 0xC0, 0xF8, 0x44, 0x44, 0x21, 0x00, 0x74, 0x62, 0xE8, 0xC5, 0xC0, 0x74, 0x62, 0xF0, 0x89, 0x80, 0x03, 0x18, 0x06, 0x30, 0x00, 0x03, 0x18, 0x06, 0x11, 0x00, 0x11, 0x11, 0x04, 0x10, 0x40, 0x00, 0x3E, 0x0F, 0x80, 0x00, 0x41, 0x04, 0x11, 0x11, 0x00, 0x74, 0x42, 0x22, 0x00, 0x80, 0x74, 0x42, 0xDA, 0xD5, 0xC0, 0x74, 0x63, 0x1F, 0xC6, 0x20, 0xF4, 0x63, 0xE8, 0xC7, 0xC0, 0x74, 0x61, 0x08, 0x45, 0xC0, 0xE4, 0xA3, 0x18, 0xCB, 0x80, 0xFC, 0x21, 0xE8, 0x43, 0xE0, 0xFC, 0x21, 0xE8, 0x42, 0x00, 0x74, 0x61, 0x78, 0xC5, 0xE0, 0x8C, 0x63, 0xF8, 0xC6, 0x20, 0x71, 0x08, 0x42, 0x11, 0xC0, 0x38, 0x84, 0x21, 0x49, 0x80, 0x8C, 0xA9, 0x8A, 0x4A, 0x20, 0x84, 0x21, 0x08, 0x43, 0xE0, 0x8E, 0xEB, 0x58, 0xC6, 0x20, 0x8C, 0x73, 0x59, 0xC6, 0x20, 0x74, 0x63, 0x18, 0xC5, 0xC0, 0xF4, 0x63, 0xE8, 0x42, 0x00, 0x74, 0x63, 0x1A, 0xC9, 0xA0, 0xF4, 0x63, 0xEA, 0x4A, 0x20, 0x74, 0x20, 0xE0, 0x87, 0xC0, 0xF9, 0x08, 0x42, 0x10, 0x80, 0x8C, 0x63, 0x18, 0xC5, 0xC0, 0x8C, 0x63, 0x18, 0xA8, 0x80, 0x8C, 0x63, 0x5A, 0xD5, 0x40, 0x8C, 0x54, 0x45, 0x46, 0x20, 0x8C, 0x62, 0xA2, 0x10, 0x80, 0xF8, 0x44, 0x44, 0x43, 0xE0, 0x72, 0x10, 0x84, 0x21, 0xC0, 0x8A, 0xBE, 0x4F, 0x90, 0x80, 0x70, 0x84, 0x21, 0x09, 0xC0, 0x22, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x41, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x17, 0xC5, 0xE0, 0x84, 0x2D, 0x98, 0xC7, 0xC0, 0x00, 0x1D, 0x08, 0x45, 0xC0, 0x08, 0x5B, 0x38, 0xC5, 0xE0, 0x00, 0x1D, 0x1F, 0xC1, 0xC0, 0x32, 0x51, 0xC4, 0x21, 0x00, 0x03, 0xE3, 0x17, 0x85, 0xC0, 0x84, 0x2D, 0x98, 0xC6, 0x20, 0x20, 0x18, 0x42, 0x11, 0xC0, 0x10, 0x0C, 0x21, 0x49, 0x80, 0x84, 0x25, 0x4C, 0x52, 0x40, 0x61, 0x08, 0x42, 0x11, 0xC0, 0x00, 0x35, 0x5A, 0xC6, 0x20, 0x00, 0x2D, 0x98, 0xC6, 0x20, 0x00, 0x1D, 0x18, 0xC5, 0xC0, 0x00, 0x3D, 0x1F, 0x42, 0x00, 0x00, 0x1B, 0x37, 0x84, 0x20, 0x00, 0x2D, 0x98, 0x42, 0x00, 0x00, 0x1D, 0x07, 0x07, 0xC0, 0x42, 0x38, 0x84, 0x24, 0xC0, 0x00, 0x23, 0x18, 0xCD, 0xA0, 0x00, 0x23, 0x18, 0xA8, 0x80, 0x00, 0x23, 0x1A, 0xD5, 0x40, 0x00, 0x22, 0xA2, 0x2A, 0x20, 0x00, 0x23, 0x17, 0x85, 0xC0, 0x00, 0x3E, 0x22, 0x23, 0xE0, 0x11, 0x08, 0x82, 0x10, 0x40, 0x21, 0x08, 0x42, 0x10, 0x80, 0x41, 0x08, 0x22, 0x11, 0x00, 0x00, 0x11, 0x51, 0x00, 0x00] spi = SPI(0, baudrate=8000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3)) print(spi) cs = Pin(5, Pin.OUT) dc = Pin(14, Pin.OUT) res = Pin(15, Pin.OUT) led = Pin(25, Pin.OUT) fig_color = 0 cxahar_color = 0 char_color_bg = 0 char_x = 0 char_y = 0 queue = [0, 0, 0, 0, 0] def putPixel(color): writeData(color >> 8) writeData(color & 0xFF) def setWindow(x, y, w, h): writeReg(0x2A) writeData(0x00) writeData(x) writeData(0x00) writeData(x + w - 1) writeReg(0x2B) writeData(0x00) writeData(y) writeData(0x00) writeData(y + h - 1) writeReg(0x2c) def writeCharQueue(): global char_x global char_y global char_color global char_color_bg setWindow(char_x, char_y, 5, 8); for i in range(5): for j in range(8): if ((queue[i] & (0x80 >> j)) > 0): putPixel(char_color) else: putPixel(char_color_bg) setWindow(char_x + 5, char_y, 1, 8); for i in range(8): putPixel(char_color_bg); def setCharQueue(ch): global chars if ((ord(ch) >= 0x20) and (ord(ch) <= 0x7E)) : c = ord(ch) - 0x20 for i in range(5) : queue[i] = chars[5 * c + i] else: for i in range(5) : queue[i] = 0xFF #print(str(queue)) def print_str(str): global char_x global char_y if (char_x > 235): char_x = 0 char_y += 8 if (char_y > 232): char_x = 0 char_y = 0 else : index = 0 for item in str: setCharQueue(str[index]) cs.value(0) writeCharQueue() char_x += 6 cs.value(1) index += 1 def setCharPlace(x, y): global char_x global char_y char_x = x; char_y = y; def setFigColor(r, g, b): global fig_color color = 0; color = b >> 3; color |= ((g & 0xFC) << 3) color |= ((r & 0xF8) << 8) fig_color = color #print('figcolor : ' + hex(fig_color)) def setCharColor(r, g, b): global char_color color = 0; color = b >> 3; color |= ((g & 0xFC) << 3) color |= ((r & 0xF8) << 8) char_color = color #print('char_color : ' + hex(char_color)) def setCharColorBG(r, g, b): global char_color_bg color = 0; color = b >> 3; color |= ((g & 0xFC) << 3) color |= ((r & 0xF8) << 8) char_color_bg = color #print('char_color_bg : ' + hex(char_color_bg)) def writeReg(reg): dc.value(0) buff = bytearray(1) buff[0] = reg spi.write(buff) #print('writeReg ' + hex(buff[0])) def writeData(data): dc.value(1) buff = bytearray(1) buff[0] = data spi.write(buff) #print('writeData ' + hex(buff[0])) def drawRectangle(x, y, w, h): global fig_color led.value(1) loop = w * h colorH = fig_color >> 8 colorL = fig_color & 0x00FF #print('ColorH = ' + hex(colorH)) #print('ColorL = ' + hex(colorL)) #color = 240 #colorH = 255 #colorL = 255 cs.value(0) # set window writeReg(0x2A) writeData(0x00) writeData(x) writeData(0x00) writeData(x + w - 1) writeReg(0x2B) writeData(0x00) writeData(y) writeData(0x00) writeData(y + h - 1) writeReg(0x2c); dc.value(1) for i in range(loop): buff = bytearray(1) buff[0] = colorH spi.write(buff) buff[0] = colorL spi.write(buff) #spi.write(hex(colorH)) #spi.write(hex(colorL)) #writeData(colorH) #writeData(colorL) #print(i) cs.value(1) led.value(0) print('draw finished') def begin(): cs.value(1) res.value(1) time.sleep(0.02) res.value(0) time.sleep(0.02) res.value(1) time.sleep(0.02) print('Reset') cs.value(0) led.value(1) writeReg(0x11) time.sleep(0.1) writeReg(0x36) writeData(0x00) writeReg(0x3A) writeData(0x55) ##--------------------------------ST7789V Frame rate writeReg(0xb2) writeData(0x0c) writeData(0x0c) writeData(0x00) writeData(0x33) writeData(0x33) time.sleep(0.002) writeReg(0xb7) writeData(0x75) time.sleep(0.002) ##---------------------------------ST7789V Power writeReg(0xc2) writeData(0x01) time.sleep(0.002) writeReg(0xc3) writeData(0x10) time.sleep(0.002) writeReg(0xc4) writeData(0x20) time.sleep(0.002) writeReg(0xc6) writeData(0x0f) writeReg(0xb0) writeData(0x00) writeData(0xf0); # RRRR RGGGG GGGB BBBB time.sleep(0.002) writeReg(0xD0) writeData(0xA4) writeData(0xA1) time.sleep(0.002) ## --------------------------------ST7789V gamma writeReg(0x21) time.sleep(0.002) writeReg(0xbb) writeData(0x3b) time.sleep(0.002) writeReg(0xE0) # Set Gamma writeData(0xF0) writeData(0x0b) writeData(0x11) writeData(0x0e) writeData(0x0d) writeData(0x19) writeData(0x36) writeData(0x33) writeData(0x4b) writeData(0x07) writeData(0x14) writeData(0x14) writeData(0x2c) writeData(0x2e) time.sleep(0.002) writeReg(0xE1) # Set Gamma writeData(0xF0) writeData(0x0d) writeData(0x12) writeData(0x0b) writeData(0x09) writeData(0x03) writeData(0x32) writeData(0x44) writeData(0x48) writeData(0x39) writeData(0x16) writeData(0x16) writeData(0x2d) writeData(0x30) writeReg(0x2A) writeData(0x00) writeData(0x00) writeData(0x00) writeData(0xEF) writeReg(0x2B) writeData(0x00) writeData(0x00) writeData(0x00) writeData(0xEF) writeReg(0x29) # Display on time.sleep(0.002) writeReg(0x2c) cs.value(1) led.value(0) print('Init finished') def colorBar(): for i in range(8): g = 255 * (1 - ((i & 0x04) >> 2)) r = 255 * (1 - ((i & 0x02) >> 1)) b = 255 * (1 - ((i & 0x01))) setFigColor(r, g, b) drawRectangle(i * 30, 0, 30, 180) for i in range(240): setFigColor(i, i, i) drawRectangle(i, 180, 1, 60) begin() setFigColor(0, 0, 0) drawRectangle(0, 0, 240, 240) colorBar() setCharPlace(0, 160) setCharColor(0, 0, 0) setCharColorBG(255, 255, 255) print_str('https://mytoolbox.tech/tec')
実行結果
実行結果を下に示します.カラーバーと文字列が正しく表示されました.EEPROM を接続する
続いては SPI インターフェースのシリアル EEPROM との接続を試してみます.使用するデバイスは ROHM 社製 BR25L320 デバイスです. (下の写真はピッチ変換基板に実装した状態です)ハードウェア接続
下に Raspberry Pi Pico の I/O 端子と BR25L320 間の配線を示します.SPI と電源・GND 端子のほか、書込み保護制御用の /WP, HOLD 信号を Raspberry Pi Pico の GP に接続します.ソフトウェア(Micro Python コード)
from machine import Pin from machine import SPI import time spi = SPI(0, baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3)) print(spi) cs = Pin(5, Pin.OUT) wp = Pin(0, Pin.OUT) hold = Pin(1, Pin.OUT) cs.value(1) wp.value(0) hold.value(0) def enablewrite(): cs.value(0) wp.value(1) hold.value(1) wen = bytearray(1) wen[0] = 0x06 spi.write(wen) print("Write enabled(" + hex(wen[0]) + ").") cs.value(1) wp.value(0) hold.value(0) def disablewrite(): cs.value(0) wp.value(1) hold.value(1) wen = bytearray(1) wen[0] = 0x04 spi.write(wen) print("Write disabled(" + hex(wen[0]) + ").") cs.value(1) wp.value(0) hold.value(0) def writeData(addr, data): cs.value(0) wp.value(1) hold.value(1) buff = bytearray(4) buff[0] = 0x02 buff[1] = (addr & 0xFF00) >> 8 buff[2] = (addr & 0x00FF) buff[3] = (data & 0xFF) spi.write(buff) print("W : " + hex(buff[0])) print("W : " + hex(buff[1])) print("W : " + hex(buff[2])) print("W : " + hex(buff[3])) cs.value(1) wp.value(0) hold.value(0) def readData(addr): cs.value(0) wp.value(1) hold.value(1) buff = bytearray(4) buff[0] = 0x03 buff[1] = (addr & 0xFF00) >> 8 buff[2] = (addr & 0x00FF) buff[3] = 0x00 spi.write_readinto(buff, buff) print("R : " + hex(buff[3])) cs.value(1) wp.value(0) hold.value(0) enablewrite() writeData(0x0A1B, 0xAA) disablewrite() print("----------------") readData(0x0A1B) print("----------------")
実行結果
書き込み時、読み出し時それぞれの波形を示します.
参考
ATM0130B3 使用フルカラー液晶コントロールキットMicroPython ライブラリのドキュメント
BR25L320 デバイス
1件のコメント