×
嵌入式 > 嵌入式开发 > 详情

关于IIC协议及代码实现

发布时间:2020-09-15 发布时间:
|
最近学了下IIC协议,这里想把模拟IIC接口和标准IIC接口总结一下。(这里只介绍一主一从的情况)

IIC数据通信是通过两根线实现通信的,即SDA和SCL,SDA是数据线,SCL是时钟线,SCL控制SDA的工作时钟,也就是说当SCL为高电平时SDA上面的数据才有效。


模拟IIC接口设置:

主要是选择两条I/O分别作为SCL和SDA线,在进行数据传输是确定其输入输出功能(配置IOxDIR寄存器)。

标准IIC接口设置:

LPC2148为例

第一步:设置管脚功能选择寄存器,选择I/O为SCL,SDA功能

例如:PINSEL0 = (PINSEL0 & (~0xF0)) | 0x50; //p0.2,p0.3 iic

第二步:设置IIC工作频率,即SCL的时钟

例如:

if(Mode == I2C_SPEED_400)
{
//--- I2C Timing for 58 MHz (t = 16.954 ns) ---
I2C0SCLH = 47; //-- more then 0.6 us - 0.8
I2C0SCLL = 93; //-- more then 1.3 us - 1.4
}
else //Slow
{
I2C0SCLH = 47*4;
I2C0SCLL = 93*4;
}

第三步:清除所有标志位

I2C0CONCLR = 0xFF;

第四步:设置主从模式,这里为主模式

I2C0CONSET = 0x40;

第五步:始能IIC接口(enable IIC)

I2C0CONSET |= I2C_FLAG_I2EN;

下面列出IIC进行数据通信时满足的几个条件:

1)起始条件:当SCL和SDA都为高电平时,如果SDA由高电平变低电平时就认为是起始条件。

IIC_Start()

{

SDA = 1;

delay(2);//这个时间有自己设定

SCL = 1;

delay(2);

SDA = 0;

delay(2);

SCL = 0;

}

这样就可以开始进行数据通信了,PS:SCL高电平时SDA的数据才有效.

2)停止条件:当SCL为高电平时,如果SDA由低电平变为高电平,可认为是一个停止条件,即停止数据传输,一般主发送机来控制。

IIC_Stop()

{

SCL = 0;

delay(2);

SDA = 0;

delay(2);

SCL = 1;

delay(2);

SDA = 1;

}

这样就产生一个停止条件。

2)响应

当主设备发送完一字节数据时,从设备会产生一个响应ACK(一位,低电平),此时主设备释放SDA线高,如果主设备接收到一位低电平,表示从设备产生了一个响应位,因此可以继续向从设备发送数据,反之则停止发送。

bit IIC_RecevAck()

{

CY = SDA;//单片机为例

delay(2);

SCL = 1;

delay(2);

SCL = 0;

delay(2);

return CY;

}

//------当主设备接收从设备的一字节数据时,主设备可以发送ACK也可以不发送ACK,如果不发送ACK表示停止读取从设备数据,反之则可以继续接收数据。

IIC_SendAck(char ack)//ack=0有响应,ack=1表示不发送响应,停止接收。

{

if(ack == 0)

{

SDA = 0;

}

else

{

SDA = 1;

}

SCL = 1;

delay(2);

SCL = 0;

}

下面举例说明IIC进行一字节数据的传输

IIC_SendOneByte(unsigned char data)//主设备向从设备发送一字节数据

{

unsigned char i;

for (i = 0; i < 8; i++)

{

if (data & 0x80)

{

SDA = 1;

}

else

{

SDA = 0;

}

delay(2);

SCL = 1;

delay(2);

SCL = 0;

delay(2);

data <<= 1;

}

SDA = 0;//可以把SDA拉低,等待响应位,也可以通过IIC_RecvAck()来拉低

}

//--------------------------------------------------------

BYTE IIC_ReadOneByte()//一般由主设备先发送一字节给从设备,让从设备发送数据给主设备

{

BYTEj,data = 0;

SDA = 1; //单片机当管脚作输入时,写入1,默认为输出功能。

for(j = 0; j < 8; j++)

{

data <<= 1;

SCL = 1;

delay(2);

data = SDA;

SCL = 0;

delay(2);

}

return data;

}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
内核日志及printk结构浅析