51单片机使用 8线/4线/PCF8574_I2C驱动 LCD1602

  • 一、8线驱动
  • 二、4线驱动
  • 三、PCF8574(I2C) 驱动
    • 1、PCF8574 介绍
    • 2、接线图
    • 3、示例代码

一、8线驱动

接线图(共需要 8 + 2 = 10 个 IO 控制)

#define  LCD1602_Port P2     //LCD1602数据端口//*****控制端口定义*****//
//RW 接地,只写不读
sbit LcdRs = P3 ^ 3;
sbit LcdEn = P3 ^ 2;void LCD1602_Write(uchar style, uchar input)
{LcdEn = 0;if(style == 0){LcdRs = 0;        //命令'0'}else{LcdRs = 1;      //数据'1'}Delay1ms();LCD1602_Port = input;Delay1ms();LcdEn = 1;Delay1ms();LcdEn = 0;Delay1ms();
}void LCD1602_Initial()
{LcdEn = 0;LCD1602_Write(0, 0x38);   //8位数据端口,2行显示,5*7点阵LCD1602_Write(0, 0x0c);     //开启显示, 无光标LCD1602_Write(0, 0x06);  //AC递增, 画面不动LCD1602_Write(0, 0x01);   //清屏Delay10ms();
}void LCD1602_GotoXY(uchar x, uchar y)   //X为显示指针的位置,即为各行的第几个位置,Y选行
{if(x == 0)LCD1602_Write(0, 0x80 + y);if(x == 1)LCD1602_Write(0, (0x80 + 0x40 + y));
}void LCD1602_Display_NoXY(uchar *str)  //向LCD写入字符串
{while(*str != '\0') {LCD1602_Write(1, *str);str++;}
}void main(void)
{LCD1602_Initial();Delay10ms();LCD1602_GotoXY(0, 2);LCD1602_Display_NoXY("Hello Word!");while(1);
}

二、4线驱动

接线图(共需要 4 + 2 = 6 个 IO 控制)

#define LCD_Port P0              //数据口sbit RS = P3 ^ 5;
sbit EN = P3 ^ 4;uchar table1[] = "LCD1602A DISPLAY";  //16
uchar table2[] = "By wxhntmy";//10//LCD使能
void lcd_en_enable()
{EN = 1;Delay100us();EN = 0;Delay100us();
}//写命令
void LCD_Write_Com(uchar cmd)
{uchar high, low, temp;high = cmd & 0xF0;low = (cmd << 4) & 0xF0;EN = 0;Delay100us();RS = 0;temp = LCD_Port & 0x0F;  //保持P0口低四位不变LCD_Port = temp | high;    //写入命令高四位Delay100us();lcd_en_enable();temp = LCD_Port & 0x0F;  //保持P0口低四位不变LCD_Port = temp | low; //写入命令低四位Delay100us();lcd_en_enable();
}//写数据
void LCD_Write_Data(uchar dat)
{uchar high, low, temp;high = dat & 0xF0;low = (dat << 4) & 0xF0;EN = 0;Delay100us();RS = 1;temp = LCD_Port & 0x0F;  //保持P0口低四位不变LCD_Port = temp | high;    //写入数据高四位Delay100us();lcd_en_enable();temp = LCD_Port & 0x0F;  //保持P0口低四位不变LCD_Port = temp | low; //写入数据低四位Delay100us();lcd_en_enable();
}
//X为显示指针的位置,即为各行的第几个位置,Y选行
void LCD1602_GotoXY(uchar x, uchar y)
{if(x == 0)LCD_Write_Com(0x80 + y);if(x == 1)LCD_Write_Com(0x80 + 0x40 + y);
}
//向LCD写入字符串
void LCD1602_Display_NoXY(uchar *str)
{while(*str != '\0') {LCD_Write_Data(*str);str++;}
}//初始化
void LCD_Init()
{Delay200ms();//等待供电稳定LCD_Write_Com(0x30);Delay5ms();LCD_Write_Com(0x30);Delay5ms();LCD_Write_Com(0x30);Delay1ms();LCD_Write_Com(0x20);Delay1ms();LCD_Write_Com(0x28);//设置4位格式,2行,5x7lcd_en_enable();LCD_Write_Com(0x28);//设置4位格式,2行,5x7LCD_Write_Com(0x0C);//整体显示,关光标,不闪烁LCD_Write_Com(0x06);//设定输入方式,增量不移位LCD_Write_Com(0x01);//清除屏幕显示Delay10ms();
}//主函数
void main(void)
{LCD_Init();        //液晶屏初始化//显示字符串LCD1602_GotoXY(0, 0);LCD1602_Display_NoXY(table1);LCD1602_GotoXY(1, 3);LCD1602_Display_NoXY(table2);while(1);
}

三、PCF8574(I2C) 驱动

1、PCF8574 介绍

  • 操作电压 2.5~6.0V
  • 低备用电流(≤10μA)
  • I2C 并行口扩展电路
  • 开漏中断输出
  • I2C 总线 实现 8 位远程 I/O 口
  • 与大多数 MCU 兼容
  • 口输出锁存,具有大电流驱动能力,可直接驱动 LED
  • 通过 3 个硬件地址引脚可寻址 8 个器件(PCF8574A 可多达 16 个)
  • DIP16,SO16 或 SSOP20 形式封装

PCF8574 是 CMOS 电路。它通过两条双向总线(I2C)可使大多数 MCU 实现远程 I/O 口扩展。该器件包含一个 8 位准双向口和一个 I2C 总线接口。PCF8574 电流消耗很低,且口输出锁存具有大电流驱动能力,可直接驱动 LED。它还带有一条中断接线(INT)可与 MCU 的中断逻辑相连。通过 INT 发送中断信号,远端 I/O 口不必经过 I2C 总线通信就可通知 MCU 是否有数据从端口输入。这意味着 PCF8574可以作为一个单被控器。
        PCF8574 和 PCF8574A 的唯一区别仅在于器件地址不相同。

PCF8574 和 PCF8574A 的从地址:

PCA8574 地址图(A2 A1 A0 悬空默认为1):

PCA8574A 地址图(A2 A1 A0 悬空默认为1):

写模式(IO 用作输出)

I2C 主机写入地址后,接着写入八位数据,这八位数据表示 PCF8574 八个 IO 的输出电平,例如写入的数据第 6 位为 1,则 PCF8574 的 P5 口输出高电平。

I2C 主机写一字节数据流程:start > write_write_address > master_receive_ack > write_data > master_receive_ack > stop

读模式(IO 用作输入)

I2C 主机写入地址后,接着读取八位数据,这八位数据表示 PCF8574 八个 IO 的输入电平,例如读取的数据第 6 位为 1,则 PCF8574 的 P5 口输入为高电平。

I2C 主机读一字节数据流程:start > write_read_address > master_receive_ack > receive_data > master_send_nack > stop

2、接线图

3、示例代码

#define  LCD_I2C_ADDRESS     0x27 << 1 //I2C地址,需要左移一位
#define BACKLIGHT           0x08        //PCF8574 P3口,背光开关
#define En                  0x04        //使能位,PCF8574 P2口
#define Rw                  0x02        //读/写位,PCF8574 P1口
#define Rs                  0x01        //选择位,PCF8574 P0口#define setbit(x,y)  x |= (1 << y)       //指定的某一位数置1
#define clrbit(x,y)  x &= ~(1 << y)      //指定的某一位数置0
#define reversebit(x,y)  x ^= (1 << y)   //指定的某一位数取反uchar table1[] = "LCD1602A PCF8574";  //16
uchar table2[] = "By wxhntmy";//10//i2c写一字节数据
void i2c_write_char(uchar address, uchar dat)
{start();send_data(address);recv_ack();send_data(dat);recv_ack();stop();
}
//i2c读一字节数据
uchar i2c_read_char(uchar address)
{uchar dat;start();send_data(address + 1);recv_ack();dat = recv_data();send_nack();stop();return dat;
}//LCD使能
void lcd_en_enable(uchar value)
{i2c_write_char(LCD_I2C_ADDRESS, value | En);   //EN = 1Delay100us();clrbit(value, 2);i2c_write_char(LCD_I2C_ADDRESS, value);  //EN = 0Delay100us();
}//lcd写命令/数据,mode=0命令,mode=1数据
void lcd_write(uchar mode, uchar cmd)
{uchar high, low;uchar temp;high = cmd & 0xF0 | BACKLIGHT;         //高四位low = (cmd << 4) & 0xF0 | BACKLIGHT;    //低四位变高四位temp = i2c_read_char(LCD_I2C_ADDRESS);        //获取引脚电平temp = temp & 0xF0;        //保留高四位电平i2c_write_char(LCD_I2C_ADDRESS, temp | BACKLIGHT);//en = 0,写引脚时保持高四位电平不变Delay100us();if(mode == 0) {i2c_write_char(LCD_I2C_ADDRESS, temp | BACKLIGHT);//rs = 0,写引脚时保持高四位电平不变} else {i2c_write_char(LCD_I2C_ADDRESS, temp | Rs | BACKLIGHT);//rs = 1,写引脚时保持高四位电平不变}temp = i2c_read_char(LCD_I2C_ADDRESS);        //获取引脚电平temp = temp & 0x0F;        //保留低四位电平i2c_write_char(LCD_I2C_ADDRESS, high | temp);//写高四位数据时保持低四位引脚电平不变Delay100us();lcd_en_enable(high | temp);i2c_write_char(LCD_I2C_ADDRESS, low | temp);//写高四位数据时保持低四位引脚电平不变Delay100us();lcd_en_enable(low | temp);}
//lcd初始化
void lcd_init()
{uchar temp;Delay50ms();Delay50ms();Delay50ms();Delay50ms();//等待供电稳定lcd_write(0, 0x30);Delay5ms();lcd_write(0, 0x30);Delay5ms();lcd_write(0, 0x30);Delay1ms();lcd_write(0, 0x20);Delay1ms();//用四线时,1602的初始化只需要高四位数据就可以完成,在初始化完成之后必须再传入四位数据,//执行完“lcd_write(0, 0x28);”之后液晶已经初始化,其实在执行了一半的时候就已经初始化完成,//此时又传入了四位数据(一个写语句会传入8位数据),这时候如果直接写数据的话,就会形成乱码,所以需要两次功能性初始化。lcd_write(0, 0x28);   //4位数据端口,2行显示,5*7点阵temp = i2c_read_char(LCD_I2C_ADDRESS);       //获取引脚电平lcd_en_enable(temp);lcd_write(0, 0x28);   //4位数据端口,2行显示,5*7点阵lcd_write(0, 0x0c);     //开启显示, 无光标lcd_write(0, 0x06);  //AC递增, 画面不动lcd_write(0, 0x01);   //清屏Delay50ms();
}
//Y为显示指针的位置,即为各行的第几个位置,X选行
//Y:0-15
//X:0-1
void LCD1602_GotoXY(uchar x, uchar y)
{if(x == 0)lcd_write(0, 0x80 + y);if(x == 1)lcd_write(0, (0x80 + 0x40 + y));
}
//向LCD写入字符串
void LCD1602_Display_NoXY(uchar *str)
{while(*str != '\0') {lcd_write(1, *str);str++;}
}void main()
{init_i2c();lcd_init();//显示字符串LCD1602_GotoXY(0, 0);LCD1602_Display_NoXY(table1);LCD1602_GotoXY(1, 3);LCD1602_Display_NoXY(table2);while(1);
}

51单片机使用 8线/4线/PCF8574(I2C) 驱动 LCD1602相关推荐

  1. 通过 I2C 驱动 LCD1602 液晶屏(51单片机)

    通过 I2C 驱动 LCD1602 液晶屏(51单片机) 硬件实物 原理图 3.程序 #include <reg51.h> #include <intrins.h>#defin ...

  2. 51单片机小项目--红外巡线小车

    这次项目要求我们使用51单片机,实现红外循迹,超声波避障的功能. 我将这个几个实现的任务一步步分解开来,首先要然小车动起来,需要模块是需要电机和定时器,我们那时候用到小黄电机,驱动是用的L298N.然 ...

  3. 51单片机学习总结系列(一)之驱动流水灯(1)

    51单片机驱动流水灯可以更好的理解IO口,这一节就主要来用查表法和移位法来实现流水灯,首先先看电路图. 电路比较简单,发光二极管正极接5V电源,负极接470Ω限流电阻,接单片机P0口,限流电阻470Ω ...

  4. 51单片机温度语音播报系统TTS播报DS18B20温度LCD1602显示

    实践制作DIY- GC0023-温度语音播报系统 一.功能说明: 基于51单片机设计-温度语音播报系统 功能介绍: 1.STC89C52单片机(STC89C51/52 AT89C51/52 任选其一) ...

  5. 51单片机自动量程(3挡)0-30v直流电压表万用表CD4051 LCD1602显示 MCP3201

    实践制作DIY- GC0062-51单片机自动量程电压表 一.功能说明: 基于51单片机设计-51单片机自动量程电压表 二.功能介绍: STC89C52单片机+LCD1602+CD4051量程选择+1 ...

  6. 51单片机DS18B20温度传感器使用及数码管温度计、LCD1602温度显示代码详解

    温馨提示:读者若要彻底理解并会灵活使用DS18B20温度传感器,请详细阅读中文手册,并且对照代码注释充分分析代码.请不要觉得中文手册内容繁多!如能静心分析,定能深有体会,获益匪浅! 一.DS18B20 ...

  7. 单片机上运行linux程序代码,在Linux下烧录51单片机

    原标题:在Linux下烧录51单片机 *本文作者:LEdge1,本文属 FreeBuf原创奖励计划,未经许可禁止转载. 背景 我一直在学习Linux 系统,但是最近还要学习51单片机,所以在Linux ...

  8. GC9A01-TFT屏幕驱动(整理有stm32/51单片机/arduino等驱动代码)

    GC9A01-TFT屏幕驱动 & 整理有stm32/51单片机/arduino等驱动代码 前言 关于GC9A01 stm32驱动 引脚接线 代码移植 文件复制 端口修改 显示函数 中文汉字数组 ...

  9. 基于51单片机的LCD1602显示温湿度

    51单片机基础难点知识理解后,直接通过下面3个小项目可以更好理解51单片机.中断 定时器 串口甚至是基础的IO输入输出都有结合,再加上一些外设模块的学习(如1602显示屏,L298N电机驱动等) 项目 ...

最新文章

  1. 进程、应用程序域、程序集、对象上下文区别与联系
  2. Linux主机密码设置,Linux如何批量创建用户和设置密码
  3. mysql bandwidth_内存带宽对mysql影响多大
  4. ORACLE——重做日志文件管理
  5. 多模块Maven工程单独打包某一模块工程
  6. 提高你的Java代码质量吧:使用valueof前必须进行校验
  7. PHP下添加PDO_Pgsql扩展
  8. C++ OS 网络 数据库 (面试)
  9. python os模块安装方法_Python模块——os模块详解
  10. VUE组件封装echarts百度地图点位效果
  11. Ember.js 入门指南 (一)
  12. 在Mac下如何制作win7/win10启动盘
  13. 为女性们点赞!Google 为女性提供更多支持
  14. 解决数据一致性方案(库存问题)
  15. 集成微控制器使太阳能微型逆变器设计成本有效
  16. Vmware虚拟化概念原理
  17. V4L2_Utils目标平台编译
  18. [译]用R语言做挖掘数据《七》
  19. 店梯erp系统规范化的仓库管理功能如何操作?
  20. 首席新媒体运营黎想教程:活动运营推广入门全攻略及进阶

热门文章

  1. linux内核中linux中readl()和writel()函数---用于读写寄存器
  2. 【iOS】—— FMDB的基础用法
  3. python如何计算平方_Python lmfit如何计算R平方?
  4. ubuntu:更新源操作步骤
  5. html 醒目的样式,创意醒目门牌设计欣赏
  6. 使用IDEA工具查看Java类层次结构关系图
  7. Openshift架构理解v3.11
  8. Josephus问题(最后一个退出的人)
  9. 面向园区网的全数字化网络架构 - Cisco DNA介绍
  10. Linux中的网络服务初步---FTP服务器、Web服务器