1. 硬件准备与环境搭建第一次拿到树莓派Pico和0.96寸LCD屏幕时我对着密密麻麻的引脚有点懵。后来发现只要搞清楚几个关键点连接起来其实很简单。RP2040芯片内置了两个SPI控制器我们这次用的是SPI0接口。微雪这款LCD开发板用的是ST7735驱动芯片屏幕分辨率是160x80通过SPI协议通信。你需要准备的硬件清单树莓派Pico开发板RP2040芯片微雪0.96寸LCD开发板ST7735驱动杜邦线若干建议用彩色线区分功能USB数据线供电和烧录程序用接线时最容易出错的是引脚对应关系。根据我的实测经验这样连接最稳定LCD的SCLK接Pico的GP2SPI0时钟线LCD的MOSI接Pico的GP3SPI0数据输出LCD的DC接Pico的GP4数据/命令选择LCD的RST接Pico的GP5复位信号LCD的CS接Pico的GP1片选信号LCD的BLK接Pico的GP0背光控制开发环境我推荐使用Thonny IDE它内置了MicroPython支持对新手特别友好。安装完IDE后记得下载最新版的MicroPython固件通过USB烧录到Pico里。第一次使用时按住Pico上的BOOTSEL按钮再插USB线电脑上会出现一个U盘把固件拖进去就完成了。2. SPI通信基础与配置SPI协议听起来高大上其实就像几个人传纸条。主设备Pico是老师从设备LCD是学生SCLK是老师的拍手节奏MOSI是老师说的话MISO是学生的回答虽然我们这个LCD不需要回复。CS片选信号就像点名叫到谁谁才能听讲。在MicroPython中配置SPI比想象中简单。先看这段基础代码from machine import Pin, SPI spi SPI(0, baudrate20_000_000, polarity0, phase0, sckPin(2), mosiPin(3), misoNone) cs Pin(1, Pin.OUT) dc Pin(4, Pin.OUT) rst Pin(5, Pin.OUT) blk Pin(0, Pin.OUT)这里有几个关键参数需要注意baudrate通信速率ST7735最高支持26.7MHz但实际用20MHz更稳定polarity时钟极性0表示空闲时低电平phase时钟相位0表示第一个边沿采样miso设为None因为我们不需要接收数据我刚开始调试时遇到过屏幕花屏的问题后来发现是SPI模式设错了。ST7735要求模式0polarity0, phase0或模式3polarity1, phase1其他模式会导致通信异常。如果屏幕显示不正常第一个要检查的就是这两个参数。3. LCD屏幕初始化流程点亮屏幕不是一通电就能显示的需要按照严格的初始化序列。这就像唤醒一个装睡的人得按照特定步骤来。ST7735的初始化过程大约有20多条命令好在MicroPython可以封装成函数def init_lcd(): # 硬件复位 rst.value(0) time.sleep_ms(100) rst.value(1) time.sleep_ms(100) # 发送初始化命令序列 send_command(0x11) # 退出睡眠模式 time.sleep_ms(120) send_command(0xB1) # 帧率控制 send_data(bytearray([0x01, 0x2C, 0x2D])) # ...更多初始化命令 send_command(0x29) # 开启显示其中send_command和send_data是两个核心函数区别在于DC引脚的状态def send_command(cmd): dc.value(0) cs.value(0) spi.write(bytearray([cmd])) cs.value(1) def send_data(data): dc.value(1) cs.value(0) if isinstance(data, int): data bytearray([data]) spi.write(data) cs.value(1)我在调试时踩过一个坑忘记在每次SPI操作前后切换CS片选信号。这会导致命令无法正确执行屏幕要么没反应要么显示乱码。另一个常见问题是初始化时序不对每条命令之间需要适当的延时特别是退出睡眠模式的120ms等待绝对不能少。4. 图形显示与性能优化基础显示功能实现后就可以开始画点、线、图形了。最底层的操作是设置显示窗口然后填充像素def set_window(x, y, w, h): send_command(0x2A) # 列地址设置 send_data(x 8) send_data(x 0xFF) send_data((xw-1) 8) send_data((xw-1) 0xFF) send_command(0x2B) # 行地址设置 send_data(y 8) send_data(y 0xFF) send_data((yh-1) 8) send_data((yh-1) 0xFF) send_command(0x2C) # 写入显存绘制单个像素的函数虽然简单但直接调用效率很低。我优化后的方案是批量写入def draw_pixel(x, y, color): set_window(x, y, 1, 1) send_data(color 8) send_data(color 0xFF) def fill_rect(x, y, w, h, color): set_window(x, y, w, h) data bytearray(2 * w * h) for i in range(0, len(data), 2): data[i] color 8 data[i1] color 0xFF send_data(data)实际测试发现填充一个80x160的矩形单像素绘制需要320ms而批量写入仅需25ms。对于动画效果这个优化至关重要。显示中文时我建议使用取模软件生成字库然后通过缓存机制减少重复计算。5. 常见问题排查指南调试SPI设备时逻辑分析仪是最好帮手。我用的是20块钱的USB逻辑分析仪配合PulseView软件可以清晰看到SPI波形。常见问题有屏幕全白或全黑检查背光控制引脚是否使能测量RST复位信号是否正常确认电源电压在3.3V显示花屏或错位重新检查SPI模式设置确认初始化序列完整执行调整屏幕的偏移参数ST7735需要设置偏移量通信不稳定降低SPI时钟频率试试缩短连接线长度在时钟线上加10kΩ上拉电阻有个特别隐蔽的bug我花了半天才解决当GPIO同时用作SPI和其他功能时需要先禁用其他复用功能。比如GP2默认是UART0的TX如果不先禁用UARTSPI时钟信号会被干扰。解决方法是在初始化时加上uart machine.UART(0) uart.deinit() # 禁用UART06. 进阶应用与项目创意掌握了基础显示后可以尝试更酷炫的应用。比如用Pico的ADC读取电位器电压实时显示波形import uctypes from machine import ADC adc ADC(26) # GP26作为ADC输入 buf bytearray(160*2) # 一行像素的缓冲区 while True: val adc.read_u16() * 80 // 65536 # 转换为屏幕Y坐标 buf buf[2:] bytes([0xFF, 0xE0]) # 左移并添加新点(黄色) set_window(0, 0, 160, 1) send_data(buf) time.sleep_ms(10)另一个实用项目是制作便携式传感器显示器。我最近用BME280传感器和这个LCD做了一个迷你气象站代码结构如下import bme280 i2c I2C(0, sclPin(17), sdaPin(16)) bme bme280.BME280(i2ci2c) def update_display(): temp, pres, hum bme.read_compensated_data() fill_rect(0, 0, 160, 80, 0x0000) # 清屏 draw_text(fTemp: {temp:.1f}C, 10, 10) draw_text(fPres: {pres/100:.1f}hPa, 10, 30) draw_text(fHum: {hum:.1f}%, 10, 50) while True: update_display() time.sleep(5)这些项目用到的完整代码我都放在了GitHub上。遇到问题可以随时查看最新的调试笔记里面记录了我遇到的各种坑和解决方案。
树莓派Pico RP2040 SPI驱动0.96寸LCD实战解析
1. 硬件准备与环境搭建第一次拿到树莓派Pico和0.96寸LCD屏幕时我对着密密麻麻的引脚有点懵。后来发现只要搞清楚几个关键点连接起来其实很简单。RP2040芯片内置了两个SPI控制器我们这次用的是SPI0接口。微雪这款LCD开发板用的是ST7735驱动芯片屏幕分辨率是160x80通过SPI协议通信。你需要准备的硬件清单树莓派Pico开发板RP2040芯片微雪0.96寸LCD开发板ST7735驱动杜邦线若干建议用彩色线区分功能USB数据线供电和烧录程序用接线时最容易出错的是引脚对应关系。根据我的实测经验这样连接最稳定LCD的SCLK接Pico的GP2SPI0时钟线LCD的MOSI接Pico的GP3SPI0数据输出LCD的DC接Pico的GP4数据/命令选择LCD的RST接Pico的GP5复位信号LCD的CS接Pico的GP1片选信号LCD的BLK接Pico的GP0背光控制开发环境我推荐使用Thonny IDE它内置了MicroPython支持对新手特别友好。安装完IDE后记得下载最新版的MicroPython固件通过USB烧录到Pico里。第一次使用时按住Pico上的BOOTSEL按钮再插USB线电脑上会出现一个U盘把固件拖进去就完成了。2. SPI通信基础与配置SPI协议听起来高大上其实就像几个人传纸条。主设备Pico是老师从设备LCD是学生SCLK是老师的拍手节奏MOSI是老师说的话MISO是学生的回答虽然我们这个LCD不需要回复。CS片选信号就像点名叫到谁谁才能听讲。在MicroPython中配置SPI比想象中简单。先看这段基础代码from machine import Pin, SPI spi SPI(0, baudrate20_000_000, polarity0, phase0, sckPin(2), mosiPin(3), misoNone) cs Pin(1, Pin.OUT) dc Pin(4, Pin.OUT) rst Pin(5, Pin.OUT) blk Pin(0, Pin.OUT)这里有几个关键参数需要注意baudrate通信速率ST7735最高支持26.7MHz但实际用20MHz更稳定polarity时钟极性0表示空闲时低电平phase时钟相位0表示第一个边沿采样miso设为None因为我们不需要接收数据我刚开始调试时遇到过屏幕花屏的问题后来发现是SPI模式设错了。ST7735要求模式0polarity0, phase0或模式3polarity1, phase1其他模式会导致通信异常。如果屏幕显示不正常第一个要检查的就是这两个参数。3. LCD屏幕初始化流程点亮屏幕不是一通电就能显示的需要按照严格的初始化序列。这就像唤醒一个装睡的人得按照特定步骤来。ST7735的初始化过程大约有20多条命令好在MicroPython可以封装成函数def init_lcd(): # 硬件复位 rst.value(0) time.sleep_ms(100) rst.value(1) time.sleep_ms(100) # 发送初始化命令序列 send_command(0x11) # 退出睡眠模式 time.sleep_ms(120) send_command(0xB1) # 帧率控制 send_data(bytearray([0x01, 0x2C, 0x2D])) # ...更多初始化命令 send_command(0x29) # 开启显示其中send_command和send_data是两个核心函数区别在于DC引脚的状态def send_command(cmd): dc.value(0) cs.value(0) spi.write(bytearray([cmd])) cs.value(1) def send_data(data): dc.value(1) cs.value(0) if isinstance(data, int): data bytearray([data]) spi.write(data) cs.value(1)我在调试时踩过一个坑忘记在每次SPI操作前后切换CS片选信号。这会导致命令无法正确执行屏幕要么没反应要么显示乱码。另一个常见问题是初始化时序不对每条命令之间需要适当的延时特别是退出睡眠模式的120ms等待绝对不能少。4. 图形显示与性能优化基础显示功能实现后就可以开始画点、线、图形了。最底层的操作是设置显示窗口然后填充像素def set_window(x, y, w, h): send_command(0x2A) # 列地址设置 send_data(x 8) send_data(x 0xFF) send_data((xw-1) 8) send_data((xw-1) 0xFF) send_command(0x2B) # 行地址设置 send_data(y 8) send_data(y 0xFF) send_data((yh-1) 8) send_data((yh-1) 0xFF) send_command(0x2C) # 写入显存绘制单个像素的函数虽然简单但直接调用效率很低。我优化后的方案是批量写入def draw_pixel(x, y, color): set_window(x, y, 1, 1) send_data(color 8) send_data(color 0xFF) def fill_rect(x, y, w, h, color): set_window(x, y, w, h) data bytearray(2 * w * h) for i in range(0, len(data), 2): data[i] color 8 data[i1] color 0xFF send_data(data)实际测试发现填充一个80x160的矩形单像素绘制需要320ms而批量写入仅需25ms。对于动画效果这个优化至关重要。显示中文时我建议使用取模软件生成字库然后通过缓存机制减少重复计算。5. 常见问题排查指南调试SPI设备时逻辑分析仪是最好帮手。我用的是20块钱的USB逻辑分析仪配合PulseView软件可以清晰看到SPI波形。常见问题有屏幕全白或全黑检查背光控制引脚是否使能测量RST复位信号是否正常确认电源电压在3.3V显示花屏或错位重新检查SPI模式设置确认初始化序列完整执行调整屏幕的偏移参数ST7735需要设置偏移量通信不稳定降低SPI时钟频率试试缩短连接线长度在时钟线上加10kΩ上拉电阻有个特别隐蔽的bug我花了半天才解决当GPIO同时用作SPI和其他功能时需要先禁用其他复用功能。比如GP2默认是UART0的TX如果不先禁用UARTSPI时钟信号会被干扰。解决方法是在初始化时加上uart machine.UART(0) uart.deinit() # 禁用UART06. 进阶应用与项目创意掌握了基础显示后可以尝试更酷炫的应用。比如用Pico的ADC读取电位器电压实时显示波形import uctypes from machine import ADC adc ADC(26) # GP26作为ADC输入 buf bytearray(160*2) # 一行像素的缓冲区 while True: val adc.read_u16() * 80 // 65536 # 转换为屏幕Y坐标 buf buf[2:] bytes([0xFF, 0xE0]) # 左移并添加新点(黄色) set_window(0, 0, 160, 1) send_data(buf) time.sleep_ms(10)另一个实用项目是制作便携式传感器显示器。我最近用BME280传感器和这个LCD做了一个迷你气象站代码结构如下import bme280 i2c I2C(0, sclPin(17), sdaPin(16)) bme bme280.BME280(i2ci2c) def update_display(): temp, pres, hum bme.read_compensated_data() fill_rect(0, 0, 160, 80, 0x0000) # 清屏 draw_text(fTemp: {temp:.1f}C, 10, 10) draw_text(fPres: {pres/100:.1f}hPa, 10, 30) draw_text(fHum: {hum:.1f}%, 10, 50) while True: update_display() time.sleep(5)这些项目用到的完整代码我都放在了GitHub上。遇到问题可以随时查看最新的调试笔记里面记录了我遇到的各种坑和解决方案。