使用LCD屏(16x2 LCD Pi Plate,带I2C接口、键盘、RGB LED、MCP23017-E/SO)显示树莓派5B系统状态(不使用python),详细中文教程
时间: 2025-06-03 15:36:25 浏览: 24
<think>好的,我需要帮助用户实现在树莓派5B上使用16x2 LCD屏(带I2C接口、键盘、RGB LED、MCP23017-E/SO)显示系统状态,并且不使用Python。用户之前询问过在Ubuntu安装C语言I2C库的问题,现在可能是在树莓派上使用类似的C语言方法。我需要考虑以下几点:
1. **硬件连接确认**:确保树莓派5B与LCD模块正确连接,尤其是I2C引脚。树莓派5B的GPIO布局是否有变化?需要确认I2C总线号是否正确,通常是I2C-1或I2C-0。
2. **启用I2C和配置权限**:用户之前的步骤已经包括启用I2C内核模块和用户组权限,但树莓派可能需要通过raspi-config启用I2C接口。需要指导用户检查并启用。
3. **依赖库安装**:用户需要C开发环境和相关库。可能需要安装libi2c-dev和build-essential,类似之前的Ubuntu步骤,但树莓派是基于Debian的,命令可能相同。
4. **MCP23017的使用**:由于LCD模块使用MCP23017扩展芯片,用户需要了解如何通过I2C控制该芯片。需要查找或提供MCP23017的寄存器配置方法,以控制LCD、键盘和RGB LED。
5. **LCD驱动编写**:需要指导用户编写C代码初始化LCD(16x2),通过MCP23017发送命令和数据。可能需要参考HD44780的指令集,因为大多数16x2 LCD基于此控制器。
6. **系统状态获取**:如何通过C程序获取CPU温度、负载、内存使用等信息。例如,读取/sys/class/thermal/thermal_zone0/temp文件获取温度,解析/proc/stat等。
7. **键盘输入处理**:如果LCD模块带有键盘,需要配置MCP23017的输入端口,轮询按键状态,并在C程序中处理输入事件。
8. **RGB LED控制**:通过MCP23017的GPIO或PWM控制LED颜色,可能需要配置相关寄存器。
9. **代码结构**:整合各部分功能,主循环中更新系统状态并刷新显示,同时处理按键输入。
10. **编译和测试**:确保代码正确编译,处理可能的权限问题,调试I2C通信问题。
可能出现的问题包括I2C地址冲突、MCP23017配置错误、LCD初始化不正确,以及系统状态数据的解析错误。需要指导用户使用i2cdetect检查设备地址,测试各部分功能模块,并逐步调试。
需要提供详细的代码示例,并注释关键部分,特别是MCP23017的初始化和LCD的控制命令。同时,提醒用户注意树莓派5B的GPIO变化,必要时参考官方文档。可能还需要调整I2C总线的速度或添加延迟以确保稳定性。</think>以下是在树莓派5B上使用 **16x2 LCD屏(带I2C接口、键盘、RGB LED、MCP23017-E/SO)** 显示系统状态的详细中文教程,全程基于 **C语言** 实现,不依赖 Python。
---
### **1. 硬件准备与连接**
#### **硬件清单**
- 树莓派5B
- 16x2 LCD Pi Plate(含I2C接口、键盘、RGB LED、MCP23017-E/SO芯片)
- 杜邦线(若LCD未直接插在GPIO上)
#### **接线说明**
- 确保LCD模块通过I2C接口连接到树莓派的 **GPIO引脚**:
- **SDA** → GPIO2(物理引脚3)
- **SCL** → GPIO3(物理引脚5)
- **VCC** → 5V
- **GND** → GND
---
### **2. 系统配置**
#### **启用I2C接口**
1. 打开终端,运行树莓派配置工具:
```bash
sudo raspi-config
```
2. 选择 **Interface Options → I2C → Yes** 启用I2C驱动。
#### **安装依赖库**
安装编译工具和I2C开发库:
```bash
sudo apt update
sudo apt install -y build-essential libi2c-dev i2c-tools
```
#### **验证I2C设备**
1. 列出I2C总线(树莓派5B通常为 `i2c-1` 或 `i2c-0`):
```bash
i2cdetect -l
```
2. 扫描设备地址(假设总线为 `i2c-1`):
```bash
i2cdetect -y 1
```
- 若看到 **0x20**(MCP23017默认地址),说明连接成功。
---
### **3. 编写C程序**
#### **代码框架**
```c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <time.h>
#include <string.h>
// MCP23017寄存器地址(根据芯片手册定义)
#define IODIRA 0x00 // I/O方向寄存器A
#define IODIRB 0x01 // I/O方向寄存器B
#define GPIOA 0x12 // GPIO端口A
#define GPIOB 0x13 // GPIO端口B
#define OLATA 0x14 // 输出锁存器A
#define OLATB 0x15 // 输出锁存器B
// LCD控制命令(基于HD44780)
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_ENTRY_MODE 0x04
#define LCD_DISPLAY_CONTROL 0x08
#define LCD_FUNCTION_SET 0x20
// 自定义函数声明
void mcp23017_write(int file, uint8_t reg, uint8_t data);
void lcd_init(int file);
void lcd_write(int file, uint8_t data, uint8_t mode);
void lcd_print(int file, const char *str);
void get_system_status(char *cpu_temp, char *mem_usage, char *cpu_load);
int main() {
int i2c_file;
const char *i2c_bus = "/dev/i2c-1"; // 根据实际总线调整
const uint8_t mcp23017_addr = 0x20; // MCP23017默认地址
// 打开I2C总线
if ((i2c_file = open(i2c_bus, O_RDWR)) < 0) {
perror("Failed to open I2C bus");
return 1;
}
// 设置MCP23017地址
if (ioctl(i2c_file, I2C_SLAVE, mcp23017_addr) < 0) {
perror("Failed to set I2C address");
close(i2c_file);
return 1;
}
// 初始化MCP23017和LCD
mcp23017_write(i2c_file, IODIRA, 0x00); // 端口A为输出(控制LCD)
mcp23017_write(i2c_file, IODIRB, 0xFF); // 端口B为输入(读取键盘)
lcd_init(i2c_file);
// 主循环:显示系统状态
while (1) {
char cpu_temp[16], mem_usage[16], cpu_load[16];
get_system_status(cpu_temp, mem_usage, cpu_load);
lcd_write(i2c_file, LCD_CLEAR, 0); // 清屏
lcd_print(i2c_file, "CPU:");
lcd_print(i2c_file, cpu_temp);
lcd_write(i2c_file, 0xC0, 0); // 跳转到第二行
lcd_print(i2c_file, "MEM:");
lcd_print(i2c_file, mem_usage);
sleep(2); // 更新间隔2秒
}
close(i2c_file);
return 0;
}
// 写入MCP23017寄存器
void mcp23017_write(int file, uint8_t reg, uint8_t data) {
uint8_t buffer[2] = {reg, data};
if (write(file, buffer, 2) != 2) {
perror("MCP23017 write failed");
}
}
// 初始化LCD
void lcd_init(int file) {
// 设置4位模式、2行显示、5x8字体
lcd_write(file, LCD_FUNCTION_SET | 0x08 | 0x04, 0);
usleep(4500);
lcd_write(file, LCD_DISPLAY_CONTROL | 0x04, 0); // 打开显示,关闭光标
lcd_write(file, LCD_CLEAR, 0);
usleep(2000);
}
// 向LCD写入数据或命令
void lcd_write(int file, uint8_t data, uint8_t mode) {
uint8_t high_nibble = data & 0xF0;
uint8_t low_nibble = (data << 4) & 0xF0;
uint8_t rs = (mode == 1) ? 0x01 : 0x00; // RS引脚:0=命令,1=数据
// 发送高4位
mcp23017_write(file, GPIOA, high_nibble | rs | 0x04); // 使能EN
usleep(1);
mcp23017_write(file, GPIOA, high_nibble | rs); // 关闭EN
usleep(100);
// 发送低4位
mcp23017_write(file, GPIOA, low_nibble | rs | 0x04);
usleep(1);
mcp23017_write(file, GPIOA, low_nibble | rs);
usleep(100);
}
// 打印字符串到LCD
void lcd_print(int file, const char *str) {
while (*str) {
lcd_write(file, *str++, 1); // 模式1=数据
}
}
// 获取系统状态(CPU温度、内存使用率、CPU负载)
void get_system_status(char *cpu_temp, char *mem_usage, char *cpu_load) {
// 读取CPU温度
FILE *fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
float temp;
fscanf(fp, "%f", &temp);
fclose(fp);
snprintf(cpu_temp, 16, "%.1fC", temp / 1000);
// 读取内存使用率
FILE *meminfo = fopen("/proc/meminfo", "r");
unsigned long total, free;
fscanf(meminfo, "MemTotal: %lu kB\nMemFree: %lu kB", &total, &free);
fclose(meminfo);
snprintf(mem_usage, 16, "%.1f%%", 100 - (free * 100.0 / total));
// 读取CPU负载(1分钟平均)
FILE *loadavg = fopen("/proc/loadavg", "r");
float load;
fscanf(loadavg, "%f", &load);
fclose(loadavg);
snprintf(cpu_load, 16, "%.2f", load);
}
```
---
### **4. 编译与运行**
1. 将代码保存为 `lcd_system_monitor.c`。
2. 编译代码:
```bash
gcc -o lcd_monitor lcd_system_monitor.c
```
3. 运行程序(需确保用户已加入 `i2c` 组):
```bash
./lcd_monitor
```
---
### **5. 功能扩展**
#### **控制RGB LED**
通过MCP23017的GPIO引脚控制LED颜色:
```c
// 设置RGB LED颜色(假设连接在MCP23017的GPIOA引脚2、3、4)
void set_rgb_led(int file, uint8_t red, uint8_t green, uint8_t blue) {
uint8_t led_state = (red << 2) | (green << 3) | (blue << 4);
mcp23017_write(file, OLATA, led_state);
}
```
#### **读取键盘输入**
通过MCP23017的GPIOB端口读取键盘矩阵:
```c
uint8_t read_keyboard(int file) {
uint8_t key;
mcp23017_write(file, GPIOB, 0xFF); // 设置端口B为输入
read(file, &key, 1); // 读取按键状态
return key;
}
```
---
### **6. 常见问题**
1. **LCD无显示**
- 检查I2C地址是否为 `0x20`,调整接线或代码中的总线号(`/dev/i2c-1` 或 `/dev/i2c-0`)。
- 添加延时确保初始化时序正确。
2. **权限不足**
- 运行 `sudo usermod -aG i2c $USER` 并重启。
3. **键盘或LED不响应**
- 检查MCP23017寄存器配置(如 `IODIRB` 方向设置)。
---
通过以上步骤,你可以通过C语言直接在树莓派5B上驱动16x2 LCD,实时显示系统状态,并扩展控制键盘和RGB LED。具体硬件操作需参考模块手册调整寄存器地址和引脚定义。
阅读全文
相关推荐
















