当前位置: 首页 > 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.dtcms.com/a/333473.html

相关文章:

  • 基于Spring Boot的智能民宿预订与游玩系统设计与实现 民宿管理系统 民宿预订系统 民宿订房系统
  • 蓝桥杯 二叉树
  • [ CSS 前端 ] 网页内容的修饰
  • linux下找到指定目录下最新日期log文件
  • liteflow
  • CSS从入门到精通完整指南
  • 【学习笔记】Java并发编程的艺术——第8章 Java中的并发工具类
  • Python工具箱系列(六十二)
  • 写作在学习中的重要性
  • 【完整源码+数据集+部署教程】脑部健康状态检测系统源码和数据集:改进yolo11-AIFI
  • 力扣top100(day04-05)--堆
  • **标题:发散创新之力,探索隐私计算的未来**隐私计算,作为当下数字化时代的热门话题,正受
  • MCP简单入门及简单操作案例(高德地图调用实现酒店查询天气查询等[Lima]示范)
  • 在执行部署脚本后,通过 ls -la 命令查看远程服务器文件时,显示的文件所有者是 games 而不是预期的 root 用户
  • 二、DOCKER常用命令
  • 最长递增子序列-dp问题+二分优化
  • Vue 侦听器(watch 与 watchEffect)全解析1
  • 【161页PPT】智慧方案企业数字化转型概述(课件)(附下载方式)
  • pcl法线估计的踩坑
  • 【GPT入门】第47课 大模型量化中 float32/float16/uint8/int4 的区别解析:从位数到应用场景
  • 《P1194 买礼物》
  • PyTorch的安装-CPU版本或者GPU安装有什么区别吗
  • 口播数字人免费API调用方案
  • Docker的相关知识探究详解
  • 【功能更新】“弹性互联网”正式上线Fusion WAN平台
  • Oracle按照特定列值排序和C#统计特定列值的所有行
  • 数据结构:N叉树 (N-ary Tree)
  • 【部署K8S集群】 1、安装前环境准备配置
  • Deepoc具身智能模型如何重塑康复辅助设备
  • Java中MybatisPlus使用多线程多数据源失效