1. 项目概述与环境搭建
各位同学好,我是你们这门课的讲师。做嵌入式这些年,我接触过不少显示方案,但说实话,I2C 接口的 LCD 驱动一直是我个人很偏爱的一个入门项目。为什么?因为它麻雀虽小五脏俱全——既有通信协议,又有硬件控制,还能立刻看到效果。
这一章,我们先打好基础。把 I2C 是什么、LCD1602 怎么工作的、开发环境怎么搭,一次性理清楚。
1.1 什么是 I2C 协议?
I2C,全称 Inter-Integrated Circuit,是飞利浦公司(现在的 NXP)在 80 年代推出的。说白了,就是让芯片之间能互相说话的一种总线标准。
它只有两根线:
- SDA(串行数据线)—— 传数据用的
- SCL(串行时钟线)—— 提供时钟节拍
我刚开始学的时候,总觉得两根线能传数据很神奇。后来自己用逻辑分析仪抓了一次波形,才真正理解——时钟线负责打拍子,数据线在拍子间隙里传 0 和 1,就这么简单。
I2C 的核心特点:
- 主从架构:一个主设备(比如树莓派 Pico)可以挂多个从设备(比如 LCD、传感器)
- 每个从设备有唯一地址,7 位或 10 位
- 标准模式 100 kbps,快速模式 400 kbps
- 支持多主机,但咱们项目只用单主机
你想想看,如果每个外设都单独拉一堆 GPIO 引脚,板子早就乱成蜘蛛网了。I2C 用两根线就能挂几十个设备,这就是它经久不衰的原因。
1.2 LCD1602 是怎么工作的?
LCD1602,名字就告诉你了——16 个字符 × 2 行。每个字符由 5×8 的点阵组成。
传统的接法需要至少 8 根数据线加几根控制线,非常占引脚。所以市面上出现了 I2C 转接板,把并行接口转成 I2C 串行接口。我们用的就是这种方案。
转接板的核心芯片通常是 PCF8574,一个 I2C 转并行口的 IO 扩展芯片。它负责接收 I2C 总线上的指令,然后模拟出 LCD 需要的并行时序。
避坑指南: 我曾经买过一批便宜的 I2C 转接板,结果发现地址不一样。PCF8574 的默认地址是 0x27,但有些厂家用了 PCF8574A,地址变成 0x3F。所以拿到模块后,第一件事就是用 I2C 扫描程序确认地址。
LCD1602 内部有 DDRAM(显示数据 RAM)和 CGROM(字符生成 ROM)。你往 DDRAM 里写一个 ASCII 码,CGROM 就会自动把对应的点阵显示出来。说白了,你只需要告诉它「在第几行第几列显示什么字符」,剩下的硬件自己搞定。
1.3 硬件准备清单
做这个项目,你需要准备以下硬件:
| 器件 | 数量 | 说明 |
|---|---|---|
| 树莓派 Pico | 1 块 | RP2040 主控,支持 MicroPython |
| LCD1602 模块 | 1 块 | 带 I2C 转接板(PCF8574) |
| 杜邦线(母对母) | 4 根 | VCC、GND、SDA、SCL |
| USB 数据线 | 1 根 | 给 Pico 供电和烧录程序 |
| 面包板(可选) | 1 块 | 方便接线调试 |
接线非常简单:
- LCD 的 VCC → Pico 的 3.3V(或 5V,看模块规格)
- LCD 的 GND → Pico 的 GND
- LCD 的 SDA → Pico 的 GP0(I2C0 的 SDA)
- LCD 的 SCL → Pico 的 GP1(I2C0 的 SCL)
注意: 有些 LCD 模块需要 5V 供电才能正常工作,但 Pico 的 GPIO 是 3.3V 逻辑。好在 I2C 是开漏输出,加上转接板上有电平转换,一般没问题。但如果你的模块不亮,先查供电电压。
1.4 搭建 Python 开发环境
我们使用 MicroPython,因为它上手快、调试方便。我个人习惯用 Thonny IDE,对新手很友好。
环境搭建步骤:
- 下载 Thonny:从 thonny.org 下载安装包,装好就行
- 烧录 MicroPython 固件:
- 按住 Pico 上的 BOOTSEL 键,插上 USB
- Thonny 右下角选择「MicroPython (Raspberry Pi Pico)」
- 点击「安装或更新固件」,选择下载好的 .uf2 文件
- 验证环境:在 Shell 里输入
print("Hello Pico"),能看到输出就对了
小技巧: 我第一次烧录时忘了按 BOOTSEL 键,折腾了十分钟。记住:先按住按键,再插 USB,等电脑识别出「RPI-RP2」盘符再松手。
1.5 扫描 I2C 设备
硬件接好了,环境搭好了,怎么知道 I2C 通不通?写个扫描程序:
from machine import Pin, I2C
# 初始化 I2C0,SDA=GP0,SCL=GP1
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# 扫描总线上的设备
devices = i2c.scan()
if devices:
print("找到 I2C 设备,地址:")
for addr in devices:
print(hex(addr))
else:
print("没有找到 I2C 设备,请检查接线")
运行后如果打印出 0x27 或 0x3F,恭喜你,硬件通了。如果什么都没显示,嗯,我曾经也遇到过——多半是线松了,或者地址不对。
1.6 本章知识体系
下面这张图帮你理清这一章的核心脉络:
这一章我们完成了三件事:理解了 I2C 协议的核心思想、搞清了 LCD1602 配合转接板的工作原理、搭好了开发环境并验证了硬件通信。这些都是后面写驱动代码的基石。