SPI on the Raspberry Pi Pico
The RP2040 has two independent SPI controllers (SPI0 / SPI1), available on the Raspberry Pi Pico from GP[0] to GP[27] pins. In this article, I tried to use this feature to connect the LCD display and read/write the EEPROM.Connecting the ATM0130B3 LCD
The ATM0130B3 is a 240x(RGB)x240 1.3-inch full-color graphic LCD. This time, we used Akizuki’s control kit with 2.54mm pitch conversion board to connect it. The pitch conversion board also has a level conversion circuit, so it can be connected directly to the Raspberry Pi Pico.Hardware connections
The following figure shows the wiring between Raspberry Pi Pico’s I/O terminals and the ATM0130B3 conversion board. All the necessary components are mounted on the board. Connect the four SPI pins /CS, D/C, and RES, and the power supply and GND pins, respectively.Software (Micro Python code)
We will use Micro Python as before, referring to the MicroPython library documentation for examples of using the SPI class for the Serial Peripheral Interface Bus Protocol (SPI).# Setup the SPI spi = SPI(0, baudrate=8000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3)) # Write the bytes type object contained in buf to the device spi.write(buff) # write bytes object in write_buf while reading in read_buf # Both buffers can be the same or different, but must have the same length spi.write_readinto(buff, buff)
The /CS, D/C, and RES signal lines are controlled as GPIOs.
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')
Results
The execution result is shown below. The color bar and character string are displayed correctly.Connecting EEPROM
Next, let’s try to connect to serial EEPROM with SPI interface. The device used is the BR25L320 device manufactured by ROHM.(The picture below shows the device mounted on the pitch conversion board.)Hardware connection
Below is the wiring between the I/O pins of the Raspberry Pi Pico and the BR25L320, including the SPI, power and GND pins, and the /WP and HOLD signals for write protection control.Software (Micro Python code)
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("----------------")
Results
The following are the waveforms for writing and reading.
References
Full Color LCD Control Kit using ATM0130B3 (JAPANESE site)MicroPython Library Documentation (JAPANESE site)
BR25L320 Devices