想通过raspi外接一个英文全键盘,尽管raspi的GPIO很丰富,但还是想省着点用,另外一个全键盘(含26个英文字母,10个数字,加减乘除之类)可能要50个左右按键,按8x8的按钮矩阵来算,需要占用16个GPIO,此时就想通过PCF8575芯片进行IO扩展,一个PCF8575芯片扩展16个GPIO,正好两个字节,正好够用。
当然最多可以8个PCF8575芯片串连,通过三个引脚控制8个芯片为不同的编号,这样最多就可以扩展出8x16=128个GPIO。
大体流程为:
raspi通过I2C连接PCF8575芯片,PCF8575芯片再与矩阵按键相连。
raspi默认未开启I2C,通过命令raspi-config,选择Interfacing Options,开启I2C即可(据说要重启raspi)。然后如下图中的GPIO2与GPIO3就变成了I2C1_SDA与I2C1_SCL了,前者为串行数据线,后者为串行时钟线。
连接PCF8575的数据线与时钟线,再电源连上VCC,GND接地,即可。INT可以先不管,VCC电源范围为2.5V至5.5V,通常是直接接到raspi上的3.3V或5V均可。最大工作电流为100mA。正面如下图,反面有A0/A1/A2三个引脚未焊接,用于设置芯片编号,默认为0x20。
通电后,在raspi的终端执行如下命令,就可以查到设备了(编号默认为0x20):
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
执行如下命令设置PCF8575的16个GPIO的状态值:
$ i2cset -y 1 0x20 0x1 0x2
-y表示yes,表示不要询问确认,1为raspi的I2CBUS编号,系统查看有3个I2C,分别为/dev/i2c-1, /dev/i2c-20, /dev/i2c-21。0x20为CHIP-ADDRESS,0x1 0x2就是要写入的两个字节,相当于P00与P11为高电平,其他均为低电平。
获取状态值:
$ i2cget -y 1 0x20 0 i 2
0x01 0x02
0 i 2表示从0位开始,连续读取2个字节。
实际写程序时,会在一个死循环里每10ms读取一次,以监测按键变化。
有些时候我们需要中断信号,以知道何时进行特定检测算法,比如检测旋转编码器的旋转方向。
PCF8575有一个中断引脚,此中断脚为开漏输出,相当于暴露一个三极管的集电极用于向外输出信号。此脚可直接与微处理器的GPIO相连,GPIO需要高电平使得中断生效,微处理器里用程序监听该GPIO的下降沿信号,当PCF8575的所有状态为输入的脚中有任何一个电平发生变化,中断信号就会产生,而读取或写入该GPIO都会自动清理该中断。