PAGE1
PAGE1
I2C通信
介绍
I2C(Inter-IntegratedCircuit)通信协议是一种简单的双向同步串行总线,用于连接微控制器和各种外部设备。I2C总线由两根线组成:SCL(串行时钟线)和SDA(串行数据线)。这种协议广泛应用于各种传感器、显示器、存储器等设备的通信中,因为它只需要少量的引脚,并且支持多设备通信。
在ArduinoUno中,I2C通信由内置的TWI(Two-WireInterface)模块实现。TWI模块使用两个引脚(A4和A5)来实现I2C通信。其中,A4引脚连接到SDA,A5引脚连接到SCL。
I2C通信的基本原理
I2C总线上的设备分为两类:主设备和从设备。主设备负责启动通信并生成时钟信号,从设备则响应主设备的请求。I2C通信的基本步骤如下:
启动信号:主设备拉低SDA线,然后拉低SCL线。
发送地址:主设备发送7位的从设备地址和1位的读/写位。
发送/接收数据:主设备和从设备之间交换数据,每次传输一个字节。
停止信号:主设备拉低SCL线,然后释放SDA线。
I2C数据传输
I2C协议使用8位数据传输。数据在时钟的上升沿被捕获。每一字节数据传输后,接收方需要发送一个应答位(ACK),表示数据已成功接收。如果从设备无法接收数据,它会发送一个非应答位(NACK)。
ArduinoUno上的I2C通信
ArduinoUno提供了两个库来处理I2C通信:Wire.h库用于主设备和从设备的通信,TWI.h库则提供了更底层的控制。本教程主要使用Wire.h库,因为它更简单易用。
Wire库的使用
Wire.h库提供了以下主要函数:
Wire.begin():初始化I2C通信,作为主设备或从设备。
Wire.beginTransmission(address):开始向指定地址的从设备发送数据。
Wire.write(value):写入一个字节的数据。
Wire.endTransmission():结束数据传输。
Wire.requestFrom(address,quantity):从指定地址的从设备请求数据。
Wire.read():读取一个字节的数据。
Wire.onReceive(function):设置一个函数,当从设备接收到数据时调用。
Wire.onRequest(function):设置一个函数,当从设备被请求发送数据时调用。
示例:主设备与从设备通信
主设备代码
下面是一个主设备代码示例,该代码向一个从设备发送数据并读取响应。
#includeWire.h
//从设备地址
#defineSLAVE_ADDRESS0x04
voidsetup(){
//初始化I2C通信
Wire.begin();
//初始化串口通信,用于调试
Serial.begin(9600);
Serial.println(I2CMasterInitialized);
}
voidloop(){
//向从设备发送数据
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write(H);//发送字符H
Wire.endTransmission();
//从从设备请求数据
Wire.requestFrom(SLAVE_ADDRESS,1);//请求1个字节的数据
if(Wire.available()){
charc=Wire.read();//读取数据
Serial.print(Receivedfromslave:);
Serial.println(c);//打印接收到的数据
}
delay(1000);//每秒执行一次
}
从设备代码
下面是一个从设备代码示例,该代码接收主设备发送的数据并发送一个响应。
#includeWire.h
//从设备地址
#defineSLAVE_ADDRESS0x04
voidsetup(){
//初始化I2C通信,设置从设备地址
Wire.begin(SLAVE_ADDRESS);
//设置接收数据的回调函数
Wire.onReceive(receiveEvent);
//设置发送数据的回调函数
Wire.onRequest(sendEvent);
//初始化串口通信,用于调试
Serial.begin(9600);
Serial.println(I2CSlaveInitialized);
}
void