1 IIC总线的连接
IIC传输数据的时候只用其实只需要两根线,一根是“SCL”为时钟线,一根是“SDA”为数据线
我们来看一下器件是怎么连接在IIC总线上的!
可以看到,SDA和SCL都接了上拉电阻,在总线空闲的时候,SDA和SCL都应该为高电平,当总线上的任何一个器件输出低电平,那总线都将变为低电平。
数据有效性
我们记住只要记住一条:IIC总线在进行数据传输时,当SCL线为高,SDA线必须保持稳定,也就是说,在当拉高SCL线的时候,SDA线不能改变其电平,只有当SCL为低电平的时候才允许SDA线进行跳变,需要注意的是这个规定只是在进行数据传输的时候起作用,其他时候比如生成起始信号的时候可以不理睬。
2 IIC的电平信号
在使用IIC总线的时候我们主要有以下几个信号。
一,起始信号当我们使用IIC总线的时候第一个发送的就是这个信号
IIC协议规定当SCL为高电平的时候,SDA由高到低跳变,为起始信号
下面来看一下代码
//起始信号 void IIC_Start(void) { SDA = 1; //先将SDA和SCL都拉高为起始信号做准备 SCL = 1; Delay5us(); //延时稳定 SDA = 0; //拉低SDA线,又高到低跳变,起始 Delay5us(); //延时稳定 SCL = 0; //拉低SCL线,钳住IIC总线 }
二 停止信号
IIC协议规定当SCL为高电平的时候,SDA由低到高跳变,为停止信号,和起始信号正好相反
下面来看一下代码
//停止 void IIC_Stop(void) { SCL = 0; //先将SDA和SCL都拉低为起始信号做准备 SDA = 0; Delay2us(); //延时稳定 SCL = 1; //拉高SCL等待SDA上升沿 Delay2us(); //延时稳定 SDA = 1; //拉高SDA Delay5us(); SCL = 0; //拉低SCL,钳住总线 }
三 应答信号
IIC协议规定当SCL为高电平的时候,SDA为低,为起始信号,注意这里是需要在SCL的高电平到来之前SDA线需先将低电平准备好,并在SCL为高期间稳定
下面来看代码
//答应 void IIC_Ack(void) { SCL = 0; //先将SDA和SCL都拉低为起始信号做准备 SDA = 0; Delay2us(); //延时稳定 SCL = 1; //将SCL拉高 Delay5us(); //在此延时阶段,SDA一直为低 SCL = 0; //拉低SCL,钳住总线 }
四 非应答信号
这个就和答应信号相反,SCL为高期间,SDA也为高并保持稳定就可以了!
下面看代码
//不答应 void IIC_NAck(void) { SCL = 0; //将SCL拉低为高电平做准备 SDA = 1; //将SDA先拉高 Delay2us(); SCL = 1; //拉高SCL Delay5us(); SCL = 0; //钳住总线 }
五 等待答应信号
发送器每发送完一个字节(8个脉冲),在第9个脉冲间释放总线,接收器返回一个ACK信号,协议规定,低电平为有效应答,高电平为无效应答。
看以下代码
//等待答应 bit IIC_Wait_Ack(void) { uint8_t temp = 0; //定义临时计数变量 SDA = 1; //先拉高SDA Delay5us(); //延时稳定 SCL = 1; //拉高SCL准备读取SDA线,SDA和SCL同时为高,释放总线控制权 Delay5us(); while(SDA) //当SDA拉低变为低电平的时候表示有效答应,调出循环 { temp++; if(temp>250) //当循环250次后SDA还没有拉低,则表示没有答应信号(不准确的延时) { IIC_Stop(); return 1; //没有答应返回1 } } SCL = 0; return 0; //有答应,返回0 }
六 发送1个字节
//发动1个字节 void IIC_Send_Byte(uint8_t dat) { uint8_t t; //临时计数变量 SCL = 0; //拉低SCL,钳住总线,准备发送数据 for(t=0;t<8;t++) //循环8次,一次发送1位 { SDA = (dat&0x80)>>7; //去低四位,然后左移七位,先发高位 dat=dat<<1; //将数据右移一位,等待下一此发送 SCL = 1; //拉高SCL,等待从器件读取SDA Delay2us(); //延时稳定 SCL= 0; //拉低SCL,钳住总线,准备发送数据 Delay2us(); //延时稳定 } }
七 读取1个字节
// 功能说明: CPU从I2C总线设备读取8bit数据 // 返 回 值: 读到的数据 uint8_t IIC_Read_Byte(uint8_t ack) { uint8_t i,value; /* 读到第1个bit为数据的bit7 ,先读高位后读低位*/ value = 0; for (i = 0; i < 8; i++) { value <<= 1; 数据左移,为下一此读取腾出位置 SCL = 1; Delay2us(); if (SDA) //如果SDA为1,则value自加 { value++; } SCL = 0; //钳住总线,准备下一此读取 Delay2us(); } if(ack==0) //读取完毕,判断答应信号 i2c_NAck(); else i2c_Ack(); return value; //返回读取到的值 }
好了,以上就是模拟IIC的基本使用方法了!