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
相关产品推荐
相关产品推荐

