/****大家都知道咱们使用液晶来显示的话,一般是要好多个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) ;
}
}
用户377235 2014-12-30 17:36
用户815770 2012-12-3 13:35
用户1622012 2011-12-25 10:05