一、I2C的特征
I 2 C 总线的特征:只要求两条总线线路 一条串行数据线 SDA 一条串行时钟线 SCL。每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机 从机关系软件设定地址,主机可以作为主机发送器或主机接收器。它是一个真正的多主机总线 如果两个或更多主机同时初始化数据传输可以通过冲突检测和仲裁,防止数据被破坏。串行的 8 位双向数据传输位速率在标准模式下可达 100kbit/s 快速模式下可达 400kbit/s 高速模式下可达 3.4Mbit/s。片上的滤波器可以滤去总线数据线上的毛刺波 保证数据完整。连接到相同总线的 IC 数量只受到总线的最大电容 400pF 限制。特殊功能:极低的电流消耗抗高噪声干扰电源电压范围宽工作的温度范围广
二、I2C总线规范
对于面向 8 位的数字控制应用,譬如那些要求用微控制器的,要建立一些设计标准:• 一个完整的系统通常由至少一个微控制器和其他外围器件例如存储器和 I/O 扩展器组成• 系统中不同器件的连接成本必须最小• 执行控制功能的系统不要求高速的数据传输• 总的效益由选择的器件和互连总线结构的种类决定
三、I2C总线术语的定义
术语 | 描述 |
发送器 | 发送数据到总线的器件 |
接收器 | 从总线接收数据的器件 |
主机 | 初始化发送、产生时钟信号和终止发送的器件 |
从机 | 被主机寻址的器件 |
多主机 | 同时有多于一个主机尝试控制总线,但不破坏报文 |
仲裁 | 是一个在有多个主机同时尝试控制总线,但只允许其中一个控制总线并使报文不被破坏的过程 |
同步 | 两个或多个器件同步时钟信号的过程 |
在I 2 C 总线上产生时钟信号通常是主机器件的责任;当在总线上传输数据时,每个主机产生自己的时钟信号,主机发出的总线时钟信号只有在以下的情况才能被改变,慢速的从机器件控制时钟线并延长时钟信号,或者在发生仲裁时被另一个主机改变。
四、数据的有效性
SDA 线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。启示和停止信号如下图:
发送到SDA线上的每个字节必须为8位,每次传输可以发送的字节数量不受限制,每个字节后必须跟一个响应位,先传输的是数据的最高位MSB,如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节可以使时钟线SCL保持低电平迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL后数据传输继续。
/*
函数功能:IIC起始信号
形参:void
返回值:void
*/
void IIC_Start(void)
{
IIC_SDA_H;//拉高数据线
IIC_SCL_H;//拉高时钟线
delay_us(DELAY_TIME);//延时
IIC_SDA_L;//拉低数据线
delay_us(DELAY_TIME);//延时
}
/*
函数功能:IIC停止信号
形参:void
返回值:void
*/
void IIC_Stop(void)
{
IIC_SDA_L;//拉低数据线
IIC_SCL_H;//拉高时钟线
delay_us(DELAY_TIME);
IIC_SDA_H;//拉高数据线
delay_us(DELAY_TIME);
}
/*
函数功能:IIC接收1bit应答
形参:void
返回值:u8 从机发送过来应答 0:应答 1:非应答
*/
u8 IIC_RecAck(void)
{
u8 ack = 0;
IIC_SDA_H;//IO切换为输入
IIC_SCL_L;//拉低时钟线,准备发送数据
delay_us(DELAY_TIME);
IIC_SCL_H;//拉高时钟线,准备接收数据
if(IIC_SDA_IN)
{
ack |= 1;
}
delay_us(DELAY_TIME);
IIC_SCL_L;//拉低时钟线,保证周期完整
delay_us(DELAY_TIME);
return ack;
}
/*
函数功能:IIC发送1bit应答
形参:u8 ack
返回值:void
*/
void IIC_SendAck(u8 ack)
{
IIC_SCL_L;//主机拉低时钟线,准备发送数据
if(ack)
{
IIC_SDA_H;//逻辑1
}
else
{
IIC_SDA_L;//逻辑0
}
delay_us(DELAY_TIME);
IIC_SCL_H;//主机拉高时钟线,准备接收数据
delay_us(DELAY_TIME);
IIC_SCL_L;
delay_us(DELAY_TIME);//拉低时钟线,保证周期完整
}
/*
函数功能:IIC发送8bit数据,接收1bit应答
形参:u8 data 主机发送8bit数据
返回值:u8 ack 接收从机应答 0:正常响应 1:非正常响应
*/
u8 IIC_SendData(u8 data)
{
u8 ack = 0;
for(u8 i=0;i<8;i++)
{
IIC_SCL_L;//拉低时钟线,准备发送数据
if(data & (0x80 >> i))//高位先出
{
IIC_SDA_H;//逻辑1
}
else
{
IIC_SDA_L;//逻辑0
}
delay_us(DELAY_TIME);
IIC_SCL_H;//拉高时钟线,准备接收数据
delay_us(DELAY_TIME);
}
ack = IIC_RecAck();//发送完8bit数据后,接收1bit应答
return ack;
}
/*
函数功能:IIC接收8bit数据,发送1bit应答
形参:u8 ack 发送给从机应答 0:正常响应 1:非正常响应
返回值:u8 接收从机发送8bit数据
*/
u8 IIC_RecData(u8 ack)
{
u8 data = 0;
IIC_SDA_H;//切换为输入模式
for(u8 i=0;i<8;i++)
{
IIC_SCL_L;//拉低时钟线,准备发送数据
delay_us(DELAY_TIME);
IIC_SCL_H;//拉高时钟线,准备接收数据
data <<= 1;
if(IIC_SDA_IN)//IO接收到高电平
{
data |= 1;
}
delay_us(DELAY_TIME);
}
IIC_SendAck(ack);
return data;
}