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 クラスの使用例を確認しながらコーディングしていきます.
1
2
3
4
5
6
7
8
9
# 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 として制御します.
raspi_pico_spi1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
from machine import Pin
from machine import SPI
import time
 
chars = [0x00, 0x00, 0x00, 0x00, 0x000x21, 0x08, 0x40, 0x10, 0x000x52, 0x94, 0x00, 0x00, 0x000x52, 0x95, 0xF5, 0x7D, 0x4A0x23, 0xE8, 0xE2, 0xF8, 0x800xC6, 0x44, 0x44, 0x4C, 0x600x64, 0xA8, 0x8A, 0xC9, 0xA00x61, 0x10, 0x00, 0x00, 0x000x11, 0x10, 0x84, 0x10, 0x400x41, 0x04, 0x21, 0x11, 0x000x01, 0x2A, 0xEA, 0x90, 0x000x01, 0x08, 0xE2, 0x10, 0x000x00, 0x00, 0x06, 0x11, 0x000x00, 0x01, 0xF0, 0x00, 0x000x00, 0x00, 0x00, 0x63, 0x000x00, 0x44, 0x44, 0x40, 0x000x74, 0x67, 0x5C, 0xC5, 0xC00x23, 0x08, 0x42, 0x11, 0xC00x74, 0x42, 0x22, 0x23, 0xE00xF8, 0x88, 0x20, 0xC5, 0xC0,
      0x11, 0x95, 0x2F, 0x88, 0x400xFC, 0x3C, 0x10, 0xC5, 0xC00x32, 0x11, 0xE8, 0xC5, 0xC00xF8, 0x44, 0x44, 0x21, 0x000x74, 0x62, 0xE8, 0xC5, 0xC00x74, 0x62, 0xF0, 0x89, 0x800x03, 0x18, 0x06, 0x30, 0x000x03, 0x18, 0x06, 0x11, 0x000x11, 0x11, 0x04, 0x10, 0x400x00, 0x3E, 0x0F, 0x80, 0x000x41, 0x04, 0x11, 0x11, 0x000x74, 0x42, 0x22, 0x00, 0x800x74, 0x42, 0xDA, 0xD5, 0xC00x74, 0x63, 0x1F, 0xC6, 0x200xF4, 0x63, 0xE8, 0xC7, 0xC00x74, 0x61, 0x08, 0x45, 0xC00xE4, 0xA3, 0x18, 0xCB, 0x800xFC, 0x21, 0xE8, 0x43, 0xE00xFC, 0x21, 0xE8, 0x42, 0x000x74, 0x61, 0x78, 0xC5, 0xE0,
      0x8C, 0x63, 0xF8, 0xC6, 0x200x71, 0x08, 0x42, 0x11, 0xC00x38, 0x84, 0x21, 0x49, 0x800x8C, 0xA9, 0x8A, 0x4A, 0x200x84, 0x21, 0x08, 0x43, 0xE00x8E, 0xEB, 0x58, 0xC6, 0x200x8C, 0x73, 0x59, 0xC6, 0x200x74, 0x63, 0x18, 0xC5, 0xC00xF4, 0x63, 0xE8, 0x42, 0x000x74, 0x63, 0x1A, 0xC9, 0xA00xF4, 0x63, 0xEA, 0x4A, 0x200x74, 0x20, 0xE0, 0x87, 0xC00xF9, 0x08, 0x42, 0x10, 0x800x8C, 0x63, 0x18, 0xC5, 0xC00x8C, 0x63, 0x18, 0xA8, 0x800x8C, 0x63, 0x5A, 0xD5, 0x400x8C, 0x54, 0x45, 0x46, 0x200x8C, 0x62, 0xA2, 0x10, 0x800xF8, 0x44, 0x44, 0x43, 0xE00x72, 0x10, 0x84, 0x21, 0xC0,
      0x8A, 0xBE, 0x4F, 0x90, 0x800x70, 0x84, 0x21, 0x09, 0xC00x22, 0xA2, 0x00, 0x00, 0x000x00, 0x00, 0x00, 0x03, 0xE00x41, 0x04, 0x00, 0x00, 0x000x00, 0x1C, 0x17, 0xC5, 0xE00x84, 0x2D, 0x98, 0xC7, 0xC00x00, 0x1D, 0x08, 0x45, 0xC00x08, 0x5B, 0x38, 0xC5, 0xE00x00, 0x1D, 0x1F, 0xC1, 0xC00x32, 0x51, 0xC4, 0x21, 0x000x03, 0xE3, 0x17, 0x85, 0xC00x84, 0x2D, 0x98, 0xC6, 0x200x20, 0x18, 0x42, 0x11, 0xC00x10, 0x0C, 0x21, 0x49, 0x800x84, 0x25, 0x4C, 0x52, 0x400x61, 0x08, 0x42, 0x11, 0xC00x00, 0x35, 0x5A, 0xC6, 0x200x00, 0x2D, 0x98, 0xC6, 0x200x00, 0x1D, 0x18, 0xC5, 0xC0,
      0x00, 0x3D, 0x1F, 0x42, 0x000x00, 0x1B, 0x37, 0x84, 0x200x00, 0x2D, 0x98, 0x42, 0x000x00, 0x1D, 0x07, 0x07, 0xC00x42, 0x38, 0x84, 0x24, 0xC00x00, 0x23, 0x18, 0xCD, 0xA00x00, 0x23, 0x18, 0xA8, 0x800x00, 0x23, 0x1A, 0xD5, 0x400x00, 0x22, 0xA2, 0x2A, 0x200x00, 0x23, 0x17, 0x85, 0xC00x00, 0x3E, 0x22, 0x23, 0xE00x11, 0x08, 0x82, 0x10, 0x400x21, 0x08, 0x42, 0x10, 0x800x41, 0x08, 0x22, 0x11, 0x000x00, 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)
 
実行結果
実行結果を下に示します.カラーバーと文字列が正しく表示されました.
カラーバー

EEPROM を接続する

続いては SPI インターフェースのシリアル EEPROM との接続を試してみます.使用するデバイスは ROHM 社製 BR25L320 デバイスです. (下の写真はピッチ変換基板に実装した状態です)
BR25L320
ハードウェア接続
下に Raspberry Pi Pico の I/O 端子と BR25L320 間の配線を示します.SPI と電源・GND 端子のほか、書込み保護制御用の /WP, HOLD 信号を Raspberry Pi Pico の GP に接続します.
回路

実体接続

ソフトウェア(Micro Python コード)
raspi_pico_spi2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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件のコメント

返信を残す

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