当前位置: 首页 > news >正文

嵌入式学习 day52 IMX6ULL裸机开发-I2C

一、I2C

        又称I2C,是是IICBus简称,所以中文应该叫集成电路总线,是一种半双工、串行、同步、芯片与芯片之间的通信,通常只有一根数据总线,采用主从应答方式

二、总线

        上图所示是IIC的总线的使用场景,所有挂载在IIC总线上的设备都有两根信号线,一根是数据线SDA,另一根是时钟线SCL。这两个信号线都是双向的。作为一种通信方式,IIC总线在某一时刻,总线只允许有一个设备处于发送状态,所发生的数据被总线上所有的设备所接收。IIC通信协议包含有设备地址,只有发送方携带的地址与某个接收方的地址相同时,接收方才真正执行相关的指令。

注:1、上拉电阻:

        IIC总线规定,设备在空闲时,两根总线都处于高电平状态。为保证这种状态,数据线SDA和时钟线SCL都要外接上拉电阻。对于I.MX来说,这个上拉电阻也可以在引脚电器配置中设置。

        2、线与特性(逻辑与)
AB总电平
111
010
100
000

        3、释放总线:

        将电平置为高电平,则数据线上的电平由对方决定

三、IIC通信时序

        1、起始信号

        IIC总线上连接的若干设备中,每次通信前,发送方首先发送一个“起始”信号,其实信号就是在SCL为高电平时,SDA发送一个低电平。当其它设备接收到这个其实信号后,将进行一次“总线仲裁”。意思就是设备(除发送其实信号的那个设备以外的)都将处于聆听状态。

        2、数据传输

        IIC总线进行数据传送时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定。只有在时钟线(SCL)上的信号为低电平期间,数据线(SCL)上的高电平或低电平状态才允许变化。同时,SCL信号由数据启动发送的设备提供。输出到数据线(SDA)上的每个字节必须是8位。数据传送时,先传送最高位(MSB),后传送最低位(LSB)。

        3、应答

        发送器每发送一个字节(8个bit),就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。 主机SCL拉高,读取从机SDA的电平。对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。
(1)数据线(SDA)为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节。
(2)数据线(SDA)为高电平时,规定为非应答位(NACK),表示接收器没有成功接收该字节。

        4、终止信号

         当发送方发送完最后一个bit后,需要发送一个结束标志来终止整个通信过程。当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。

        5、完整时序

四、读写时序

        1、写时序:

        

        首先由主机发送一个起始位,主机再以高位先行原则发送7个bit位的设备地址和1个bit位的数据流向位(0,表示主机发从机收),从机应答一个ACK,主机发送存入数据的寄存器地址,从机再次应答ACK,主机发送数据,从机应答ACK,循环发送n个数据(每个数据两个字节),n不大于8个,从机应答ACK,主机发送停止信号

        2、读时序

        首先由主机发送一个起始位,主机再以高位先行原则发送7个bit位的设备地址和1个bit位的数据流向位(0,表示主机发从机收),从机应答一个ACK,主机发送读取数据的寄存器地址,从机再次应答ACK,主机再发送一个起始位,再以高位先行原则发送7个bit位的设备地址和1个比特位的数据流向位(1,表示主机收从机发),从机应答一个ACK,从机向主机发送数据,主机应答一个ACK,直到最后一个数据发送完成后,主机应答一个NACK表示数据读取完毕,主机再发送停止信号

五、I2C的时钟

        由时钟配置的66M

六、I2C寄存器

                1、IFDR(分频寄存器)

        2、I2CR(控制寄存器)

        3、I2SR(状态寄存器)

        4、数据寄存器

七、步骤

        1、初始化

        (1)引脚复用功能和电器属性

        (2)寄存器设置

void init_i2c1(void)

{

    IOMUXC_SetPinMux(IOMUXC_UART4_RX_DATA_I2C1_SDA,1);

    IOMUXC_SetPinMux(IOMUXC_UART4_TX_DATA_I2C1_SCL,1);

    IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA,0x70b0);

    IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL,0x70b0);

    I2C1->I2CR &= ~(1 << 7);

    I2C1->IFDR = 0x15;

    I2C1->I2CR |= (1 << 7);

}

        2、写数据

        

void i2c_write(I2C_Type *base,unsigned char dev_addr,unsigned char reg_addr,const unsigned char* data,unsigned int len)

{

    base->I2SR &= ~((1 << IAL) | (1 << IIF));

    while((base->I2SR & (1 << ICF)) == 0);

    base->I2CR |= (1 << MSTA) | (1 << MTX);

    base->I2CR &= ~(1 << TXAK);

   

    base->I2SR &= ~(1 << IIF);

    base->I2DR = dev_addr << 1;

    while((base->I2SR & (1 << IIF)) == 0);

   

    base->I2SR &= ~(1 << IIF);

    base->I2DR = reg_addr;

    while((base->I2SR & (1 << IIF)) == 0);

    while(len--)

    {

        base ->I2SR &= ~(1 << IIF);

        base->I2DR = *data++;

        while((base->I2SR & (1 << IIF)) == 0);

    }

    base->I2CR &= ~(1 << MSTA);

    int t = 0;

    while((base->I2SR & (1 << IBB)) != 0 && t < 10)

    {

        ++t;

        delay_us(100);

    }

}

        3、读数据

void i2c_read(I2C_Type *base,unsigned char dev_addr,unsigned char reg_addr,unsigned char* data,unsigned int len)

{

    base->I2SR &= ~((1 << IAL) | (1 << IIF));

    while((base->I2SR & (1 << ICF)) == 0);

   

    base->I2CR |= (1 << MSTA) | (1 << MTX);

    base->I2CR &= ~(1 << TXAK);

    base->I2SR &= ~(1 << IIF);

    base->I2DR = dev_addr << 1;

    while((base->I2SR & (1 << IIF)) == 0);

    base->I2SR &= ~(1 << IIF);

    base->I2DR = reg_addr << 1;

    while((base->I2SR & (1 << IIF)) == 0);

    base->I2CR |= (1 << RSTA);

    base->I2SR &= ~(1 << IIF);

    base->I2DR = dev_addr << 1 | (1 << 0);

    while((base->I2SR & (1 << IIF)) == 0);

    base->I2CR &= ~(1 << MTX);

    base->I2SR &= ~(1 << IIF);

    if(1 == len)

    {

        base->I2CR |= (1 << TXAK);

    }

    *data = base->I2DR;

    while(len--)

    {

        while((base->I2SR & (1 << IIF)) == 0);

        base->I2SR &= ~(1 << IIF);

        if(1 == len)

        {

            base->I2CR |= (1 << TXAK);

        }

        else if(0 == len)

        {

            base->I2CR &= ~((1 << MSTA) | (1 << TXAK));

            int t = 0;

            while((base->I2SR & (1 << IBB)) != 0 && t < 10)

            {

                ++t;

                delay_us(100);

            }

        }

        *data++ = base->I2DR;

    }

}

http://www.lryc.cn/news/622466.html

相关文章:

  • Redis核心应用场景及代码案例
  • WordPress 7B2主题,在使用PHP 8.0+出现502的解决办法。
  • 【机器学习深度学习】OpenCompass 评测指标全解析:让大模型评估更科学
  • platform总线注册流程分析
  • 洛谷 P2842 纸币问题 1 -普及-
  • C++类与对象核心知识点全解析(下)
  • 模板方法模式C++
  • 机器翻译:模型微调(Fine-tuning)与调优详解
  • JavaWeb开发_Day13
  • vue3相关基础
  • MySQL知识解析
  • linux-----------------锁
  • week1-[一维数组]传送
  • 【Spring框架】SpringAOP
  • 六大主流负载均衡算法
  • Java项目基本流程(四)
  • Python day45
  • lcm通信库介绍与使用指南
  • 【121页PPT】锂膜产业MESERP方案规划建议(附下载方式)
  • 【学习嵌入式day-25-线程】
  • 华测科技的3D GPR数据分析
  • 前瞻性技术驱动,枫清科技助力制造企业借助大模型完成生产力转化
  • 2025戴尔科技峰会:破局者的力量与智慧
  • 【C#补全计划】事件
  • PCA降维理论详解
  • 学习嵌入式之硬件——I2C
  • 系统介绍pca主成分分析算法
  • C语言:指针(5)
  • 智能指针:C++内存管理的利器
  • c++程序示例:多线程下的实例计数器