使用模拟I2C读取NCA9555

I2C介绍

I2C(集成电路总线),由Philips公司(2006年迁移到NXP)在1980年代初开发的一种简单、双线双向的同步串行总线,它利用一根时钟线和一根数据线在连接总线的两个器件之间进行信息的传递,为设备之间数据交换提供了一种简单高效的方法。每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。

I²C最重要的功能包括:

只需要两条总线;
没有严格的波特率要求,例如使用RS232,主设备生成总线时钟;
所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址;
I²C是真正的多主设备总线,可提供仲裁和冲突检测;
传输速度;
标准模式:Standard Mode = 100 Kbps
快速模式:Fast Mode = 400 Kbps
高速模式: High speed mode = 3.4 Mbps
超快速模式: Ultra fast mode = 5 Mbps
最大主设备数:无限制;
最大从机数:理论上是127;

I2C 的IO初始化

SDA SCL都设置成推挽输出,并都设置成高电平

void IIC_Init(void)
{
    SDA_OUT();
    SCL_OUT();
    SDA_SET();
    SCL_SET();
}

I2C开始时序

在这里插入图片描述

void IIC_Start(void)
{
    SDA_OUT();      //由于上一个SCL状态是0或者是1,要让SDA稳定输出,都可以设置为1。
    SDA_SET();
    Delay_us(2);

    SCL_SET();      //让SCL发生变化,为0不变,为1则变化,表明数据可以变动了。
    Delay_us(2);

    SDA_RESET();      //SDA线数据变化,从而可以保证发出的是start信号。
    Delay_us(2);

    SCL_RESET();      //将I2C总线钳住,下一个时间SDA可以输出高低电平。
    Delay_us(4);
}

I2C结束时序

在这里插入图片描述

void IIC_Stop(void)
{
    SDA_OUT();
    SDA_RESET();      //上一个状态的SCL=0,这个状态设置SDA=0,目的是让状态能反转
    Delay_us(2);

    SCL_SET();      //该时刻设置SCL=1,然后就可以让数据稳定在改状态下。
    Delay_us(2);

    SDA_OUT();
    Delay_us(4);
}

I2C等待应答信号

uint8_t IIC_Wait_Ack(void)
{
    uint16_t ucErrTime = 0;

    SCL_RESET();
    Delay_us(1);

    SDA_IN();                   //SDA设置为输入

    while (READ_SDA())
    {
        ucErrTime++;
        if (ucErrTime > 250)
        {
            IIC_Stop();
            return 0;           //超时,表明数据传输有问题
        }
    }
    SCL_SET();
    Delay_us(1);

    SCL_RESET();           //时钟输出0
    Delay_us(2);

    return 1;
}

产生ACK应答

void IIC_Ack(void)
{
    SCL_RESET();
    Delay_us(2);

    SDA_OUT();
    SDA_RESET();
    Delay_us(1);

    SCL_SET();
    Delay_us(1);
    SCL_RESET();
    Delay_us(4);

}

不产生应答

void IIC_NAck(void)
{
    SDA_OUT();
    SCL_RESET();
    Delay_us(2);

    SDA_OUT();
    Delay_us(2);

    SCL_SET();
    Delay_us(2);
    SCL_RESET();
    Delay_us(2);
}

发送8位数据

void SendByte(uint8_t c)
{
    uint8_t BitCnt;
    for (BitCnt = 0; BitCnt < 8; BitCnt++) /*要传送的数据长度为8位*/
    {
        SDA_OUT();
        if ((c << BitCnt) & 0x80)
            SDA_SET(); /*判断发送位*/
        else
            SDA_RESET();
        Delay_us(2);
        SCL_SET(); /*置时钟线为高,通知被控器开始接收数据位*/
        Delay_us(4);
        SCL_RESET();
    }

}

接收8位数据

uint8_t RcvByte()
{
    uint8_t retc;
    uint8_t BitCnt;
    retc = 0;
    //      SDA_OUT();
    //      SDA_OUT();
    SDA_IN();    //SDA设置为输入
    for (BitCnt = 0; BitCnt < 8; BitCnt++)
    {
        Delay_us(2);
        SCL_RESET(); /*置时钟线为低,准备接收数据位*/
        Delay_us(4);
        SCL_SET(); /*置时钟线为高使数据线上数据有效*/
        Delay_us(4);
        retc = retc << 1;
        if (READ_SDA() == 1)
            retc = retc + 1; /*读数据位,接收的数据位放入retc中 */
        Delay_us(2);
    }
    SCL_RESET();
    Delay_us(2);
    return (retc);
}

是否应答

void Ack_I2c(uint8_t a)
{
    SDA_OUT();
    if (a == 0)
        SDA_RESET(); /*在此发出应答或非应答信号 */
    else
        SDA_OUT();
    Delay_us(2);
    SCL_SET();
    Delay_us(4);
    SCL_RESET(); /*清时钟线,钳住I2C总线以便继续接收*/
    Delay_us(2);
}

I2C发送单个字节

uint8_t ISendByte(uint8_t sla, uint8_t c)
{
    IIC_Start(); /*启动总线*/
    SendByte(sla); /*发送器件地址*/
    if (ack == 0)
        return (0);
    SendByte(c); /*发送数据*/
    if (ack == 0)
        return (0);
    IIC_Stop(); /*结束总线*/
    return (1);
}

I2C发送两个字节

uint8_t ISendStr(uint8_t sla, uint8_t suba, uint8_t s)
{
    uint8_t i;
    uint8_t no = 1;
    IIC_Start(); /*启动总线*/

    SendByte(sla); /*发送器件地址*/
    if (IIC_Wait_Ack() == 0)
        return (0);

    SendByte(suba); /*发送器件子地址*/
    if (IIC_Wait_Ack() == 0)
        return (0);

    //for(i=0;i<no;i++)
    {
        SendByte(s); /*发送数据*/
        if (IIC_Wait_Ack() == 0)
            return (0);
        //  s++;
    }

    IIC_Stop(); /*结束总线*/

    return (1);
}

使用I2C读取数据

uint8_t IRcvStr(uint8_t sla, uint8_t suba)
{
    uint8_t i;
    uint8_t s;
    uint8_t no = 1;
    IIC_Start(); /*启动总线*/

    SendByte(sla); /*发送器件地址*/
    if (IIC_Wait_Ack() == 0)
        return (0);

    SendByte(suba); /*发送器件子地址*/
    if (IIC_Wait_Ack() == 0)
        return (0);

    IIC_Start();
    SendByte(sla + 1);
    if (IIC_Wait_Ack() == 0)
        return (0);

    s = RcvByte(); /*发送数据*/
    Ack_I2c(1); /*发送非应位*/
    IIC_Stop(); /*结束总线*/
    return s;
}

NCA9555端口初始化,并把16个端口设置成输入模式,读取按键值

#define PCA9555 0x40
IIC_Init();
ISendStr(PCA9555,0x06,0xff);// p0设置为输入,1为输入
ISendStr(PCA9555,0x07,0xff);// p1设置为输入//默认输出高
uint8_t buff8=0,buff9;
buff8 = ~IRcvStr(PCA9555,0x00);
buff9 = ~IRcvStr(PCA9555,0x01);

部分参考https://blog.csdn.net/u010632165/article/details/109188507?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170053238516800227447903%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=170053238516800227447903&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-2-109188507-null-null.142v96pc_search_result_base7&utm_term=I2C&spm=1018.2226.3001.4187

NCA9555是一款由ON Semiconductor公司生产的I2C总线控制器。这款芯片具有16个通用输入/输出引脚,可以广泛用于数字电路的控制和通信。NCA9555可以通过I2C总线连接到主控制器,使其能够与其他设备进行通信并控制其状态。 NCA9555数据手册是关于该芯片的详细技术文档,包含了关于其功能、引脚定义、时序图、寄存器描述、特性参数等方面的信息。数据手册提供了对该芯片的全面了解和应用指南,使工程师能够更好地使用它进行硬件设计和编程。 数据手册中包含了NCA9555的引脚图和引脚功能描述,这有助于工程师正确地连接芯片,以及了解每个引脚的作用。时序图显示了各个操作的时序要求,帮助工程师进行正确的时序设计,以确保芯片正常工作。 此外,数据手册还包含了NCA9555的寄存器描述,详细说明了各个寄存器的功能和配置方法,通过对这些寄存器的编程,可以实现对芯片功能的灵活控制。特性参数表列出了芯片的电气特性和性能指标,包括供电电压范围、工作温度范围、IO口电流能力等,这些参数对于设计和测试过程中的性能评估非常重要。 总之,NCA9555数据手册是理解和应用该芯片的重要参考文献。通过仔细阅读和研究数据手册,工程师可以更好地了解NCA9555的特性和功能,并能够更加有效地将其应用于电路设计和系统集成中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值