I2C总线

目录

基本原理

总线结构

上拉电阻

信号电平

速度

STC8H芯片I2C引脚

I2C开发流程

STC8H的I2C配置

STC8H的I2C读取

STC8H的I2C写入

2C地址问题

设备地址

从设备寄存器地址

I2C通讯流程(了解)


基本原理

I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路之间进行数据交换。它最初由飞利浦公司(Philips)开发,现已成为一种通用的串行通信协议,被广泛应用于各种电子设备和嵌入式系统中。

总线结构

I2C总线包括两根信号线:SDA(串行数据线)和SCL(串行时钟线)。这两根信号线共用一个总线,因此在总线上可以连接多个设备。在I2C总线上,每个设备都有一个唯一的地址,用于标识设备。

SCL线是时钟线,用于控制数据传输的速度和时序;SDA线是数据线,用于传输实际的数据.

设备的地址通常是由设备制造商确定的,并在设备的数据手册中公布。

总之我们搞明白几个关键名词就可以:

  1. Master: 主设备。通常是主控MCU
  2. Slave:从设备。通常是功能芯片,例如RTC时钟,陀螺仪,温湿度等等。
  3. SCL:时钟线,控制数据传输的速度和时序。
  4. SDA:数据线。传输数据的。
  5. 地址:从设备地址。主设备通过地址进行访问。在总线中,每个从设备地址唯一。
上拉电阻

在I2C总线中,上拉电阻的大小通常是由以下几个因素决定的:

  1. 总线长度:总线长度越长,上拉电阻的阻值就应该越小,以保证信号的稳定性。这是因为,总线长度越长,线路上的电容就越大,需要更多的电流来充电和放电,因此上拉电阻的阻值也应该相应地减小。
  2. 总线上的设备数量:总线上连接的设备数量越多,需要更大的电流来充电和放电,以确保信号的稳定性。因此,当总线上连接的设备数量增加时,上拉电阻的阻值也应该相应地减小。
  3. 总线上设备的最高工作频率:I2C总线的时钟频率通常在100kHz到400kHz之间。如果总线上的设备需要使用更高的时钟频率,则上拉电阻的阻值应该相应地减小,以确保设备能够在规定的时间内完成数据的传输。

总的来说,I2C总线中上拉电阻的大小需要根据具体的情况来确定,以保证总线的稳定性和可靠性。一般来说,上拉电阻的阻值应该在1kΩ到10kΩ之间。

信号电平

I2C总线的信号电平是基于器件的供电电压而定的,通常为3.3V或5V。在I2C总线上,SDA和SCL信号线都是开漏模式,因此需要外接上拉电阻,以避免信号电平的不确定性。(默认高电平)

速度

I2C总线的速度是由其时钟频率决定的。I2C总线的时钟频率通常在100kHz到400kHz之间,其中100kHz是标准模式(Standard Mode),400kHz是快速模式(Fast Mode)。

  • 在标准模式下,I2C总线的时钟频率为100kHz,数据传输速率最高可以达到每秒约10kbps。标准模式适用于大多数的应用场景,可以满足许多设备的数据传输需求。
  • 在快速模式下,I2C总线的时钟频率为400kHz,数据传输速率最高可以达到每秒约40kbps。快速模式适用于一些需要更高速度的应用场景,例如传感器数据采集等。

此外,I2C总线还支持更高速度的高速模式(High Speed Mode)和超高速模式(Ultra-Fast Mode),它们的时钟频率分别为1MHz5MHz。这些高速模式通常用于一些需要非常高速数据传输的应用场景。

需要注意的是,总线的速度不仅受时钟频率的影响,还受到总线长度、电容负载、上拉电阻大小等因素的影响。因此,在实际应用中,需要根据具体情况来确定总线的速度以确保数据传输的稳定性和可靠性。

STC8H芯片I2C引脚

STC8H内置了一组I2C接口。

I2C接口

SCL

SDA

I2C1

P1.5

P1.4

P2.5

P2.4

P3.2

P3.3

I2C开发流程

总结起来,I2C总线编程开发步骤为以下:

  1. 引脚功能配置
  2. I2C配置
  3. 总线数据读取或写入

I2C引脚配置为开漏(OD)模式

基本上所有的芯片平台都是这种流程,具体的代码写法可能有所差异,但是道理相通。

STC8H的I2C配置

记得开启扩展寄存器使能:

记得开启扩展寄存器使能:

EAXSFR();

配置IO口为开漏模式

P3_MODE_OUT_OD(GPIO_Pin_2 | GPIO_Pin_3);

以下是STC8H的I2C配置代码。

  1. I2C.c I2C.h
  2. NVIC.c NVIC.h
  3. Switch.h
/****************  I2C初始化函数 *****************/
void	I2C_config(void)
{
	I2C_InitTypeDef		I2C_InitStructure;

	I2C_InitStructure.I2C_Mode      = I2C_Mode_Master;	//主从选择   I2C_Mode_Master, I2C_Mode_Slave
	I2C_InitStructure.I2C_Enable    = ENABLE;			//I2C功能使能,   ENABLE, DISABLE
	I2C_InitStructure.I2C_MS_WDTA   = DISABLE;			//主机使能自动发送,  ENABLE, DISABLE
	I2C_InitStructure.I2C_Speed     = 13;				//总线速度=Fosc/2/(Speed*2+4),  
                                                        // 400k, 24M => 13
                                                        // 100k, 24M => 58
	I2C_Init(&I2C_InitStructure);
	NVIC_I2C_Init(I2C_Mode_Master,DISABLE,Priority_0);	//主从模式, I2C_Mode_Master, I2C_Mode_Slave; 中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

	I2C_SW(I2C_P33_P32);					//I2C_P14_P15,I2C_P24_P25,I2C_P33_P32
}
  • I2C_MODE:模式,当前是Master还是Slave。
  • I2C_Speed: 速度。100k或者400k,通过总线速度=Fosc/2/(Speed*2+4)公式计算。
STC8H的I2C读取

stc8h提供了库函数,对I2C进行读取和写入。

标准的读数据帧:

//========================================================================
// 函数: void I2C_ReadNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)
// 描述: I2C读取数据函数.
// 参数: dev_addr: 设备地址, mem_addr: 存储地址, *p读取数据存储位置, number读取数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_ReadNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)   /*  DeviceAddress,WordAddress,First Data Address,Byte lenth   */
{
	Start();                                //发送起始命令
	SendData(dev_addr);                     //发送设备地址+写命令
	RecvACK();
	SendData(mem_addr);                     //发送存储地址
	RecvACK();
	Start();                                //发送起始命令
	SendData(dev_addr|1);                   //发送设备地址+读命令
	RecvACK();
	do
	{
		*p = RecvData();
		p++;
		if(number != 1) SendACK();          //send ACK
	}
	while(--number);
	SendNAK();                              //send no ACK	
	Stop();                                 //发送停止命令
}
STC8H的I2C写入

标砖的写数据帧:

库函数中的写入 I2C_WriteNbyte

//========================================================================
// 函数: void I2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)
// 描述: I2C写入数据函数.
// 参数: dev_addr: 设备地址, mem_addr: 存储地址, *p写入数据存储位置, number写入数据个数.
// 返回: none.
// 版本: V1.0, 2020-09-15
//========================================================================
void I2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number)  /*  DeviceAddress,WordAddress,First Data Address,Byte lenth   */
{
	Start();                                //发送起始命令
	SendData(dev_addr);                     //发送设备地址+写命令
	RecvACK();
	SendData(mem_addr);                     //发送存储地址
	RecvACK();
	do
	{
		SendData(*p++);
		RecvACK();
	}
	while(--number);
	Stop();                                 //发送停止命令
}

2C地址问题

开发过程中,经常有address问题。由于翻译问题,和一些程序员编码命名问题,导致我们经常把address概念混淆。

通常我们关心的地址有:

  1. 设备地址:具体说法就是从设备的访问地址。
  2. 设备中要访问的地址:从设备中的寄存器地址。
设备地址

设备地址其实包含了两个地址,一个是读取从设备时的地址,一个是向从设备写入数据时的地址。这两个地址还不一样。这两个地址的来源需要翻看从设备的芯片手册,进行查看。

设备地址是8个位的,最后一位表示读还是写,1表示读,0表示写。(1读0写这个是默认的,但也不排除一些奇葩厂商芯片设计自定义反向操作,一切以实际为准)

上图中,就是一个I2C的从设备地址,最后一位决定是读还是写。

我们在查询用户手册的过程中,必须确认这个地址,但通常会碰到一些问题:

  1. 只提供一个地址。

通常会明确说是读地址还是写地址,一定要查阅清楚。还有就是只提供了一个地址,没有明确说明通常是前七位组成的地址。

  1. 1种类型的从设备多个串联。一种类型的芯片通常地址是相同的,但是要访问具体的从设备需要唯一地址,否则不能正常工作。这个时候需要芯片支持地址扩展。
  2. 多种类型的从设备地址相同。这个就需要从设备可以配置改地址的方式。
从设备寄存器地址

通常我们通过I2C总线要去写入或者读取的就是这些寄存器地址。对于寄存器地址数据含义,需要阅读芯片手册。

I2C通讯流程(了解)

对于一些已经提供了库函数的芯片平台,使用I2C是非常容易的,不要从底层做起,因为有良好的API支持。

但是对于没有支持的,或者是需要清楚的了解过程的,需要去理解这个流程。

I2C通信流程如下:

  1. 主设备发送起始信号(Start)。
  2. 主设备发送从设备地址和读/写位,请求与从设备建立通信。
  3. 从设备返回应答信号(ACK)。
  4. 主设备发送要读/写的数据。
  5. 从设备返回应答信号(ACK)。
  6. 通信结束时,主设备发送停止信号(Stop)。

下面是每个步骤的详细说明:

  1. 起始信号(Start):主设备通过拉低SDA线而将SDA线从高电平转换成低电平,同时将SCL线拉高。这表示通信开始了。
  2. 从设备地址和读/写位:主设备发送从设备地址和读/写位,告诉从设备要进行读或写操作。I2C总线支持多个从设备,因此地址是从设备的标识符。地址的最低位表示通信模式,0表示写模式,1表示读模式。
  3. 应答信号(ACK):从设备接收到地址后,会发送应答信号(ACK)表示已经准备好接收或发送数据。如果没有设备响应主设备发送的地址,则通信失败。
  4. 发送数据:主设备向从设备发送要写入的数据。
  5. 应答信号(ACK):从设备接收到数据后,发送应答信号(ACK)表示已经成功接收数据。如果从设备没有成功接收到数据,将发送非应答信号(NACK)。
  6. 停止信号(Stop):通信结束后,主设备发送停止信号(Stop),将SDA线从低电平拉到高电平,同时将SCL线拉高。这表示通信结束了。

需要注意的是,在步骤2和步骤4中,如果主设备发送的数据超过了从设备的缓存,从设备将发送非应答信号(NACK)表示数据传输失败。主设备在收到非应答信号(NACK)后将终止通信。

需要注意的是,在步骤2和步骤4中,如果主设备发送的数据超过了从设备的缓存,从设备将发送非应答信号(NACK)表示数据传输失败。主设备在收到非应答信号(NACK)后将终止通信。

81.png

image.png


 

  • 15
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux I2C总线寄存器是用于控制和配置I2C总线通信的寄存器集合。I2C(Inter-Integrated Circuit)总线是一种串行通信协议,用于在多个设备之间进行数据交换。 在Linux系统中,I2C总线寄存器位于内核空间中的驱动程序中,由内核提供支持。通过这些寄存器,可以实现对I2C总线的读写操作、设备的探测和配置等功能。 I2C总线寄存器主要包括如下几个方面的功能: 1. 控制寄存器:用于设置I2C总线的工作模式和速率等参数。通过控制寄存器可以选择I2C总线的主从模式,设置传输速率和时钟频率等。 2. 数据寄存器:用于存储需要传输的数据。在写操作中,数据会被写入数据寄存器,然后通过I2C总线发送给目标设备。在读操作中,目标设备的数据会被存储在数据寄存器中,然后从数据寄存器中读取出来。 3. 状态寄存器:用于检测I2C总线的状态。通过状态寄存器可以判断I2C总线是否忙碌、传输是否成功等。状态寄存器中的标志位可以提供给驱动程序检测和判断使用。 4. 地址寄存器:用于设置目标设备的地址。在I2C总线中,每个设备都有一个唯一的地址,通过地址寄存器可以设置要读写的目标设备的地址。 总的来说,Linux I2C总线寄存器提供了对I2C总线通信的底层控制和管理能力,通过对这些寄存器的操作可以实现I2C设备的读写操作、总线的配置和控制等功能。同时,通过驱动程序对这些寄存器进行访问和操作,可以方便地实现I2C设备的驱动开发和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值