目录
目录
前言
芯片介绍
开发平台准备
撰写测试程序
有时候会遇到接口不够用的情况,那这个情况的话,我们就可以考虑一下使用芯片来扩展。MCP23016这一款芯片国内用的好像不多,也许是成本,也许是现在MCU引脚多数时候都够用,直接选个适合项目的MCU就可以,所以我基本没有找到什么开源资料。
所以今天就来讲一讲这一个芯片的使用
这一个芯片的作用很明确了,16位IO扩展,还带有中断,3个硬件地址引脚,能自由切换,也就是你最多可以使用3块这个芯片在一条I2C总线上。
这一款其实是我在公司仓库捡到的,捡了五六片,看了一下Datasheet好像还不错,所以就拿来开发一下。目前来看对于电源的支持也不错,2.0-5.5V,基本涵盖常用的几家的MCU
为了使用这个芯片,我画了一张原理图,这个原理图验证后可知是正确的,如果你是简单用一用,可以放心的参考
当然随之的还有一个PCB,我也通过线上方式制作了出来
连接后长这样,我顺便试了一下我设计的另一个电源模块
开发环境是Arduino,我这人比较懒一点所以有库当然是用库了,为了直接先获取到现在的I2C地址,我使用这一段代码来遍历并得出MCP23016的I2C地址
#include
void setup(){
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
}
void loop(){
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for (address = 1; address < 127; address++ ){
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0){
Serial.print("I2C device found at address 0x");
if (address < 16)
Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}else if (error == 4){
Serial.print("Unknow error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
我正常的把IO扩展板连接到A4(SDA)和A5(SCL),烧录这段程序,打开串口以及PC端的界面,得到当前的地址是0x27
这个芯片是通过I2C,不管懂不懂先回顾一下I2C通讯用到的信号含义,我直接找一张贴这里
Arduino的I2C用起来很方便,可以先写一个I2C模版,这模版基本讲明一个写数据的过程
#include
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
}
byte cmd = 0;
byte set = 0;
void loop() {
Wire.beginTransmission(0x27); // transmit to device
Wire.write(cmd ); // sends byte
Wire.write(set ); // sends byte
Wire.endTransmission(); // stop transmitting
delay(500);
}
然后,回过头来看数据表,我们刚才已经得知目前设置的地址是0x27了,在呼叫I2C设备后,需要传输要写数据的地址,下面这个表就说明各个指令对应的设置的功能,可以看作是选单
而下面这一张表则注明功能设置,如果要测试,我们最先需要做的事情就是设定GP0和GP1这两个寄存器,Value on POR是说刚上电时候的默认配置。
GP:通用接口
OLAT:输出锁存器
IPOL:输入极性
IODIR:输入输出设置
INTCAP:中断设置
IOCON:设置IOCON0就会设置IOCON1
依据上面这个表,可以了解到,我们应该要先对IO口进行设置,也就是使用这一段代码
Wire.begin(); // join i2c bus (address optional for master)
Wire.beginTransmission(0x27); //设备的地址,门牌号
Wire.write(0x06); // 和I2C设备说明,我们要设置IO口
Wire.write(0x00); // 设置为0x00,也就是P0.0-P0.7全部输出
Wire.write(0xFF); // 设置为0xFF,也就是P1.0-P1.7全部输入
Wire.endTransmission();
然后,再设置输出端口的寄存器,我设置了一个0x03,也就是0000 0011,如果设置好那么P0.0和P0.1会有电平
Wire.beginTransmission(0x27);
Wire.write(0x00);
Wire.write(0x03);
Wire.endTransmission();
设置完成后是这样,可以正常的使用
这个代码的完整版本我放这里
//配置MCP23016 IO扩展板输出的代码
#include
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Wire.beginTransmission(0x27); // setup out direction registers
Wire.write(0x06); //
Wire.write(0x00); //
Wire.write(0xFF); //
Wire.endTransmission();
}
byte cmd = 0x01;
byte set = 0x07;
byte set2 = 0x01;
void loop() {
Wire.beginTransmission(0x27);
Wire.write(0x00);
Wire.write(0x03);
Wire.endTransmission();
delay(500);
}
有一点是,这一基于I2C通讯的芯片可以连续进行配置,比如我设置0x00,那如果传送两个字节,就可以把0x01也一块给配置了,其实也就是先低位再高位