原创 利用PCF8574芯片扩展IO口来显示液晶1602

2010-5-12 19:37 10059 3 6 分类: MCU/ 嵌入式

/****大家都知道咱们使用液晶来显示的话,一般是要好多个IO口的,比如1602,它至少需要6个IO口。上网搜一下,知道了可以用PCF8574。PCF8574芯片,是NXP公司出的IIC型I/O资源扩展芯片,其具有8位的双向I/O口,8个I/O的总的输出驱动电流高达200mA。为了利用8574使1602显示,也是耗了好几天的时间。第一天,在搞懂了IIC的原理后,开始看PCF8574的中文PDF,感觉有点被忽悠,于是硬着头皮把8574的英文PDF看了下来。总算是明白了,此时是信心百倍。第二天,用PROTEUS仿真了,结果能显示,可把程序烧写进单片机后,电路板上的液晶就是不显示,一点反应都没有,再试几次,还是不行。怀疑是PCF8574问题,于是用万用表检测一下PCF8574的8个IO口,晕,都是高电平。难道是个坏的?再换一个试试看,还是没反应。奇了怪了,到底是什么问题,只好上网再找找人家关于使用8574的心得,发现8574有两种,PCF8574和PCF8574A;细看一下自己买的型号,PCF8574AP。这到底是哪种呀?不管了,试试再说,第一次写的地址是0X40没反应。这次试下用0X70,再试试看,1602还是没显示,没信心了。第三天,再来。再用万用表测下8574的8个IO口,指针有偏转了,这说明8574有在工作,可1602还是没显示。难道是液显没初始化好,再重新看看程序,没问题呀。该不会是这1602是坏的吧?把舍友的1602拔来插上,1602竟然黑了,有反应。搞死,从实验室拿来的1602竟然是个尸体。哎!
虽然1602有反应了,可就是不显示应有的,只有黑的一片。看来现在是程序的问题了,再上网看看人家的心得,看到有人说因为液显只写不读,要在主程序中加一个长延时,才能显示。看他说的有道理而且也成功的利用8574使1602显示了,于是乎按照他说的加了个长延时,哈哈,1602终于显示了,这几天的努力终于没有白费。
(之前想用74LS164、74HC595使液晶1602显示,仿真能使1602显示,可我同学之前用74LS164试过,在现实中不能显示,后来我用8574成功后,想想那应该也是延时的问题,当然这还有待验证)


********通过参考网上的一些程序,整理出以下程序,供大家参考*******/  
#include <reg51.h>       //51芯片管脚定义头文件
#include <intrins.h>  //内部包含延时函数 _nop_();
#define uchar unsigned char
#define uint  unsigned int
 #define SetDDRAM(Address) WriteInstruc(0x80|Address)


sbit  SDA  =P1^1;   //串行数据输入
sbit  SCL  =P1^0;   //移位时钟脉冲
sbit   RS =P1^3;
sbit    EN= P1^2;
          



void delay1(int ms)
{
 unsigned char y ;
  while(ms--)
 {
  for(y = 0 ; y<250 ; y++)
  {
   _nop_() ;
   _nop_() ;
   _nop_() ;
   _nop_() ;
  }
 }
}


  
   
   //起始信号
   void Start_8574(void)
   {
    SDA="1";
 _nop_();
 SCL=1;
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 SDA=0;
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 SCL=0;
 }


 //停止信号
 void Stop_8574(void)
 {
  SDA="0";
     _nop_();
  SCL="1";
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  SDA="1";
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  }
 


   //初始化IIC函数
   void Init_8574(void)
   {
    SCL="1";
     _nop_();
  _nop_();
  SDA=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
    }


    // 向IIC总线写一字节数据函数
    void IIC_WriteByte(uchar temp)
    {
     uchar i;
  for(i=0;i<8;i++)
  {
   SDA=(bit)(temp & 0x80) ;
   temp <<=1;
   _nop_();
  _nop_();
   SCL="1";
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   SCL="0";
   }
    _nop_();
    SDA="1";
    _nop_();
    SCL="1";
      while(SDA);
      _nop_();
   SCL="0";
       }


    //向IIC总线上的从机写多字节数据函数
   void Puts_8574(uchar SlaveAddr,uchar data1)
    {
  Start_8574();
  IIC_WriteByte(SlaveAddr);
         IIC_WriteByte(data1);
     Stop_8574();
    }
  
   
    //写指令函数:WriteInstruc()
  void WriteInstruc(uint temp)
  {
   delay1(1) ;
   RS="0";
   EN="0";
 Puts_8574(0x70,temp);
 _nop_() ;
    _nop_() ;
 _nop_() ;
    _nop_() ;
 EN=1;
    _nop_() ;
 _nop_() ;
    _nop_() ;
 _nop_() ;
    _nop_() ;
 EN=0;
 }



 //写数据函数  :WriteData()
 void WriteData(uint data1)
 {
  delay1(1) ;
 RS=1;
 EN=0;
 Puts_8574(0x70,data1);
    _nop_() ;
 _nop_() ;
    _nop_() ;
 EN=1;
 _nop_() ;
    _nop_() ;
 _nop_() ;
    _nop_() ;
 _nop_() ;
    _nop_() ;
 EN=0;
 }
 
  void PCF8574_Init(void)
  {
   WriteData(0x00);
   }
  
   //显示字符函数:DispCharacter()
   //x为行号,y为列号
   //data为显示字符的码字数据
   void DispCharacter(uint x,uint y,uint data1)
   {
    uint temp;
 temp =y&0x0f;
 x  &=0x01;
 if(x) temp|=0x40;
 SetDDRAM(temp);
 WriteData(data1);
 }


 //LCD复位:LCDReset()
 void LCDReset()
 {
  WriteInstruc(0x01);
  WriteInstruc(0x02);
  }


 


  //LCD初始化
  void InitLCD()
  {
     delay1(50) ;
    WriteInstruc(0x01) ;      //清除LCD的显示内容           
    WriteInstruc(0x3c) ;      //16*2显示,5*7点阵,8位数据  
    delay1(5) ;
 // WriteInstruc(0x3c) ;
//  delay1(5) ;
    WriteInstruc(0x0c) ;      //显示开,关光标  
    delay1(5) ;
  //  WriteInstruc(0x06) ;      //移动光标 
   // delay1(5) ;
    WriteInstruc(0x01) ;      //清除LCD的显示内容 
    delay1(5) ;
 
    }
   
   
  
      void main()
   {
    InitLCD();
 //   PCF8574_Init();


    while(1)
    {
     delay1(500) ;//这个延时很关键
    DispCharacter(0,4,'w');
    DispCharacter(0,5,'e');
    DispCharacter(0,6,'l');
    DispCharacter(0,7,'c');
    DispCharacter(0,8,'o');
    DispCharacter(0,9,'m');
    DispCharacter(0,10,'e');
   // delay1(5) ;
    }
   }    



 
 

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户377235 2014-12-30 17:36

74164不能显示,是因为那东西数据是事实变化的,比如你给74164输入数据,从0到7的时候I/O一直在变化,会导致1602时许错乱,如果换成595的话,只有锁存置位才能引起一次I/O刷新

用户815770 2012-12-3 13:35

附件为什么无法下载

用户1622012 2011-12-25 10:05

good ,thank you
相关推荐阅读
用户555785 2009-12-13 12:55
TTL电平和CMOS电平的区别
什么是TTL电平,什么是CMOS电平,他们的区别(一)TTL高电平3.6~5V,低电平0V~2.4V CMOS电平Vcc可达到12V CMOS电路输出高电平约为0.9Vcc,而输出低电平约为 0.1V...
用户555785 2009-11-14 18:32
工科的学生玩电脑
          快毕业了,在大学里玩电脑玩得也还行,专业软件还有其它的一些软件也玩了不少。所以有些经验什么的就想写出来与大家分享。         我的专业是电子信息工程。专业软件有用到的是EWB...
用户555785 2009-11-09 21:22
把我逼急了,我也来狠的
     暑假时要参加电子竞赛,因为电脑没有串口,就买了一根USB转串口线,准备做单片机下载用。结果却不能兼容。,花了我15块钱却不能用。难不成再买一条USB转串口线?不成。突然灵光一闪,自己的电脑不...
我要评论
3
3
关闭 站长推荐上一条 /3 下一条