/**********************************I2C总线驱动******************************#includeAT89X52.h#includeintrins.h#defineSomeNOP();{_nop_();_nop_();_nop_();_nop_();_nop_();}//定义空指令sbitSDA=P1^3;//模拟I2C数据传输位sbitSCL=P1^2;//模拟I2C时钟控制位bitbdataI2C_Ack;//应答标志位/************************************I2C_Start*******************************voidI2C_Start(){SDA=1;//发送起始条件的数据信号_Nop();SCL=1;SomeNOP();//起始条件建立时间大于4.7us,延时SDA=0;//发送起始信号SomeNOP();//起始条件建立时间大于4us,延时SCL=0;//钳住I2C总线准备发送或接收数据/******解释:I2C总线在空闲状态下都是被上拉为高电平的,所以当它们处于低电平时就表示忙的状态.***/_nop_();_nop_();}/************************************I2C_Stop********************************voidI2C_Stop(){SDA=0;//发送结束条件的数据信号_Nop();SCL=1;//发送结束条件的时钟信号SomeNOP();//结束条件建立时间大于4us,延时SDA=1;//发送I2C总线结束信号SomeNOP();}/************************************I2C_CheckAck****************************bitI2C_CheckAck(void){ucharerrtime=255;//因故障接收方无Ack,超时值为255SDA=1;//发送器先释放SDASomeNOP();SCL=1;SomeNOP();//时钟电平周期大于4uswhile(SDA)//判断SDA是否被拉低{errtime--;if(errtime==0){I2C_Stop();return(0);}}SCL=0;_nop_();return(1);}/************************************I2C_SendB*******************************voidI2C_SendB(ucharc){ucharBitCnt;for(BitCnt=0;BitCnt8;BitCnt++)//要传送的数据长度为8位{if((cBitCnt)&0x80)//判断发送位(从高位起发送){SDA=1;}else{SDA=0;}_nop_();_nop_();SCL=1;//置时钟线为高通知被控器开始接收数据位SomeNOP();//保证时钟高电平周期大于4usSCL=0;}_nop_();_nop_();I2C_Ack=I2C_CheckAck();//检验应答信号,作为发送方,所以要检测接收器反馈的应答信号._nop_();_nop_();}/************************************I2C_RcvB********************************ucharI2C_RcvB(){ucharretc;ucharBitCnt;//位retc=0;SDA=1;//置数据总线为输入方式,作为接收方要释放SDA.for(BitCnt=0;BitCnt8;BitCnt++){_nop_();SCL=0;//置时钟线为低准备接收数据位SomeNOP();//时钟低电平周期大于4.7usSCL=1;//置时钟线为高使数据有效_nop_();_nop_();retc=retc1;if(SDA==1){retc=retc+1;//读数据位,接收的数据放入retc中}_nop_();_nop_();}SCL=0;_nop_();_nop_();return(retc);}/************************************I2C_Ackn********************************voidI2C_Ackn(bita){if(a==0)//在此发送应答或非应答信号{SDA=0;}else{SDA=1;}SomeNOP();SCL=1;SomeNOP();//时钟电平周期大于4usSCL=0;//清时钟线钳住I2C总线以便继续接收_nop_();_nop_();}/********************************I2C_ISendB**********************************bitI2C_ISendB(ucharsla,ucharsuba,ucharc){I2C_Start();//启动总线I2C_SendB(sla);//发送器件地址if(!I2C_Ack){return(0);}I2C_SendB(suba);//发送器件子地址if(!I2C_Ack){return(0);}I2C_SendB(c);//发送数据if(!I2C_Ack){return(0);}I2C_Stop();//结束总线return(1);}/**********************************I2C_IRcvB*********************************bitI2C_IRcvB(ucharsla,ucharsuba,uchar*c){I2C_Start();//启动总线I2C_SendB(sla);if(!I2C_Ack){return(0);}I2C_SendB(suba);//发送器件子地址if(!I2C_Ack){return(0);}I2C_Start();//重复起始条件I2C_SendB(sla+1);//发送读操作的地址if(!I2C_Ack){return(0);}*c=I2C_RcvB();//读取数据I2C_Ackn(1);//发送非应答位I2C_Stop();//结束总线return(1);}