模拟IIC都使用了五年了,现在第一次以博客的形式分享出来,后续还会继续分享更多黑科技资料!
IIC总线目前在单片机开发应用当中非常的常见,比如四轴无人机要读取陀螺仪加速计的数据可以用IIC读取,读取磁力计需要用IIC读取,读取气压计需要用到IIC。IIC总线用法相对简单,硬件只需要接两根线就可以,一个时钟线(SCL),一个数据线(SDA);需要注意的是数据线在接硬件的时候一般需要外接上拉。
IIC时许
对于IIC其信号主要有以下几个 :
开始信号、结束信号和应答/非应答信号。也如上图;
开始结束信号
应答非应答信号
然后我们直接上模拟IIC程序:
static void I2C_delay(void){volatile int i=3;while(i–);}//先定义一个IIC时延,用于后面IIC调整速率。
IIC开始信号
void I2C_Start(void)
{
SDA_OUT();
SDA_H;
SCL_H;
I2C_delay();
SDA_L; //START:when CLK is high,DATA change form high to low
I2C_delay();
SCL_L;
}
IIC结束信号
void I2C_Stop(void)
{
SDA_OUT();
SCL_L;
SDA_L;//STOP:when CLK is high DATA change form low to high
I2C_delay();
SCL_H;
SDA_H;
I2C_delay();
}
IIC应答信号
void I2C_Ack(void)
{
SCL_L;
SDA_OUT();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
}
IIC非应答信号
void I2C_NoAck(void)
{
SCL_L;
SDA_OUT();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
}
IIC等待应答信号
uint8 I2C_WaitAck(void)
{
uint8_t ucErrTime=0;
SDA_IN(); //SDAÉèÖÃΪÊäÈë
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
while(SDA_read)
{
ucErrTime++;
if(ucErrTime>50)
{
I2C_Stop();
return 0;
}
I2C_delay();
}
SCL_L;
return 1;
} //IIC发送完一个字节数据或者地址时需要等待应答,若收到应答则表示主机跟设备通信成功。
IIC写入数据和读数据
void I2C_SendByte(uint8 SendByte)
{
uint8_t t;
SDA_OUT();
SCL_L;
I2C_delay();
for(t=0;t<8;t++)
{
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
uint8 I2C_ReceiveByte(void)
{
uint8_t i=0,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
SCL_L;
I2C_delay();
SCL_H;
receive<<=1;
if(SDA_read) receive++;
I2C_delay();
}
return receive;
}
至此,IIC大概介绍完。
这几年在用IIC过程中遇到的比较多的问题就是软件IIC写好了但是硬件IIC没有加上拉,这个问题也可以通过示波器查看,一般在一个字节时钟内(8个时钟周期),SDA无法正常拉高拉低大概就是这个问题。