两个IO口,四根线!51单片机IIC控制LCD1602的究极偷懒方案!!!
51单片机
51单片机是一个历史悠久、应用极其广泛、且非常适合初学者入门的8位微控制器系列。
它并非特指某一种芯片,而是泛指所有兼容Intel 8051指令系统的单片机统称。自20世纪80年代诞生以来,它在工业控制、仪器仪表、消费电子等领域留下了深刻的印记,至今仍是国内高校单片机教学和无数电子爱好者入门的首选平台。
技术特点与核心优势
51单片机能经久不衰,主要得益于以下几点:
极简架构,易于上手:其经典的哈佛结构和精简的指令集,让初学者能快速理解单片机的底层工作原理。
成本低廉,选择丰富:芯片本身价格低,配套的开发工具和学习资源也非常成熟丰富,降低了入门门槛。
资源典型,覆盖广泛:集成了CPU、RAM、ROM、I/O端口、定时器、中断系统以及UART等串行通信接口,足以应对大多数基础的控制任务。
主要产品与型号演进
可以从以下几个维度来了解51单片机家族的产品:
经典51子系列与52子系列:这是最基础的分类。主要的区别在于内部存储资源的多少。以经典8051为例,其内部有128字节RAM和4KB ROM,而52子系列(如8052)则增加到256字节RAM和8KB ROM。
主流厂商与芯片:市场上涌现了大量兼容芯片,主流厂商包括:
Intel(英特尔):鼻祖,MCS-51系列的创造者,其80C51、87C51等是原始设计的基础。
Atmel(艾特梅尔):其AT89C51、AT89S51系列曾风靡一时,是早期开发板和DIY项目的首选。
STC(宏晶科技):国产厂商,其STC89C52等系列凭借增强性能、在线编程(ISP)和中文资料,在国内极受欢迎。
其他厂商:还包括Philips(飞利浦)、华邦、Dallas(达拉斯)、Siemens(西门子)等。
应用场景
虽然性能已非顶尖,但凭借极高的性价比,51单片机仍在许多领域发挥着作用。
工业自动化:广泛用于可编程逻辑控制器(PLC)、传感器接口和数据采集系统。
消费电子:许多家用电器,如洗衣机、空调、微波炉等,其核心控制单元可能就是一颗51单片机。
教育与科研:作为高校“单片机原理”等课程的教学核心,用于验证基本原理和培养编程思维。
智能家居:常用于家庭安防系统、智能照明等逻辑相对简单的子系统。
I2C介绍
I2C(Inter-Integrated Circuit,内部集成电路)是一种由飞利浦公司(现恩智浦半导体)在1980年代开发的两线式串行通信总线。它主要用于在电路板级别的短距离、低速设备之间进行数据传输,比如连接微控制器、传感器、存储器、LCD驱动器(如你之前问到的PCF8574)等。
简单来说,I2C是一种让多个芯片之间只用两根线就能“通话”的协议,因其引脚少、连接简单、支持多设备,在嵌入式系统中极其常用。
核心特点
两线制:仅需两根信号线。
SDA (Serial Data Line):串行数据线,用来传输实际的数据。
SCL (Serial Clock Line):串行时钟线,用来同步数据传输的节奏。
主从架构:总线上可以挂载多个设备。主设备(通常是单片机)负责产生时钟、发起和结束通信;从设备(如传感器、PCF8574)则听从主设备的指令。
多主设备支持:理论上,总线上可以有多个主设备,它们之间通过仲裁机制决定谁获得控制权。
设备寻址:每个从设备都有一个唯一的7位或10位地址。主设备通过发送这个地址来指定要与哪个设备通信。
半双工:数据可以在两个方向上传输,但不能同时进行。
内置应答机制:接收方在收到每字节数据后会回复一个应答位,发送方能据此确认传输是否成功,提高了可靠性。
物理层与电气特性
总线需要接上拉电阻(通常为4.7kΩ)。在空闲时,SDA和SCL线都被上拉至高电平。设备通过将线路拉低来输出信号。
支持多种速率模式(由慢到快):
标准模式:100 kbit/s
快速模式:400 kbit/s
高速模式:3.4 Mbit/s
协议层(一次完整的数据传输)
一次典型的数据传输包含以下几个清晰的步骤,就像一次标准的对话:
起始信号:主设备发号施令。在SCL高电平时,主设备将SDA线从高电平拉低到低电平。这告诉所有从设备:“注意,要开始新的通信了!”
发送设备地址:主设备发送7位或10位的从设备地址,再加上一位读写控制位(0表示“我要写”,1表示“我要读”)。
等待应答:主设备释放SDA线。被寻址到的从设备会拉低SDA线来回应:“收到,我在呢!” 这个应答位就是ACK。
发送/接收数据:主设备和从设备开始按约定的方向传输数据。每个字节是8位,最高有效位(MSB)先发。每发送完一个字节,都会跟着一个应答位(由接收方发出)。
停止信号:通信结束。在SCL高电平时,主设备将SDA线从低电平拉高到高电平。这告诉所有设备:“本次通信结束,总线空闲了。”
I2C的优缺点
优点 缺点 引脚占用极少:只需2个GPIO口。 速度相对较慢:不如SPI(串行外设接口)快。 支持多主多从:结构灵活。 功耗相对较高:因为上拉电阻会消耗电流。 连接简单:设备挂在同一条总线上,不需要像SPI那样用片选线区分。 每个设备都需要唯一地址:地址冲突会导致通信失败。 有应答机制:增强了通信可靠性。 协议比UART稍复杂:需要理解起始、停止、应答等概念。 应用广泛:几乎所有微控制器和无数传感器都支持。 受限于总线电容:线缆不能太长(通常建议几米以内)。 常用iic器件:
序号 器件类型 典型型号 主要功能 / 应用场景 1 I/O 扩展器 PCF8574, MCP23017 通过I2C扩展数字I/O引脚,常用于驱动LCD1602、按键矩阵等 2 EEPROM 存储器 AT24C02, CAT24C256 非易失性数据存储,保存系统配置、用户参数、小容量数据日志 3 温湿度传感器 SHT30, AHT20, HDC1080 测量环境温度和相对湿度,用于智能家居、气象站、温室监控 4 气压/高度传感器 BMP280, LPS22HB 测量大气压力和海拔高度,应用于无人机定高、手机气压计 5 环境光传感器 BH1750, OPT3001 测量光照强度(Lux),用于屏幕亮度自动调节、智能照明 6 OLED 显示驱动 SSD1306, SH1106 驱动小型OLED单色屏幕(如0.96英寸 128×64)显示文字和图形 7 实时时钟 (RTC) DS1307, PCF8563, DS3231 提供精确的日期和时间,带电池备份,用于电子钟、数据记录器 8 ADC / DAC 转换 PCF8591, ADS1115, MCP4725 模数转换(读取模拟电压)或数模转换(输出模拟信号) 9 姿态/惯性测量 MPU6050, ICM-20948 集成加速度计和陀螺仪(部分带磁力计),用于计步、平衡车、姿态解算 10 I2C 多路复用器 TCA9548A 将一路I2C总线扩展为8个独立通道,解决多设备地址冲突问题
LCD1602 字符型液晶显示模块
LCD1602是一种工业级字符型液晶模块,由HD44780控制器驱动,可显示2行、每行16个ASCII字符。它采用5V供电,内置192个常用字符的字库(含英文字母、数字、日文假名及特殊符号),也支持用户自定义8个5×8点阵字符。
模块采用16引脚接口,核心信号包括:RS(数据/命令选择)、RW(读/写选择)、EN(使能脉冲)以及8位或4位并行数据线D0~D7。为节省I/O口,常与PCF8574等I2C转并行芯片配合使用,此时仅需SDA、SCL两线即可控制。
使用时需注意:通过外接电位器调节VO引脚电压以改变显示对比度;背光通常由A和K引脚供电;初始化必须严格按时序设置(如4位模式、显示开/关、清屏等)。其低功耗、高可靠性、显示清晰的优点,使其广泛应用于电子表、温度计、智能仪表等嵌入式设备,是初学者的理想入门模块。
IIC转LCD1602模块
介绍
IIC转LCD1602模块,本质上是一个为LCD1602字符液晶显示屏专门设计的“转接板”或“驱动板”。它通过一个I2C(IIC)接口芯片(通常是PCF8574),将LCD1602所需的众多并行控制引脚,转换为仅需两根线的I2C串行接口。
模块通常由LCD1602显示屏、PCF8574 I2C I/O扩展芯片和一个用于调节屏幕对比度的蓝色电位器三部分组成。PCF8574芯片的I2C地址可通过其引脚A0、A1、A2进行修改,以此避免总线上多个设备的地址冲突。其中一些模块可能还会有背光控制的跳线帽(用于开启/关闭背光)、背光调节电阻以及数据位选择电阻。
引进配置
VCC:接电源正极(通常为5V)。
GND:接电源地线。
SDA:I2C数据线,接单片机的对应I2C数据引脚。
SCL:I2C时钟线,接单片机的对应I2C时钟引脚。
PCF8574实物图
LCD1602实物图:
iic转lcd1602实物图:
proteus 仿真电路图:
51代码实现:
#include <REG52.H> #include <intrins.H> /* PCF8574 地接的常见情况? PCF8574接地方式与I2C接线完整说明 A0、A1、A2引脚接地主要用于设置PCF8574的I2C设备地址。PCF8574默认7位地址为0x20,实际写地址计算方式为(0x20 << 1) | 0 = 0x40。 若A0、A1、A2全部接地,设备7位地址为0x20,对应写地址为0x40;若A0接VCC、A1和A2接地,设备7位地址为0x21,对应写地址为0x42。 在LCD1602与PCF8574搭配使用时,R/W引脚通常固定接地,设置为只写不读模式,能够简化程序逻辑,同时节省单片机IO资源。 PCF8574的INT引脚为开漏输出引脚,主要用于中断信号通知,常规使用场景下直接悬空即可。该引脚接地会影响中断功能,若项 目无需使用中断功能,可忽略该影响,接地或悬空都不影响屏幕正常显示。 PCF8574的P0~P3引脚对应LCD1602的RS、R/W、E控制引脚,P4~P7对应LCD1602的D4~D7数据引脚,部分转接板引脚定义存在差异,使用前需查阅对应模块官方文档。 I2C地址配置示例 PCF8574模块A0、A1、A2全部接地时,7位设备地址为0x20,I2C写操作发送地址为0x40。市面上常见的蓝色PCF8574转接板,默认自带引脚拉高, 7位地址为0x27,对应I2C写地址为0x4E。实际使用中,建议通过I2C扫描工具确认模块真实设备地址,从根源避免I2C通信失败、屏幕不显示、乱码等问题。 关键注意事项 LCD1602的R/W引脚建议接地,51单片机开发中一般无需读取LCD状态,该接法可节省IO口,同时规避读写时序异常问题。I2C通信总线需要在SDA、SCL引脚 分别接入4.7kΩ上拉电阻至VCC,保障总线通信稳定。使用PCF8574驱动LCD1602,必须遵循HD44780标准初始化流程,依次发送三次0x30指令,再发送0x28指令 切换四线工作模式,完成屏幕初始化配置。 */ //===================== PCF8574T 驱动 ===================== #define PCF8574T_W_Address 0x40 //4e #define PCF8574T_R_Address 0x4F //===================== IIC 底层 ===================== sbit IIC_SDA = P3^7; sbit IIC_SCL = P3^6; void IIC_Delay6us() { _nop_(); } void IIC_Start() { IIC_SDA = 1; IIC_SCL = 1; IIC_Delay6us(); IIC_SDA = 0; IIC_Delay6us(); IIC_SCL = 0; } void IIC_Stop() { IIC_SCL = 0; IIC_SDA = 0; IIC_Delay6us(); IIC_SCL = 1; IIC_Delay6us(); IIC_SDA = 1; } void IIC_WriteByte(unsigned char Byte) { unsigned char i; for(i = 0; i < 8; i++) { IIC_SDA = Byte & (0x80 >> i); IIC_SCL = 1; IIC_Delay6us(); IIC_SCL = 0; } } unsigned char IIC_ReceptionAck() { unsigned char BitAck; IIC_SDA = 1; IIC_SCL = 1; BitAck = IIC_SDA; IIC_Delay6us(); IIC_SCL = 0; return BitAck; } //===================== PCF8574T 驱动 ===================== //#define PCF8574T_W_Address 0x40 //4e //#define PCF8574T_R_Address 0x4F void PCF8574T_Write_Byte(unsigned char dat) { IIC_Start(); IIC_WriteByte(PCF8574T_W_Address); IIC_ReceptionAck(); IIC_WriteByte(dat); IIC_ReceptionAck(); IIC_Stop(); } //===================== LCD1602 四线驱动 ===================== void LCDPCF_1ms() //@11.0592MHz { unsigned char i, j; _nop_(); i = 2; j = 199; do { while (--j); } while (--i); } void LCDPCF1602_WriteCmd(unsigned char Cmd) { unsigned char cd; //高四位 cd = (Cmd / 16) << 4; PCF8574T_Write_Byte(cd); PCF8574T_Write_Byte(cd | 0x04); LCDPCF_1ms(); PCF8574T_Write_Byte(cd); LCDPCF_1ms(); //低四位 cd = (Cmd % 16) << 4; PCF8574T_Write_Byte(cd); PCF8574T_Write_Byte(cd | 0x04); LCDPCF_1ms(); PCF8574T_Write_Byte(cd); LCDPCF_1ms(); } void LCDPCF1602_WriteDat(unsigned char Dat) { unsigned char da; //高四位 da = (Dat / 16) << 4; PCF8574T_Write_Byte(da | 0x01); PCF8574T_Write_Byte(da | 0x05); LCDPCF_1ms(); PCF8574T_Write_Byte(da | 0x01); LCDPCF_1ms(); //低四位 da = (Dat % 16) << 4; PCF8574T_Write_Byte(da | 0x01); PCF8574T_Write_Byte(da | 0x05); LCDPCF_1ms(); PCF8574T_Write_Byte(da | 0x01); LCDPCF_1ms(); } void LCDPCF1602_SetCursor(unsigned char line,unsigned char column) { if(line == 1) { LCDPCF1602_WriteCmd(0x80 | (column - 1)); } else { LCDPCF1602_WriteCmd(0x80 | (column - 1) + 0x40); } } void LCDPCF1602_Init() { LCDPCF_1ms(); LCDPCF1602_WriteCmd(0x28); //4线2行 LCDPCF_1ms(); LCDPCF1602_WriteCmd(0x0C); //开显示 无光标 LCDPCF1602_WriteCmd(0x06); //地址自增 LCDPCF1602_WriteCmd(0x01); //清屏 LCDPCF_1ms(); } //显示字符串 void LCDPCF1602_ShowStr(unsigned char line,unsigned char column,unsigned char *string) { unsigned char i; LCDPCF1602_SetCursor(line,column); for(i = 0; string[i] != 0; i++) { LCDPCF1602_WriteDat(string[i]); } } //===================== 主函数 ===================== void main(void) { LCDPCF1602_Init(); LCDPCF1602_ShowStr(1, 1, "Hello World"); LCDPCF1602_ShowStr(2, 1, "PCF8574+LCD1602"); while(1) { } }现象演示:
