搜索
bottom↓
回复: 14

用PCF8574做了块LCD1602到I2C的转换板,可以直接用I2C来连接LCD1602了,通电测试成功:)

[复制链接]

出0入0汤圆

发表于 2007-9-24 18:52:04 | 显示全部楼层 |阅读模式
昨晚用洞洞板做了个PCF8574(I2C I/O扩展芯片)的转换板,把LCD1602变成了I2C接口,用M32的SDA SCL来驱动,这下可以省了好多IO口,刚刚把程序改完,通电实验成功,发个帖子,也顺便感谢下昨天在坛子上回答我问题帮助过我的朋友。


阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2007-9-24 18:53:49 | 显示全部楼层
/***********************************************************************************
                                LCD1602液晶通过PCF8574转换成I2C接口驱动函数
LCD1602液晶与PCF8574之间的连接方式:
  [LCD]   PCF8574
   1 GND-  8  GND
   2 +5V- 16  VCC  
   3 VLC- LCD contrast control voltage 680欧电阻到地
   4 RS -  5  P1        //RW低电平时,当RS=1 RW=0写数据;RS0 RW=0写指令
   5 RW -  6        P2  //RW引脚始终置低电平
   6 EN -  7  P3        //EN为读写使能端,高电平有效,下降沿锁定数据
  11 D4 -  9  P4        //4位数据总线,要用PORT的高4位
  12 D5 - 10  P5
  13 D6 - 11  P6
  14 D7 - 12  P7
作者:alien2006
时间:20070924
版本:V1.0
说明:LCD驱动采用4线驱动方法,LCD1602的RW端接低电平,这样无法读数据,操作需插入合适的
                        的延时,由于LCD1602是慢速器件,因此时序要注意,参考其手册
                        LCD第一行显示寄存器地址:0X80-0X8F  
                        LCD第二行显示寄存器地址:0XC0-0XCF
                        PCF8754设置地址为0x40H
                        I2C接口线序定义为:1、SDA                2、Vdd        3、Vss        4、SCL
*************************************************************************************/
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>

#define PCF8574_Address 0x40  //PCF8574 I2C地址
#define TWI_Stop()  TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))                                                                   
#define TWI_Start() TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN))

//--------------函数声明----------------------
static void TWI_Init(void);//TWI初始化
static unsigned char TWI_Send_A_Data(unsigned char Address, unsigned char Data);//TWI向指定的地址发送一个字节
static void DelayUS(unsigned int us);        //----uS级延时
static void DelayMS(unsigned int ms);  //----mS级延时
void LCD1602_Write_Command(unsigned char command);        //向LCD1602写入指令
void LCD1602_Write_Data(unsigned char data);        //向LCD1602写入数据  
void LCD1602_Device_Init(void);                          //LCD1602初始化函数
void LCD1602_Set_Position(unsigned char x, unsigned char y);  //向LCD1602设置下一个准备写入的字符位置
void LCD1602_Write_String(unsigned char X, unsigned char Y, char *String); //向指定的位置开始写字符串

unsigned char temp=0;
/*******************************************************************/
int main()
{
        LCD1602_Device_Init();
        while(1)
        {
                DelayMS(500);
                LCD1602_Write_String(0, 0, "0123456789ABCDEF");
                LCD1602_Write_String(0, 1, "0123456789abcdef");
                DelayMS(500);
                LCD1602_Write_String(0, 0, "hello! kitty1234");
                LCD1602_Write_String(0, 1, "HELLO! KITTY5678");
        }
        return 0;
}

/*--------初始化TWI------------------------
函数名称:void TWI_Init(void)
函数参数:无
函数说明:初始化TWI
-----------------------------------------*/
void TWI_Init(void) //初始化TWI
{
    TWCR= 0X00; //disable twi
    TWBR= 0x20; //设置波特率
    TWSR= 0x00; //设置预分频=1
    TWCR= 0x04; //enable twi
}

/*-------TWI向指定的地址发送一个字节--------------
函数名称:void TWI_Send_A_Data(unsigned char Address, unsigned char Data)
                                        TWI向指定的地址发送一个字节
函数参数:unsigned char Address //待发送的目的地址
                                        unsigned char Data    //待发送的数据
函数返回:unsigned char //1表示成功,其他返回状态码
函数说明:TWI向指定的地址发送一个字节
-------------------------------------------------*/
unsigned char TWI_Send_A_Data(unsigned char Address, unsigned char Data)//TWI向指定的地址发送一个字节
{
        TWI_Start();//发送Start
        while(!(TWCR & (1<<TWINT)));//等待START发送完毕,TWINT置位,并返回状态
        if(TW_STATUS != TW_START)        //检查发送完毕后的状态是否正确,如不正确则转向错误处理部分
        {
                //return TWSR;//出错则返回状态码
        }
        TWDR = Address|TW_WRITE;//写SLA+W到TWDR
        TWCR = (1<<TWINT)|(1<<TWEN);//启动发送TWDR
        while(!(TWCR & (1<<TWINT)));//等待TWDR发送SLA+W完毕TWINT置位,并返回状态
        if((TW_STATUS == TW_MT_SLA_ACK)||(TW_STATUS == TW_MT_SLA_NACK))//检查返回的状态是否正确
        {
                //return  TWSR;
        }
        TWDR = Data;//装载要发送的数据
        TWCR = (1<<TWINT)|(1<<TWEN);//启动发送TWDR
        while(!(TWCR & (1<<TWINT)));//等待TWDR发送DATA完毕,TWINT置位,并返回状态
        if(TW_STATUS != TW_MT_DATA_ACK)//检查DATA发送返回状态是否正确
        {
                //return TWSR;
        }
        TWI_Stop();//结束本次发送
        return 1;
}

//----------------ms级延时---------------
void DelayMS(unsigned int ms)  //----mS级延时
{
        unsigned int i;
  for(i=0; i<ms; i++) _delay_ms(1);
}

//----------------us级延时---------------
void DelayUS(unsigned int us)        //----uS级延时
{
        unsigned int i;
  for(i=0; i<us; i++) _delay_us(1);
}

/*------------向LCD1602写入指令----------------------------
函数名称:void LCD1602_Write_Command(unsigned char command)       
                                        向LCD1602写入指令
函数参数:unsigned char command //准备写入的指令
函数说明:向LCD1602的指令寄存器写入一个指令
---------------------------------------------------------------*/
void LCD1602_Write_Command(unsigned char command)        //向LCD1602写入指令
{
        //unsigned char temp=0;
        DelayUS(17);//此处插入一个等待很重要,小于这个时间会导致连续写时出现错误
        //先写入高4位
        temp = command&0xF0;//先处理高4位,EN=0,RW=0,RS=0
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp |= 0x08; //拉高EN
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp &= 0xf7;        //EN置低,下降沿写入液晶
        TWI_Send_A_Data(PCF8574_Address, temp);
        //接下来写入低4位
        temp = command<<4;
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp |= 0x08; //拉高EN
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp &= 0xf7;        //EN置低,下降沿写入液晶
        TWI_Send_A_Data(PCF8574_Address, temp);
}

/*------------向LCD1602写入数据----------------------------
函数名称:void LCD1602_Write_Data(unsigned char data)       
                                        向LCD1602写入数据
函数参数:unsigned char data //准备写入的数据
函数说明:向LCD1602的指令寄存器写入一个数据
---------------------------------------------------------------*/
void LCD1602_Write_Data(unsigned char data)        //向LCD1602写入数据  
{
        //unsigned char temp=0;
        DelayUS(17);//此处插入一个等待很重要,小于这个时间会导致连续写时出现错误
        //先写入高4位
        temp = (data&0xF0)|0x02;//先处理高4位,EN=0,RW=0,RS=1
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp |= 0x08; //拉高EN
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp &= 0xf7;        //EN置低,下降沿写入液晶
        TWI_Send_A_Data(PCF8574_Address, temp);
        //接下来写入低4位
        temp = (data<<4)|0x02;
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp |= 0x08; //拉高EN
        TWI_Send_A_Data(PCF8574_Address, temp);
        temp &= 0xf7;        //EN置低,下降沿写入液晶
        TWI_Send_A_Data(PCF8574_Address, temp);
}

/*------------------------------------------------------------------
函数名称:void LCD1602_Init(void)//LCD1602初始化函数
函数参数:无
函数说明:参考LCD1602液晶说明手册
------------------------------------------------------------------*/
void LCD1602_Device_Init(void)                          //LCD1602初始化函数
{
        TWI_Init();
        DelayMS(50);        //先等待50毫秒VDD上电稳定
        LCD1602_Write_Command(0x28);//先进行功能设置,四位数据接口,两行显示,5′7点阵字符。
        DelayUS(40);        //等待上条指令完成
        LCD1602_Write_Command(0x0C);//Display On/Off Control,显示开关:D=1为开,光标开关:C=1为开,闪烁开关:B=1为开
        //LCD1602_Write_Command(0x06);//AC地址递增模式
        //DelayMS(2);
        LCD1602_Write_Command(0x01);//清屏
        DelayMS(2);
}

/*--------设置AC地址--------------------------------------------------
函数名称:void LCD1602_Set_Position(unsigned char x, unsigned char y)
                                        向LCD1602设置下一个准备写入的字符位置
函数参数:unsigned char x 行地址 0~F
                                        unsigned char y 列地址 0~1
函数说明:设置AC地址,
---------------------------------------------------------------------*/
void LCD1602_Set_Position(unsigned char x, unsigned char y)  //向LCD1602设置下一个准备写入的字符位置
{
        unsigned char address = (y == 0) ? (0x80 + x) : (0xC0 + x);
        LCD1602_Write_Command(address);
}

/*--------向指定的位置开始写字符串 ---------------------------------------
函数名称:LCD1602_Write_String(unsigned char X, unsigned char Y, char *s)
                                        向指定的位置开始写字符串
函数参数:unsigned char X                //列位置
                                        unsigned char Y                //行位置
                                        char *String                                                //要显示的字符串
函数说明:向指定的位置开始写字符串
------------------------------------------------------------------------*/
void LCD1602_Write_String(unsigned char X, unsigned char Y, char *String) //向指定的位置开始写字符串
{
        LCD1602_Set_Position(X, Y);
        while(*String)
        {
                LCD1602_Write_Data(*String++);
        }
}

     再分享下调试成功的源代码.

出0入0汤圆

发表于 2007-9-26 19:38:32 | 显示全部楼层
PCF8574 ,贵吗,多少钱一片,感觉S64的IO口不够,呵呵  可拿来扩占

出0入0汤圆

 楼主| 发表于 2007-9-26 22:53:15 | 显示全部楼层
年初买的,具体价格忘了,数了下手头有4片,估计不太便宜,肯定是5-10元之间,要不然就不会只买4片了,就直接10片10片买了,呵呵,

出0入0汤圆

发表于 2012-7-26 10:32:25 | 显示全部楼层
价格有点贵,直接用便宜的单片机模仿吧

出0入0汤圆

发表于 2012-7-26 15:21:06 | 显示全部楼层
不错 学习了

出0入0汤圆

发表于 2012-7-29 16:36:29 | 显示全部楼层
请问这个能提供电路图吗?

出0入0汤圆

发表于 2012-10-17 14:10:13 | 显示全部楼层
兄台有联系方式吗qq

出0入0汤圆

发表于 2012-11-15 15:21:13 | 显示全部楼层
学习,谢谢!!!

出0入0汤圆

发表于 2012-11-16 09:23:19 | 显示全部楼层
mark~~~~~~~~~~~

出0入0汤圆

发表于 2012-12-20 10:40:11 | 显示全部楼层
谢谢共分享,楼主幸苦了。

出0入0汤圆

发表于 2013-4-3 20:35:07 | 显示全部楼层
好的很 刚买的这个转换模块  打算用M16驱动下试试呢 看到了LZ的无私奉献  感谢感谢

出0入0汤圆

发表于 2013-4-3 20:37:44 | 显示全部楼层
挺复杂的啊  硬件省了  软件增加了点

出0入0汤圆

发表于 2013-9-24 08:22:36 | 显示全部楼层
好象淘宝上最便宜的只要0.6元。不只质量怎样。如果质量还可以的话,我也想用它来驱动LCD1602了。

出0入4汤圆

发表于 2016-6-2 12:03:05 | 显示全部楼层
用楼主的程序试了下  硬件一样  但是上电后只是背光一直闪烁
没有显示   这是怎么回事
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 10:37

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表