I2C接口

article/2025/11/7 4:04:44

一、I2C总线协议内容

1. I2C总线引脚定义

SDA (I2C数据引脚)

CLK (I2C数据引脚)

 

2. I2C总线物理连接

I2C总线物理连接如下图所示,SDA和CLK连接线上连有两个上拉电阻,当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低。

 

二、I2C总线的数据传送

1. 数据位的有效性规定

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化

1 scl处于高电平的时候,如果sda处于低电平:传输数据0,sda处于高电平:传输数据1

2.在scl处于高电平的时候,sda用来传输数据,必须保持电平稳定

3.如果要产生数据即sda需要变化时,只能在scl处于低电平的时候

 

 

2. 起始和终止信号

SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。 

1. 信号的发起和终止,由主机发起,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

 

2. scl处于高电平的时候,sda由高->低的跳变, 表示发起传输,产生起始信号s,

如果低->高跳变,表示终止传输,产生终止信号p

3. 在中间,可以正常传输数据

4. 连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号

5. 如果出现,从机在接收到一部分数据后需要对数据处理,如何因对这种情况?

接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平从而使主机处于等待状态【只有scl处于高电平的时候,主机才会去匹配sda的电平,接收下一个bit】。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。

 

3. 数据传送格式

1)字节传送与应答

每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)

主机每次发起通信后,第一个字节,往往是从设备的地址【7位】+RW【寻址信号】

 

1. 由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。

2. 如果从机对主机进行了应答,但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”【sda处于高电平】通知主机,主机则应发出终止信号以结束数据的继续传送。

3   当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”【拉高sda】来实现的。然后,从机释放SDA线,以允许主机产生终止信号

 

2)数据帧格式

I2C总线上传送的数据信号是广义的,即包括地址信号,又包括真正的数据信号。

在起始信号后必须传送一个从机的地址(7位),第8位数数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。每次数据传送总是由主机产生的终止信号结束。在总线的一次数据传送过程中,可以有以下几种组合方式:

a) 主机向从机发送数据:

注1:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。

A表示应答, A非表示非应答(高电平)。S表示起始信号,P表示终止信号。

注2:I2C总线协议有明确的规定:采用7位的寻址字节(寻址字节是起始信号后的第一个字节)

b) 主机从从机中读取数据

c)主机从从机中既有读数据也有写数据

 

三、I2C发送与接收数据时序图

注:红色框代表主机拥有sda控制权,绿色框代表从机拥有sda控制权

 

1. 主机发送数据

2. 主机读取数据

 

四、Exynos4412-I2C控制器

1. I2C总线控制器概述

Exynos4412有9个I2C总线控制器,其中8个是通用I2C控制器,另1个I2C控制器是专门位HDMI提供。如下图所示:Exynos4412控制器通过读写寄存器来实现I2C通信,I2CCON寄存器和I2CSTAT寄存器用来配置、控制I2C控制器,并显示控制器状态。

 

2. I2C控制器寄存器详解

A)I2CCONn寄存器

B) I2CSTATn寄存器

 

C)I2CDSn 寄存器

该寄存器用来收发数据

 

五. I2C控制器流程

1. 配置主机发送模式

1)配置对应的I2C引脚的功能为SDA和SCL

2) 设置I2CCON[6]配置I2C发送时钟和中断使能

3)设置I2C发送使能,I2CSTAT[4]= 0b1

2. 将要通信的I2C从机的地址和读写位写入I2CDSn 寄存器

3. 将0xF0写入I2CSTAT寄存器

I2CSTAT[7:6] =0xb11设置4412模式为主机发送模式

I2CSTAT[5] = 0xb1,该位写1,发送开始信号

I2CSTAT[4] = 0xb1写1,使能I2C串口发送

4. I2C控制器发出开始信号后,在2中写入的I2CDS寄存器地址自动发送到SDA总线上,用来寻找从机。

5. 在ACK周期后,I2C控制器发生中断,I2CSTAT[4] 被自动置1,I2C传输暂停

6. I2C数据通信是否结束,结束跳转到10,没有结束跳转到7

7.  将要传输的数据写入I2CDS寄存器准备发送。

8. 清除中断标志位,通过向I2CCON[4]中写0实现

9. 清除中断标志位后,I2CDS寄存器内的数据就开始发送到SDA总线上。发送完成后,跳转到5。

10. 将0XD0写入I2CSTAT寄存器。

I2CSTAT[7:6] =0xb11设置4412模式为主机发送模式

I2CSTAT[5] = 0x0,该位写0,发送停止信号

I2CSTAT[4] = 0xb1,使能I2C串口发送

11. 清除中断标志位,通过向I2CCON[4]中写0实现

12. 延时等待一段时间,使得停止信号生效,I2C通信结束

 

I2C控制器主机发送模式流程图如下:

 

六、I2C接口读取MPU6050传感器数据测试实验

1. 实验目的:略

2. 实验原理:



3. 实验内容

Exynos4412通过I2C总线读取MPU6050的Z轴角速度结果并打印。首先要配置Exynos4412的I2C5(原理图连接I2C5)控制器,配置GPIO为I2C功能模式,再根据MPU6050芯片手册提供的芯片地址、寄存器说明和时序对MPU6050操作。

1)MPU6050的I2C地址


在电路图中AD0电平为0,所以MPU6050的I2C地址为0x68

 

2)在MPU6050手册中,有以下几种操作时许,分别是字节写时序、页写时序、当前地址读时序、随机地址读时序和顺序读时序。

A)字节写时序(Byte Write)如下图所示:

 

字节写时序依次要发送器件地址和读写位(AD + W)、数据写入地址(RA)和写入的8位数据(DATA)

 

A)字节读时序(Byte Read)如下图所示:

字节读时序依次要发送器件地址和读写位(AD + W)、数据读取地址(RA)。因为要转换数据流向,因此重新发送开始信号(S),接着发送器件地址和读写位(AD + R)、读取数据(DATA)。

七. 使用I2C控制器读取MPU6050数据示例代码如下:



#include "exynos_4412.h"


//****************************************
// MPU6050内部地址
//****************************************
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0x68 //IIC写入时的地址字节数据,+1为读取


void mydelay_ms(int time);
void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data);
void iic_read(unsigned char slave_addr, unsigned char addr, unsigned char *data);
void MPU6050_Init ();
int get_data(unsigned char addr);


/*-------------------------MAIN FUNCTION------------------------------*/
/**********************************************************************
 * @brief Main program body
 * @param[in] None
 * @return int
 **********************************************************************/
int main(void)
{
int data;


unsigned char zvalue;


GPB.CON = (GPB.CON & ~(0xF<<12)) | 0x3<<12; // GPBCON[3], I2C_5_SCL
GPB.CON = (GPB.CON & ~(0xF<<8)) | 0x3<<8; // GPBCON[2], I2C_5_SDA


mydelay_ms(100);
uart_init();


/*---------------------------------------------------------------------*/
I2C5.I2CSTAT = 0xD0;        //设置I2CM Master 输出模式,停止信号,使能I2C串口输出
I2C5.I2CCON &= ~(1<<4); /*clean interrupt pending bit  */
/*---------------------------------------------------------------------*/


mydelay_ms(100);
MPU6050_Init();
mydelay_ms(100);


printf("\n********** I2C test!! ***********\n");


while(1)
{
//Turn on
GPX2.DAT |= 0x1 << 7;


data = get_data(GYRO_ZOUT_H);
printf(" GYRO --> Z <---:Hex: %0x", data);
printf("\n");


mydelay_ms(20);
//Turn off
GPX2.DAT &= ~(0x1 << 7);
mydelay_ms(500);
}
return 0;
}


void mydelay_ms(int time)
{
int i, j;
while(time--)
{
for (i = 0; i < 5; i++)
for (j = 0; j < 514; j++);
}
}




/**********************************************************************
 * 函数功能: iic 向特定地址写一个字节
 * @param[in] slave_addr,iic从机地址
 * addr, 芯片内部特定地址
 * data,写入的数据
 * @return None
 **********************************************************************/
void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)
{
I2C5.I2CDS = slave_addr << 1 | 0x0;
I2C5.I2CCON = 1<<7 | 1<<6 | 1<<5;/*ENABLE ACK BIT, PRESCALER:512, ,ENABLE RX/TX */
I2C5.I2CSTAT = 0x3 << 6 | 1<<5 | 1<<4;/*Master Trans mode ,START ,ENABLE RX/TX ,*/
while(!(I2C5.I2CCON & (1<<4)));


I2C5.I2CDS = addr;
I2C5.I2CCON &= ~(1<<4); //Clear pending bit to resume.
while(!(I2C5.I2CCON & (1<<4)));


I2C5.I2CDS = data; // Data
I2C5.I2CCON &= ~(1<<4); //Clear pending bit to resume.
while(!(I2C5.I2CCON & (1<<4)));


I2C5.I2CSTAT = 0xD0; //stop


I2C5.I2CCON &= ~(1<<4);


mydelay_ms(10);
}
/**********************************************************************
 * @brief iic 从特定地址读取一个字节的数据
 * @param[in] slave_addr,iic从机地址
 * addr, 芯片内部特定地址
 * @return None
 **********************************************************************/
void iic_read(unsigned char slave_addr, unsigned char addr, unsigned char *data)
{
I2C5.I2CDS = slave_addr << 1 | 0x0;


I2C5.I2CCON = 1<<7 | 1<<6 | 1<<5;/*ENABLE ACK BIT, PRESCALER:512, ,ENABLE RX/TX */
I2C5.I2CSTAT = 0x3 << 6 | 1<<5 | 1<<4;/*Master Trans mode ,START ,ENABLE RX/TX ,*/
while(!(I2C5.I2CCON & (1<<4)));


I2C5.I2CDS = addr;
I2C5.I2CCON &= ~(1<<4); //Clear pending bit to resume.
while(!(I2C5.I2CCON & (1<<4)));
I2C5.I2CSTAT = 0xD0; //stop




I2C5.I2CDS = slave_addr << 1 | 0x01; // Read
I2C5.I2CCON = 1<<7 | 1<<6 | 1<<5;/*ENABLE ACK BIT, PRESCALER:512, ,ENABLE RX/TX */


I2C5.I2CSTAT = 2<<6 | 1<<5 | 1<<4;/*Master receive mode ,START ,ENABLE RX/TX ,*/
while(!(I2C5.I2CCON & (1<<4)));


I2C5.I2CCON &= ~((1<<7) | (1<<4));/* Resume the operation  & no ack*/
while(!(I2C5.I2CCON & (1<<4)));//判断有没有收到data


I2C5.I2CSTAT = 0x90;
I2C5.I2CCON &= ~(1<<4); /*clean interrupt pending bit  */


*data = I2C5.I2CDS;
mydelay_ms(10);
}


/**********************************************************************
 * @brief MPU6050_Init program body
 * @param[in] None
 * @return None
 **********************************************************************/
void MPU6050_Init ()
{
iic_write(SlaveAddress, PWR_MGMT_1, 0x00); //设置使用内部时钟8M
iic_write(SlaveAddress, SMPLRT_DIV, 0x07); //设置陀螺仪采样率
iic_write(SlaveAddress, CONFIG, 0x06);     //设置数字低通滤波器
iic_write(SlaveAddress, GYRO_CONFIG, 0x18);//设置陀螺仪量程+-2000度/s
iic_write(SlaveAddress, ACCEL_CONFIG, 0x01);//设置加速度量程+-2g
}


/**********************************************************************
 * @brief get MPU6050 data program body
 * @param[in] addr
 * @return int
 **********************************************************************/
int get_data(unsigned char addr)
{
char data_h, data_l;
iic_read(SlaveAddress, addr, &data_h);
iic_read(SlaveAddress, addr+1, &data_l);
return (data_h<<8)|data_l;
}







 

 

 

 

 

 

 



http://chatgpt.dhexx.cn/article/PVApxdyv.shtml

相关文章

“如何成为阿里云P8架构师?“ ”当然是考取阿里云新版ACE认证啊”

**简介&#xff1a;**阿里云新版云计算架构师ACE认证全面重构上线&#xff01;为建立云计算生态领域含金量第一的专家级人才标准和认证体系&#xff0c;影响泛云生态高层次技术人才&#xff0c;阿里云历时一年&#xff0c;组织近百位专家&#xff0c;对云计算架构师ACE认证进行…

阿里云认证(ACA/ACP/ACE)的分类以及官网价格

阿里云认证分类&#xff1a; 阿里云认证分为三个等级&#xff0c;分别为初级(ACA)、中级(ACP)、高级&#xff08;ACE&#xff09; 下面还有很多的子分类 在子分类中&#xff0c;云计算是认证中最受欢迎的&#xff0c;无论是ACA云计算&#xff0c;还是ACP云计算&#xff0c;都…

阿里云ACA、ACP、ACE认证考试区别,报名入口及模拟试题分享

阿里云认证考试包含ACA、ACP、ACE三种认证类型&#xff0c;是阿里云针对不同产品类别、用户成长阶段、生态岗位&#xff0c;精心打造不同的认证考试。获得阿里云认证考试证书能够基于阿里云产品解决实际问题。获得更多阿里云生态下的就业机会。 助理工程师&#xff08;ACA&…

成为阿里云架构师的进阶之路——阿里云首批ACE认证通过者逸疏专访

自2018年3月阿里云发布云计算架构师ACE(Alibaba Cloud Certified Expert,阿里云认证高级工程师)级别认证后,上线不到3个月,吸引了近百位业界优秀从业者参与考试。获得阿里云ACE认证,对于业界资深架构师来说,是自身实力的最好证明。 阿里云大学致力于培养云生态链路上的…

阿里云P8架构师|历时4个月1次通关ACE认证

李东是我在阿里云厂商这边了解到第一个自学通过ACE认证P8架构师&#xff0c;现将他学习考证记录分享给大家 写在前面&#xff1a; 我是来自阿里云数字政府行业线的解决方案架构师李东。 2022年3月28日阿里云发布了新版ACE&#xff08;Alibaba Cloud Certified Expert - Cloud…

阿里云新版云计算架构师ACE认证专家解读会重磅来袭

简介&#xff1a;专家命题人非常解读 9600元全额代金券限量发放&#xff01;活动钉群&#xff1a;31889256。 3月28日&#xff0c;阿里云新版云计算架构师ACE认证正式升级发布&#xff0c;面向云架构师、解决方案架构师、资深运维/交付等人群&#xff0c;提供技术能力认证。自升…

通过新版阿里ACE认证,实验操作题你来解一下

大家都知道了哈&#xff0c;阿里云新版ACE认证&#xff0c;现在是云认证界的塔尖位置&#xff0c;因为要成功拿到新版ACE认证&#xff0c;需要破关斩将&#xff0c;三个守门的将&#xff0c;分别是笔试&#xff0c;实验操作&#xff0c;以及面试 1&#xff0c;笔试 相对实验操…

为什么我不建议在阿里云官网报考ACP/ACE认证?

考acp的时候刚开始以为直接在阿里云官网寻找课程备考报名就可以了,官方提供的课程应该没有问题,但是实际学习的时候发现,官方提供的内容虽然涵盖了大部分知识点,但是由于缺少对应的学习服务,学习效果上总是差强人意。 除了学习效果意外,再就是两个更重要的原因,贵且麻烦…

阿里云ACA、ACP、ACE认证考试常见问题

阿里云专业技术认证包含&#xff1a; 阿里云Apsara Clouder技能认证 阿里云助理工程师认证ACA级别&#xff08;Alibaba Cloud Certified Associate&#xff09; 阿里云专业工程师认证ACP级别&#xff08;Alibaba Cloud Certified Professional&#xff09; 阿里云基于岗位的…

阿里云的ACP认证与ACE认证含金量高吗?

该文章详细的介绍了阿里云认证。 云计算ACP认证介绍&#xff1a; 阿里云云计算专业认证(ACP 级-Alibaba Cloud Certification Professional)是面向使用阿里云云计算产品的架构、开发、运维类人员的专 业技术认证&#xff0c;主要涉及阿里云的计算、存储、网络、安全类的核心…

阿里云认证未来网络学院ACE公开课——30分钟掌握ACE考试通关攻略

简介&#xff1a;新版ACE通关攻略&#xff0c;这4点经验&#xff0c;帮你斩获高分&#xff01;入群即赠价值3000元ACP全套线上课资料包&#xff01;公开课钉群&#xff1a;44832770。 新版ACE通关攻略&#xff0c;这4点经验&#xff0c;帮你斩获高分 阿里云云计算架构师 ACE 认…

技能证里的天花板-阿里云云计算架构师ACE认证将全面升级!

近年来&#xff0c;随着国内数字化实践的不断深化&#xff0c;中国企业上云意识和积极性明显提高&#xff0c;上云比例和应用场景深度有所提升。根据亿欧智库2022年2月发布的《2021中国公有云服务商能力指数研究报告》指出&#xff1a;随着数字经济和新技术的发展&#xff0c;预…

阿里云ACE认证介绍

01-阿里云ACE认证概述 阿里云云计算架构师ACE认证是针对云架构师&#xff0c;解决方案架构师&#xff0c;云运维专家等技术人员的阿里云高级别技术认证。 通过该技术认证可以有效证明该认证人员具备丰富的需求分析能力&#xff0c;云架构设计能力&#xff0c;云架构部署实施能…

运营商大数据中建模到底是什么意义?

建模字面意思不难理解&#xff0c;就是通过不同企业的特殊需求来建立不同的数据采集模型&#xff01;前面我们说过运营商大数据具备T1的时效性和超前的准确性&#xff0c;之所以它具备这两点特性完全是因为运营商大数据的建模方式&#xff01; 第一种建模方式&#xff1a;网址和…

三网运营商大数据如何实现精准获客,稳定客户资源获取平台

在过去&#xff0c;对众多企业来说&#xff0c;销售获客的方法大多是来自于一些地推或者电话营销&#xff0c;然而在如今的时代&#xff0c;人们在线上获客已经成为常态&#xff0c;让获客的方式也有了更多的可能性&#xff0c;企业想在激烈的竞争中突出重围&#xff0c;就需要…

销售业绩迅速提升10倍的秘诀——运营商大数据精准

销售行业备受关注的焦点无非就是业绩&#xff0c;在互联网时代&#xff0c;你有没有感觉到企业的传统销售模式获客越来越艰难。有时候时间浪费了不说&#xff0c;还毫无效果&#xff0c;那今天我们来讲一下如何短时间之内让你的销售业绩提升十倍呢&#xff0c;必须跟得上大数据…

运营商大数据 | 打造新型获客模式 破除流量困局

大师彼得.德鲁克曾说&#xff0c;“企业存在的唯一目的就是创造顾客。” 互联网时代&#xff0c;维系企业存在的一大动力&#xff0c;就是流量&#xff0c;创造流量&#xff0c;无疑等于是创造顾客。 时下企业竞争的关键&#xff0c;也就是流量的竞争&#xff0c;在生产、销售…

运营商大数据是什么?

​ 1.以联通大数据为代表的运营商大数据&#xff0c;可以通过网站&#xff0c;网页&#xff08;同行的网站&#xff0c;自己的竞价推广网站&#xff0c;网页均可&#xff09;手机APP,400电话/固话&#xff0c;可以通过建模进行用户画像建立和分析&#xff0c;分析使用在手机和使…

【数方大数据】什么是三网运营商大数据精准获客?

【数方大数据】什么是三网运营商大数据精准获客&#xff1f; 三网运营商大数据是近两年来行业营销的有效手段。它主要是根据运营商的终端用户数据和企业的一些特点&#xff0c;达到准确获取客户、精准营销的目的。在中国&#xff0c;移动、联通和电信拥有超过10亿的用户。现在&…

各行业怎么利用运营商大数据精准获客?怎么建模比较好?

说到运营商大数据&#xff0c;相信大家都不陌生&#xff0c;我们常说的运营商大数据有联通&#xff0c;移动&#xff0c;电信三大运营商&#xff0c;但是怎么来选择这几个运营商&#xff0c;怎么来选择模型是企业不得不面临的问题。 我们知道大数据的获客原理是由基础属性上网标…