IO扩展芯片PCA9557

这篇博客介绍了如何利用PCA9557芯片通过I2C接口扩展GPIO引脚。PCA9557是一款拥有4个内部寄存器的IC,用于扩展8个GPIO输出,适用于引脚有限的蓝牙芯片。博主提供了详细的初始化、设置模式、输出值设置和输入值读取的C代码实现,并特别提到了PCA9557的IO0为开漏输出,需要外部上拉电阻才能实现高电平输出。
摘要由CSDN通过智能技术生成

项目上用到的一款蓝牙芯片引脚太少,选择了PCA9557扩展IO,通过一路i2c可以扩展出8个IO。这款芯片没有中断输入,所以更适合做扩展输出引脚用,内部寄存器也比较少,只有4个,使用起来很容易。


输入寄存器

 

输出寄存器

 

极性颠倒寄存器

 

 配置寄存器

参考代码

/*
 * pca9557.c
 *
 *  Created on: 2021-07-15
 *      Author: shynan
 */
#include "sl_i2cspm.h"
#include "sl_i2cspm_instances.h"
#include "pca9557.h"

#define PCA9557_I2C_DEVICE  sl_i2cspm_sensor
#define PCA9557_I2C_BUS_ADDR  0x18

#define PCA9557_INPUT_PORT_REG          0x00
#define PCA9557_OUTPUT_PORT_REG         0x01
#define PCA9557_POLARITY_INVERSION_REG  0x02
#define PCA9557_CONFIG_REG              0x03

#define POLARITY_INVERSION_DEFAULT  0xF0
#define CONFIG_DEFAULT              0xFF

static I2C_TransferReturn_TypeDef pca9557_read(uint8_t reg, uint8_t* val, uint8_t len)
{
    I2C_TransferSeq_TypeDef seq;
    I2C_TransferReturn_TypeDef ret;

    seq.addr = PCA9557_I2C_BUS_ADDR << 1;
    seq.flags = I2C_FLAG_WRITE_READ;

    seq.buf[0].data = &reg;
    seq.buf[0].len  = 1;

    seq.buf[1].data = val;
    seq.buf[1].len  = len;

    // Perform the transfer and return status from the transfer
    ret = I2CSPM_Transfer(PCA9557_I2C_DEVICE, &seq);
    return ret;
}

static I2C_TransferReturn_TypeDef pca9557_write(uint8_t reg, uint8_t* val, uint8_t len)
{
    I2C_TransferSeq_TypeDef seq;
    I2C_TransferReturn_TypeDef ret;

    seq.addr = PCA9557_I2C_BUS_ADDR << 1;
    seq.flags = I2C_FLAG_WRITE_WRITE;

    seq.buf[0].data = &reg;
    seq.buf[0].len  = 1;

    seq.buf[1].data = val;
    seq.buf[1].len  = len;

    // Perform the transfer and return status from the transfer
    ret = I2CSPM_Transfer(PCA9557_I2C_DEVICE, &seq);
    return ret;
}

int pca9557_init(void)
{
    uint8_t reg = PCA9557_POLARITY_INVERSION_REG;
    uint8_t polarity = 0;
    I2C_TransferReturn_TypeDef status;

    status = pca9557_write(reg, &polarity, 1);
    if (status != i2cTransferDone)
    {
      /* read polarity fail */
      return -1;
    }
    return 0;
}

int pca9557_set_mode(const uint8_t pin, const uint8_t mode)
{
    uint8_t io_mode = 0;
    uint8_t reg = PCA9557_CONFIG_REG;
    I2C_TransferReturn_TypeDef status;
    status = pca9557_read(reg, &io_mode, 1);
    if (status != i2cTransferDone)
    {
      /* read config fail */
      return -1;
    }

    if (mode == EXTAND_IO_OUTPUT)
    {
      io_mode &= (~pin);
    } else {
        io_mode |= pin;
    }

    status = pca9557_write(reg, &io_mode, 1);
    if (status != i2cTransferDone)
    {
      /* read config fail */
      return -1;
    }
    return 0;
}

int pca9557_setOutputValue(const uint8_t pin, const uint8_t val)
{
    uint8_t io_val = 0;
    uint8_t reg = PCA9557_OUTPUT_PORT_REG;
    I2C_TransferReturn_TypeDef status;
    status = pca9557_read(reg, &io_val, 1);
    if (status != i2cTransferDone)
    {
      /* read config fail */
      return -1;
    }

    if (val == 0)
    {
      io_val &= (~pin);
    } else {
        io_val |= pin;
    }
    status = pca9557_write(reg, &io_val, 1);
    if (status != i2cTransferDone)
    {
      /* read config fail */
      return -1;
    }
    return 0;
}

int pca9557_getInputValue(uint8_t* val)
{
    uint8_t reg = PCA9557_INPUT_PORT_REG;
    I2C_TransferReturn_TypeDef status;
    if (val == NULL)
    {
      return -1;
    }
    status = pca9557_read(reg, val, 1);
    if (status != i2cTransferDone)
    {
      /* read config fail */
      return -1;
    }

    return 0;
}

/*
 * pca9557.h
 *
 *  Created on: 2021-07-15
 *      Author: shynan
 */

#ifndef EXPAND_IO_PCA9557_H_
#define EXPAND_IO_PCA9557_H_
#include <stdlib.h>
#include <stdint.h>

typedef unsigned char uint8_t;

enum {
  EXTAND_IO_OUTPUT = 0,
  EXTAND_IO_INPUT = 1,
};

#define PCA9557_IO0       0x01
#define PCA9557_IO1       0x02
#define PCA9557_IO2       0x04
#define PCA9557_IO3       0x08
#define PCA9557_IO4       0x10
#define PCA9557_IO5       0x20
#define PCA9557_IO6       0x40
#define PCA9557_IO7       0x80

extern int pca9557_init(void);

extern int pca9557_set_mode(uint8_t pin, const uint8_t mode);

extern int pca9557_setOutputValue(const uint8_t pin, const uint8_t val);

extern int pca9557_getInputValue(uint8_t* val);
#endif /* EXPAND_IO_PCA9557_H_ */

​​​​​​​IO0无法输出高电平问题,看了下芯片手册发现这个引脚比较特殊,是开漏输出,需要外部上拉。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值