1.心血来潮看本身能不能参考时序图从新写一个IIC驱动,增强一下时序图的理解。记录下来,之后遇到此类的IIC时序的芯片能够直接操做。spa
先说说本身参照手册来写AT24c02的IIC低层驱动,从写完到最后调试成功所遇到的问题:3d
1.先肯定SDA、SCL两根线的硬件链接。 (因为本身换了一套开发板,本身当时没有意识到,最后发现了)。调试
2.先调串口便于打印调试 (可是以前调试好的代码,居然不能用)本身也是醉了。而后把总中断关掉,就莫名其妙的变好了。这个问题本身也没搞明白。code
3.本身错在了起始信号那里,我把SCL拉高后,没有再拉低,就直接去写数据了。这确定就悲剧了。。blog
4.还有不能很频繁不断擦除、写入。否则会出错。。。开发
本身的想法是 写入一个字节在读出用串口发出来。it
2.模拟iic时序 class
2.1起始信号 date
先是 SDA和SCL都拉高 并延时(延时时间能够参考手册<读写周期那块>) 循环
//总线初始化
void Iic_init()
{
SDA=1;
delay10us();
SCL=1;
delay10us();
}
//iic的开始信号(在时钟线SCL为高的时候数据线由高变低)
void start()
{
SDA=0;
delay10us();
SCL=0;
delay10us(); //以前是这里没有把时钟线拉低。才致使没有正确的起始信号。
}
2.2中止信号
//中止信号 (在时钟线SCL为高时数据线由低变高)
void stop()
{
SCL=1;
delay10us();
SDA=0;
delay10us();
SDA=1;
delay10us();
}
2.3 写一个字节带应答信号:
//写一个字节(带应答的) 返回值为1,成功写入并应答。不然反之。
unsigned char Iic_write(unsigned char date) //高位在前
{
unsigned char i,j=0;
for(i=0;i<8;i++) // 好比: data: 10011001
{
SDA=date>>7; //第一次发送一个字节的最高位(bit7),第二次发送一个字节的bit6,
//先送给数据线,让他准备好
date=date<<1; // 为了方便读取下一位 // C语言的位操做本身要特别熟悉<C语言高级专题>
//delay10us();
SCL=1;
delay10us();
SCL=0;
delay10us(); //成功给SDA写入一位数据。
}
//此时在这里 SCL(时钟线) 已经为低了。
SDA=1; //应答信号 acknowledge 时序是先把 数据先拉高,第九个时钟周期,看SDA是否被拉低。
delay10us();
SCL=1;
delay10us();
while(SDA) //由时序图知 若是发送应答 SDA由高置低
{
j++; //若是不该答避免死循环
if(j>200)
{
SCL=0;
return 0; //SDA=1; SCL=0
}
}
SCL=0;
delay10us();
return 1; //SDA=0; SCL=0
}
2.3 读一个字节的数据
1 //iic读一个字节
2 unsigned char Iic_read() 3 { 4 unsigned char dat=0,i; 5 SDA=1; //不知道为何这里要把数据线拉高,我感受高低都行吧!
6 delay10us(); 7 for(i=0;i<8;i++) 8 { 9 SCL=1; // 这个时候就要准备往SDA数据线里送数据了。
10 delay10us(); 11 dat=dat<<1; 12 dat=dat|SDA; // 这两句代码的顺序要注意,第八次的时候就直接把最低位的赋给dat了
13 SCL=0; 14 delay10us(); 15 } 16 return dat; 17 }
而后在写稍微高层(针对器件)的时序协议:
写、读一个字节的时序:
调用底层时序来完成就好了。