You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F3Discovery搭载PCF8574T的1602 I2C LCD无显示求助

搞定STM32 HAL驱动PCF8574T 1602 LCD无显示的问题

兄弟,我之前折腾过同款PCF8574T+1602的模块,一眼就看出问题了——你直接往I2C发ASCII字符肯定不行啊!这个模块不是透传的,PCF8574T是把LCD的控制信号和4位数据打包成一个字节发送的,而且LCD必须先走完初始化流程才能干活。下面给你一步步捋明白:

1. 先把I2C地址的事儿搞清楚

你找到的0x3D是7位地址,HAL_I2C_Master_Transmit要求的是左移一位后的8位写地址(因为写操作时最低位是0)。所以正确的写地址是0x3D << 1也就是0x7A,你之前的adresseLCD*2是对的,但要确保每次发送都用这个写地址,别搞混了。

2. 封装PCF8574T和LCD的通信函数

PCF8574T的8个引脚分配是:P0-P3对应LCD的D4-D7,P4是RS(0发命令,1发数据),P5是RW(我们只用写,固定设0),P6是EN(需要脉冲触发LCD读数据),P7是背光(你背光亮说明这个引脚是高,没问题)。

先写两个基础函数,用来发命令和数据:

#define LCD_BACKLIGHT 0x08 // P7置1,保持背光
#define LCD_RS        0x10 // P4是RS引脚
#define LCD_EN        0x40 // P6是EN引脚

// 发送4位数据/命令(配合EN脉冲)
void lcd_send_nibble(I2C_HandleTypeDef *hi2c, uint8_t nibble, uint8_t rs) {
    uint8_t data = (nibble << 4) | LCD_BACKLIGHT; // 把4位数据放到P0-P3,开背光
    if (rs) data |= LCD_RS; // RS=1表示是数据,0是命令
    
    // 拉EN高,触发LCD读取
    HAL_I2C_Master_Transmit(hi2c, (0x3D << 1), &data, 1, 100);
    HAL_Delay(1);
    // 拉EN低,完成脉冲
    data &= ~LCD_EN;
    HAL_I2C_Master_Transmit(hi2c, (0x3D << 1), &data, 1, 100);
    HAL_Delay(1);
}

// 发送完整的命令字节(拆成两次4位发送)
void lcd_send_command(I2C_HandleTypeDef *hi2c, uint8_t cmd) {
    lcd_send_nibble(hi2c, cmd >> 4, 0); // 高4位
    lcd_send_nibble(hi2c, cmd & 0x0F, 0); // 低4位
    // 清屏、归位命令需要更长延时
    if (cmd == 0x01 || cmd == 0x02) HAL_Delay(2);
}

// 发送完整的数据字节(同样拆两次)
void lcd_send_data(I2C_HandleTypeDef *hi2c, uint8_t data) {
    lcd_send_nibble(hi2c, data >> 4, 1);
    lcd_send_nibble(hi2c, data & 0x0F, 1);
}

3. 必须的LCD初始化流程

1602上电后不能直接发数据,得先配置它的工作模式(4位模式、显示开关、光标设置这些),这是你最缺的一步!加个初始化函数:

void lcd_init(I2C_HandleTypeDef *hi2c) {
    HAL_Delay(50); // 上电先等50ms让LCD稳定
    
    // 强制切换到4位模式(不管之前是什么状态)
    lcd_send_nibble(hi2c, 0x03, 0);
    HAL_Delay(5);
    lcd_send_nibble(hi2c, 0x03, 0);
    HAL_Delay(1);
    lcd_send_nibble(hi2c, 0x03, 0);
    HAL_Delay(1);
    lcd_send_nibble(hi2c, 0x02, 0); // 正式进入4位模式
    
    // 配置为2行、5x8字体
    lcd_send_command(hi2c, 0x28);
    // 先关闭显示(后续再打开)
    lcd_send_command(hi2c, 0x08);
    // 清屏
    lcd_send_command(hi2c, 0x01);
    HAL_Delay(2);
    // 设置光标右移,不移动屏幕
    lcd_send_command(hi2c, 0x06);
    // 打开显示,关闭光标(如果要光标就改成0x0E)
    lcd_send_command(hi2c, 0x0C);
}

4. 修改主函数,让它正常工作

把你的主函数改成这样,先初始化LCD,再发字符串:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    MX_USB_PCD_Init();
    
    // 先初始化LCD!
    lcd_init(&hi2c1);
    
    // 发送测试字符串到第一行
    char *test_msg = "Hello STM32!";
    while (*test_msg) {
        lcd_send_data(&hi2c1, *test_msg++);
        HAL_Delay(50); // 稍微延时让显示更流畅
    }
    
    while(1)
    {
        // 可以在这里加其他逻辑
    }
}

额外要排查的坑

  • 上拉电阻:STM32的I2C引脚默认可能没开内部上拉,PCF8574T需要SDA和SCL引脚接4.7kΩ的上拉电阻到VCC,如果你的模块没自带,一定要自己加!
  • I2C时钟速度:CubeMX里把I2C的时钟速度设成100kHz以内,PCF8574T不支持高速I2C。
  • 通信是否成功:可以给HAL_I2C_Master_Transmit加返回值判断,比如if (HAL_I2C_Master_Transmit(...) != HAL_OK),看看是不是真的发送成功了,排除硬件接线问题。

内容的提问来源于stack exchange,提问作者Gaetan Kelabra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:38:25