PCF8575中文资料程序详解参考设计

立创EDA,中国自主研发的PCB设计工具,免费使用!云端设计!

PCF8575用来扩展单片机IO口,I2C总线接口,所以,只需用单片机2条线。一片PCF8575可扩展16个IO,PCF8575有3个地址定义引脚,所以用单片机2个引脚,就可以扩展8X16=128个IO。把2个IO口,变成128个IO口,真是好东西!而且,扩展出来的IO口,既可以是输入,也可以是输出。而且此IO口最大输出20ma电流,最大输入承载电流也是20ma,也就是说,可以直接驱动LED了。

我在最近的项目中,需要用到60个IO控制LED,还要用到16个按键,还要输出3路PWM来控制直流电机调速,还需要2个IO来控制2个电机的正转和反转,还需要2个SPI口控制2个SPI器件,1个ADC用作模拟量输入。所以我选择了5片PCF8575用来扩展,其中1片PCF8575作为输入端,接16个按键,4片PCF8575用来驱动LED(共60个IO)。完成这么多功能,只用了1片SOP20封装的STC15W408AS作为主控单片机,还剩3个单片机IO口没有用。

多个PCF8575连接或者1个PCF8575连接单片机,都是只用2条线,都接到I2C引脚上即可。由于I2C容易模拟,随便找2个单片机引脚即可。

多片PCF8575

如果要用PCF8575扩展输入,比如按键,可以把PCF8575的INT引脚连接到单片机的中断引脚,当PCF8575的引脚上有上升沿或者下降沿时,PCF8575的IO口都会产生中断。当然,不用中断引脚也可以,在程序中循环扫描即可。

问题1:PCF8575适合3.3V的单片机吗?PCF8575适合5V的单片机吗?

PCF8575供电电压从2.5V~5.5V,所以,3.3V的单片机和5V的单片机都可以使用。

PCF8575供电电压

问题2:都在I2C总线上,那我怎么控制其中一个,而不影响其它的呢?

PCF8575芯片上有地址定义引脚A2 A1 A0,在设计电路的时候,可以把他们接地或者接VCC。例如:如果都接地,地址就是000;如果把A2接VCC,把A1,A0接地,地址就是100。

写程序的时候,在发送完启动位之后,就可以发“地址+读/写位”控制你想要的某一个芯片了。

PCF8575地址字节

上图中,S是启动位,接下来的0100是I2C协议委员会授予的地址码,A2 A1 A0就是我们刚才说的在PCF8575上的3个引脚,R/W是读写为,你要读PCF8575的IO电平,这里就是1,你要给PCF8575写数据,也就是说,你要控制PCF8575的引脚电平,这个位就是0。图中最后一个A是应答位。

问题3:如何把PCF8575的引脚设置为输入/输出引脚

不用设置,就和STC单片机引脚一样,可以随时读取它的引脚电平,可以随时控制它的引脚电平。

 

接下来写程序吧

1.写数据时序图:

PCF8575写时序图

写数据,也就是控制PCF8575的16个IO引脚电平,根据时序图,首先写启动位,然后写地址字节,然后接收应答信号,然后发送一个字节控制P0.0~P0.7,然后接收应答信号,然后再写一个字节控制P1.0~1.7,然后再接收一个应答信号,然后写结束位。一次数据就传输完成了。

假设我们现在要给A2A1A0接地的PCF8575发送数据,R/W位为0,A2 A1 A0为0,那么地址字节就是0x40.

void PCF8575_Wirte(unsigned int val)
{
 bit AckTemp=1;
 
 I2C_Start(); // 发送启动位
 I2C_Write8Bit(0x40); // 发送地址
 AckTemp=I2C_Check_Ack(); // 接收应答
 I2C_Write8Bit(val);  // 控制P0.0~P0.7
 AckTemp=I2C_Check_Ack(); // 接收应答
 I2C_Write8Bit(val>>8); // 控制P1.0~P1.7
 AckTemp=I2C_Check_Ack(); // 接收应答
 I2C_Stop(); // 发送停止位
}

2.读数据时序图:

PCF8575读时序图

 

读数据,用来获取PCF8575的16个IO的引脚电平。根据时序图,首先发送启动位,然后发送地址字节,然后接收应答信号,然后接收一个字节(该字节数据表示P0.0~P0.7的引脚电平),然后发送应答信号,然后接收一个字节(该字节表示P1.0~P1.7引脚的电平),然后发送应答信号,然后发送停止位。

特别注意:发送完地址信号后,接收从机的应答位,然后再接收完一个字节后,就不是接收从机的应答位了,而是主机给从机发送一个应答位,告诉从机我已经接收到一个字节了,你发第二个字节吧,然后再接收一个字节。很多童鞋接收到一个字节以后还是等待从机的应答位,结果造成无法读取P1.0~P1.7的引脚电平,或者每次读到的都是0xFF。接收完第二个字节后,如果还想接收一遍,主机再发送应答,接收第一个字节,主机再发送应答,接收第二个字节。如果接收完第二个字节后,不想在接收了,主机要发送“不应答”给从机,再发送停止位。

仔细看看时序,就可以看到这点,如下图:

PCF8575应答

假设我们现在要读A2 A1 A0都接地的PCF8575引脚电平,地址字节就是0x41

void PCF8575_Read(unsigned char addr)
{ 
 bit AckTemp=1;
 I2C_Start(); // 发送启动位
 I2C_Write8Bit(0x41); // 发送地址位
 AckTemp=I2C_Check_Ack(); // 接收应答信号
 PCF8575_LVal=I2C_Read8Bit(); // 接收1个字节(P0.0~P0.7)
 I2C_Ack();  // 发送应答位
 PCF8575_HVal=I2C_Read8Bit(); // 接收1个字节(P1.0~P1.7)
 I2C_NoAck(); // 发送不应答位
 I2C_Stop(); // 发送停止位
}

 

KEIL工程源文件(KEIL4 for C51)

点击下载(或右键另存为):PCF8575程序

 


关注我的微信公众号,可以第一时间看到我的文章

微信公众号科技老顽童