您的位置:首页 > 其它

关于单片机IIC总线的理解(附程序)

2017-10-10 21:14 309 查看
#include<iic.h>

void delay10us(void){//误差 0us
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}

void iicStart(){
SDA = 1;
delay10us();
SCL = 1;
delay10us();
SDA = 0;
delay10us();
SCL = 0;//SCL=0时,SDA状态允许变化
delay10us();

}

unsigned char iicSendDate(unsigned char dat){
unsigned char i,a;
for(i=0;i<8;i++){
SDA = dat>>7;
dat>>=1;
SCL = 1;
delay10us();
SCL = 0;
delay10us();
}
//等待应答. SCL、SDA释放   等待应答时,SCL=1,SDA=1,应答后,SDA=0
SDA = 1;
delay10us();
SCL = 1;
//delay10us();  不需要延时,后面通过a++延时,来判断是否发送成功
//应答与否—————_是否发送成功
while(SDA){//若应答,则SDA=0,从而结束循环,返回1.
a++;
delay10us();
if(a>200){
SCL = 0;
delay10us();
            return 0;
}

}
SCL = 0;//SCL=0时,允许SDA状态发生变化,为了下一次发送
delay10us();
return 1;

}
//读取过程,主机先发送从机器件地址,要读取的地址,后要重复一次起始信号并发出器件地址和读取方向1 (发送函数包含等待从机应答过程即等待 SDA=0的过程)
//发送完后,scl = 0; 才开始读取数据过程——iicReadDate()函开始数执行
unsigned char iicReadDate(){
unsigned char i,dat = 0;
//scl =0;之前已经等于0了,不用写
SDA = 1;//读取字节前,先释放SDA,SDA=1不是将端口固定位高电平,而是关闭单片机
//内部下MOG管,让SDA线的电平由信号决定。
delay10us();//等待SDA为状态的更新
for(i=0;i<8;i++){//接受8个字节
SCL = 1;//SDA为高电平时,数据是稳定的
delay10us();
dat<<=1;//iic是串行传输的,只能一位一位传输,并且最高位在前
dat |=SDA;//将dat左移一位,然后将SDA位的状态放到dat的最后一位,赋值给dat,循环8次,依次写到dat的8个位中。dat的最初的首位被移出,
delay10us();
SCL = 0;//SCL=0时,SDA状态才允许发生变化。为后续的终止信号做准备。
delay10us();

}
return dat;

}
void iccStop(){
SDA = 0;
delay10us();
SCL = 1;  //释放
delay10us();
SDA = 1;  //释放
delay10us();

}
//iic总线  相当于数据线,由单片机模拟。

//往24c02的一个地址写入数据
void at24co2WriteDate(unsigned char addr,unsigned char dat){

iicStart();//开始

iicSendDate(0xa0);//发送写器件地址	1010 000 0
iicSendDate(addr);//发送该器件的存储区的首地址
iicSendDate(dat);//发送数据

iicStop();//停止

}

//从24c02内读取数据
unsigned char at24c02ReadDate(unsigned char addr ){	//addr:器件的存储区的首地址。器件的地址已知
unsigned char num;
iicStart();//开始

iicSendDate(0xa0);//发送器件地址+0
iicSendDate(addr);//发送该器件的存储区的首地址
iicStart();
iicSendDate(0xa1);

num = iicReadDate();

iicStop();//结束

return num;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: