以下基于江科大与普中科技学习I2C通讯
目录
4.1主机向从机发送数据, 数据传送方向在整个传送过程中不变;
4.3在传送过程中, 当需要改变传送方向时, 起始信号和从机地址都被重复产生一次, 但两次读/写方向位正好相反
一、介绍:
I2C( Inter- Integrated Circuit) 总线是由 PHILIPS 公司开发的两线式串行总线, 用于连接微控制器及其外围设备。 是微电子通信控制领域广泛采用的一种总线标准。 它是同步通信的一种特殊形式, 具有接口线少, 控制方式简单,器件封装形式小, 通信速率较高等优点。 I2C 总线只有两根双向信号线。 一根是数据线 SDA, 另一根是时钟线 SCL。 由于其管脚少, 硬件实现简单, 可扩展性强等特点, 因此被广泛的使用在各大集成芯片内。
二、I2C物理层:
2.1 连接方式:
2.2 特点:
- 由两条总线组成:SDA(数据线)、SCL(时钟线)
- 可连接多个通信主机和多个通信从机,可实现一主多从,多主多从模式。
- 每个连接到总线的设备都有一个地址,这个地址是独一无二的,主机可通过这个地址进行不同设备的访问。
- 每条总线前都有外接一颗上拉电阻,即防止开漏输出中的高阻态,固为稳定状态,上拉成高电平。
- 三种传输模式:标准:100kbit/s;快速:400kbit/s;高速:3.4Mbit/s
- 两种寻址方式:7位和10位。通常使用7位,使用7位字节寻址,其后跟着一位方向位。其中D7-D4固定位1010;D3-D1可寻地址,共有2的3次方个,8个地址,所以最大运与允许8个设备;D0即方向位(读写位),当为R(1),读位,位W(0),读位
三、I2C协议层:
在I2C通信中,供定义了五种通信方式:起始、停止、应答、发送、接收
发送/接收:在数据传输时,SCL为高电平时,SDA上的数据必须保持稳定。SCL为低电平 时,SDA上的电平状态才允许改变,每次传输以字节为单位,字节数则不受限制。
每一个字节必须保证是8位。数据传送时,先传送最高位,每传送一位后紧跟一位应答位(一 帧数据帧共有9位)
3.1 起始:
SDA、SCL都为高电平时处在空闲状态,当SCL为高电平,SDA实现从高电平到低电平的下降沿时
3.2 停止:
SDA、SCL都为高电平时处在空闲状态,当SCL为高电平,SDA实现从低电平到高电平的上降沿时
3.3 应答:
每当发送端发送完一个字节的数据后,后面都需要紧跟着一个校验位,即应答位。其通过接收端控制SDA来实现的,以告诉发送端的状态。若为应答(低电平):发送端会继续发送下一个数据;若为非应答(高电平):发送端将停止发送数据。
四、数据的传输组合方式:
4.1主机向从机发送数据, 数据传送方向在整个传送过程中不变;
4.2主机在第一个字节后, 立即从从机读数据;
4.3在传送过程中, 当需要改变传送方向时, 起始信号和从机地址都被重复产生一次, 但两次读/写方向位正好相反
五、AT24C02:
由于51 单片机没有硬件 IIC 接口, 即使有硬件接口我们通常还是采用软件模拟 I2C。 主要原因是硬件 IIC 设计的比较复杂, 而且稳定性不怎么好, 程序移植比较麻烦, 而用软件模拟 IIC, 最大的好处就是移植方便, 同一个代码兼容所有单片机, 任何一个单片机只要有 IO 口( 不需要特定 IO) , 都可以很快的移植过去。
5.1 封装及引脚功能:
A0、A1、A2:器件地址输入引脚
SDA、SCL:总线
VSS:地
VCC:正电源
WP:写保护。1:只读不写;0:可读可写
5.2 电路连接:
5.3 程序实现:
程序来源与江科大,这里不用对SDA、SCL拉低拉高后延时微秒,也可执行读写。
#include <REGX52.H>
#define AT24C02_ADDRESS 0xA0
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void I2C_Start(void)
{
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0;
}
}
/**
* @brief I2C接收一个字节
* @param 无
* @retval 接收到的一个字节数据
*/
unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}
I2C_SCL=0;
}
return Byte;
}
/**
* @brief I2C发送应答
* @param AckBit 应答位,0为应答,1为非应答
* @retval 无
*/
void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA=AckBit;
I2C_SCL=1;
I2C_SCL=0;
}
/**
* @brief I2C接收应答位
* @param 无
* @retval 接收到的应答位,0为应答,1为非应答
*/
unsigned char I2C_ReceiveAck(void)
{
unsigned char AckBit;
I2C_SDA=1;
I2C_SCL=1;
AckBit=I2C_SDA;
I2C_SCL=0;
return AckBit;
}
/**
* @brief AT24C02写入一个字节
* @param WordAddress 要写入字节的地址
* @param Data 要写入的数据
* @retval 无
*/
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}
/**
* @brief AT24C02读取一个字节
* @param WordAddress 要读出字节的地址
* @retval 读出的数据
*/
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS|0x01);
I2C_ReceiveAck();
Data=I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}