IIC通信的内容(只看重点)
1.IIC通信主要依靠两根线:SCL和SDA.
2.高位在先,低位在后。
3.有ACK和NAK之说。
4.起始信号和终止信号时,SCL在高电平时变化。数据信号时,SCL为低电平期间变化,SCL高电平读取。
5.“整体上来说器件都是有一个最快速度的限制,而没有一个最慢速度的限制,所以在换用高速的单片机后,通常都是靠在个步骤步骤之间,插入软件延时来满足最慢时序的要求”对这句话有深刻理解的话,就会大体上掌握时序。
EEPROM
EEPROM有好几个系列:24x01/02/04/08/16,观察发现最后两位是01等等,代表容量为1K bit。其他也是这个道理。
我们需要阅读AT2402的手册,在此之前,需要补充一些知识。
<1>8-byte page(1k,2k),16-byte page(4k,8k,16k)(1k和2K的页数是8字节,其余的几页都是16字节)
<2>1k/2k的硬件地址有3个,言外之意可以一个总线挂8个1k/2k的IIc器件。而4K两个地址位最多挂4个,8K一个地址位最多挂两个,16K只能一个总线挂一个。
正式进入手册,跟之前认识温度传感器是类似的,还是需要读和写的操作,但与IIc结合使用,又会有很多的不同。
还是要先看原理图:
在这些脚中,我们写程序只用SCL和SDA 两个引脚。
接下来,看着说明书写程序。
第一步:先来看看一张图有一个整体的把握。
第二步:先写开始和停止的子函数。
void iicstrat()//1 iic的起始信号
{
sda=1;
_nop_();
scl=1;
_nop_();
sda=0;
_nop_();
scl=0;
_nop_();
//以上由起始信号起始部分的图写成的
}
void iicstop()//2 iic的停止信号
{
sda=0;
_nop_();
scl=1;
_nop_();
sda=1;
_nop_();
//以上由起始信号停止部分的图完成
}
这里需要说明的是,起始命令时,SCL和SDA都是由高到低的。而停止命令时,与之相反。
第三步:写的命令。在写之前,看一张存储地址的图。
void iicwrite(uchar add,uchar dat)//3 写数据,定义一个地址,定义一个数据
{
iicstrat();//一 启动一次iic的转换
writebyte(0x90);//在存储位上,高8位是固定的:1010,低8位是默认的:0000 所以起始值是 90
//iic时,为a0,但现在是A/D转换器,只需一处做出改变,其他地方一样
ack();//响应信号的程序
writebyte(add);//写地址
ack();//等待
writebyte(dat);//写数据
ack();//再等待
iicstop();//最后,停止
}
void writebyte(uchar dat)//4 写字节
{
uchar i;
for(i=0;i<8;i++)//1010 00008位逐一写
{
scl=0;//先是拉低SCL的信号
sda=dat&0x80;//然后是给SDA一个信号
scl=1;//随后将其拉高
dat<<=1;//最后将其一位一位的写入
}
scl=0;//必须置0,因为要给一个返回的信号
}
uchar ack()//5 响应信号的程序
{
scl=1;//因其又是一个时钟周期,才会给我们一个数据
iicdelay(5);//这里必须是特殊的延迟,不能是其他
if(sda==1)//判断是否出现了错误
{
scl=0;
iicstop();
return 0;
}
else //返回是1的时候,才会回到写数据的函数中
{
scl=0;
return 1;
}
}
void iicdelay(uchar m)//6 特殊的延迟,此处定义了5个时钟周期
{
do
{
_nop_();
}
while(m--);
}
第四步:读的命令。
uchar iicread(uchar add)//7 读的操作
{
uchar temp;
//与写的操作一样的
iicstrat();
writebyte(0x90);
ack();
writebyte(add);
ack();
iicstop();
//之后重新开始
iicstrat();
writebyte(0x91);//让最后1为位置1,是进行读的操作
ack();
temp=iicreadbyte();
iicstop();
temp=0.39*temp;
return temp;
}
uchar iicreadbyte()//8 写字节
{
uchar dat;
uchar i;
//一部分仿照读字节的程序
for(i=0;i<8;i++)
{
scl=1;
iicdelay(5);
dat<<=1;
if(sda==1)//可以简写为sda
{
dat|=0x01;
}
scl=0;
}
return dat;
}