Raspberry Pi Pico を使ってみた [6] – Micro Python で SPI 通信


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 とそのまま接続可能です.
1.3 インチフルカラーグラフィック液晶ディスプレイ
ハードウェア接続
下に 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 デバイスです. (下の写真はピッチ変換基板に実装した状態です)
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("----------------")

実行結果
実行結果

書き込み時、読み出し時それぞれの波形を示します.
Pulse View 波形(Write Enable コマンド発行)
Pulse View 波形(Write)
Pulse View 波形(Write Disable コマンド発行)
Pulse View 波形(Read)

参考

ATM0130B3 使用フルカラー液晶コントロールキット
MicroPython ライブラリのドキュメント
BR25L320 デバイス

1件のコメント

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です