一.I2C总线概述
- 解决芯片与芯片之间的通讯
- uart ,485 解决板子与板子之间通讯
数据传输速率为从机控制。
SDA :数据传输总线
SCL :时钟线
总线上连接多少个从机设备是与线间电容有关,线间电容不超过400pF 即可
I2C总线为内部开漏接口方式,需在SCL与SDA处加上拉电阻
SDA与SCL要为高电平,则挂在总线上的从机设备线都应该为高电平。(线与关系)
二.I2C总线协议数据
(1)只有总线空闲时才允许启动数据传输。
(2)在数据传输时,当时钟线为高电平时,数据线必须保证稳定状态,不允许有跳变。
一.字节传送与应答
二.I2C总线的寻址
器件(从机)的地址由7位组成,它与一位方向位构成了I2C总线数据传输时起始状态S之后第一个字节。
当主机发送了第一个字节后,系统中的每一个从机都在起始状态S之后把高7位与本机地址比较,如果与本机地址一样,则被主机选中,是接收数据还是发送数据由R/W 确定。方向位(R/W),用“ 0”表示主机发送(写)数据(W),“ 1”表示主机接收 数据(R)
二.I2C数据代码
NOP指令
#include <intrins.h> 包含其文件
(1)一个NOP就是一个机器周期(2)空指令,延时一个机器周期
(3)这个与单片机型号、指令类型和使用的晶振频率有关,比如AT89C51,是一个12个时钟周期等于1个机器周期的单片机 ,如果使用的晶振是12MHz的话,执行一条单指令的
NOP 需要 12x(1/12M)=1微秒的时间。
SCL维持Tsu-STA时间后,SDA 开始变为低电平。
BSP_I2C.c
起始信号:当SCL 线在高电平期间 SDA 线从高电平向低电平切换。
注意:
起始信号和停止信号是在SCL 是高电平期间,SDA线电平切换的过程,而不是单纯的高低电平。
/*******************************************************************************
Function : bsp_I2c_start
Description : i2c驱动 起始函数
Input : 无
Output : 无
Return : 无
*******************************************************************************/
void bsp_I2c_start(void)
{
I2C_SCL = 1;
I2C_SDA = 1;
I2C_Delay(); //scl需要维持4.7us,拉低SDA,产生起始信号
I2C_SDA = 0; //此时SCL仍维持在高电平。SDA进行信号跳变
I2C_Delay();
I2C_SCL = 0; //产生起始信号后,SCL线应拉低。否则SCL高电平默认发送数据。而此时的SDA线为低电平会当作地址(数据)
}
/*******************************************************************************
Function : bsp_I2c_Stop
Description : i2c驱动 停止函数
Input : 无
Output : 无
Return : 无
*******************************************************************************/
void bsp_I2c_Stop(void)
{
I2C_SDA = 0;
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 1;
IC_Delay();
}
/*******************************************************************************
Function : bsp_I2c_ACK
Description : i2c驱动 停止函数
Input : 无
Output : 无
Return : 无
*******************************************************************************/
void bsp_I2c_ACK(void)
{
I2C_SCL = 0;
I2C_Delay();
I2C_SDA = 0;
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SCL =0;
I2C_Delay();
I2C_SDA = 1; //应答完成以后立马释放总线。
IC_Delay();
}
/*******************************************************************************
Function : bsp_I2c_NACK
Description : i2c驱动 应答函数
Input : 无
Output : 无
Return : 无
*******************************************************************************/
void bsp_I2c_NACK(void)
{
I2C_SCL =0;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
}
/*******************************************************************************
Function : bsp_I2c_WaitACK
Description : CPU产生一个时钟,并读取器件的ACK信号
Input : 无
Output : 无
Return : 返回0表示正确应答,1表示无应答
*******************************************************************************/
unsigned char bsp_I2c_WaitACK(void)
{
unsigned char ret;
I2C_SDA = 1; //CPU释放总线
I2c_Delay();
I2C_SCL=1(); //cpu驱动SCL=1,此时器件会返回ACK信号
i2c_Delay();
if(EEPROM_I2C_SDA_READ()) //CPU读取SDA线状态,有应答返回1,无应答返回0
{
ret = 1;
}
else
{
ret = 0;
}
I2C_SCL=1(); //准备接收下一个字节
I2c_Delay();
return ret;
}
/*******************************************************************************
Function : bsp_I2c_write
Description : 主机通过i2c 写一个字节给从机
Input : byte:写入的一个字节
Output : 无
Return : 无
*******************************************************************************/
void bsp_I2c_start(unsigned char byte)
{
unsigned char temp;
for (temp = 0x80;temp != 0;0x80 >>= 1)
{
if((byte & temp) == 0)
{
I2C_SCL = 0;
}
else
{
I2C_SCL = 1;
}
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
}
}
//bit 是变量类型,相当于boot 只占一个位,最多可定128个bit变量
//sbit 是给可位寻址的变量(或特殊功能寄存器)的某一个位定个别名,不另占空间
bit I2C_RecvAck()
{
bit ack;
I2C_SDA = 1; //主机主动释放SDA,为读ack做准备
I2C_Delay();
I2C_SCL = 1;
ack = I2C_SDA;
I2C_Delay();
I2C_SCL = 0;
return ack;
}
BSP_I2C.h