/******************************************************************
/*驱动名称:I2c总线驱动
/*函数原型: (每个函数的都有返回值,函数返回"1"则函数的操作成功,否则失败)
/*bit SendByte_I2c_OneAd(unsigned char Ad,unsigned char Data)
/*功能描述:向器件地址为Ad的器件发送数据"Data",这里Ad为器件的高7为地址,最后一位(读写控制位)按0处理,
/* 在相应的函数中会对最后一位进行处理
/*
/*bit SendBytes_I2c_SonAds(unsigned char Chip_Ad,unsigned char Ad,unsigned char *s,unsigned char SendByte_Num )
/*功能描述:向器件地址为"Chip_Ad",子地址为Ad开始的空间依次存放"SendByte_Num"个字符,存放的内容从"S"指向的地址里的内容
/*
/*bit RevByte_I2c_OneAd(unsigned char Ad,unsigned char *s)
/*功能描述:从器件地址为Ad的器件接收一个字节数据,接收的数据放到S指向的空间
/*
/*bit RevBytes_I2c_SonAds(unsigned char Chip_Ad,unsigned char Ad,unsigned char *s,unsigned char SendByte_Num)
/*功能描述:从器件地址为"Chip_Ad"的器件的子地址"Ad"处读出"SendByte_Num"个字节数据存到"s"指向的空间
/*
/*编程人:LT
/*编程时间:2010.5
/*参考资料:周立功---增强型80C51单片机速成与实战
/* 郭天翔---新概念51单片机C语言教程
/*********************************************************************/
#include <reg51.h>
#include <intrins.h>
#define _Nop() _nop_()
#define Delay_5us _Nop();_Nop();_Nop();_Nop();_Nop();
#define Delay_2us _Nop();_Nop();
#define Delay_1us _Nop();
#define High 1
#define Low 0
sbit SDA=P2^1;
sbit SCL=P2^0;
bit Ask_I2c;
void Start_I2c()//起始信号,启动I2c
{
SDA=High;//SCL高电平期间,SDL一个下降沿启动I2c
Delay_1us;
SCL=High;
Delay_5us;
SDA=Low;
Delay_5us;
SCL=Low;//拉低I2c,准备发送或接收数据
Delay_2us;
}
void Stop_I2c()//结束I2c数据传输
{
SDA=Low;//SCL高电平期间,SDL一个上升沿终止I2c
Delay_1us;
SCL=High;
Delay_5us;
SDA=High;
Delay_5us;
}
void SendByte_I2c(unsigned char SendData)//向I2c总线上传输一个字节数据,传输成功则标志 "Ask_I2c" 置1
{ //根据标志可判断是否传输成功
unsigned char BitNum;
for(BitNum=0;BitNum<8;BitNum++)
{
if((SendData<<BitNum)&0x80)
SDA=1;
else
SDA=0;
Delay_1us;
SCL=High;
Delay_5us;//数据送到SDA上后,SCL高电平必须保持4.5us以上,数据才能被从机接收
SCL=Low;
}
Delay_2us;
SDA=High;
Delay_2us;
SCL=High;
Delay_5us;
if(SDA==High)
Ask_I2c=0;
else
Ask_I2c=1;
SCL=Low;
Delay_2us;
}
unsigned char RevByte_I2c()//从总线上接收一个字节的数据
{
unsigned char RevByte;
unsigned char BitNum;
RevByte=0;
SDA=High;
for(BitNum=0;BitNum<8;BitNum++)
{
Delay_1us;
SCL=Low;//拉低SCL等待SDA上数据的变化
Delay_5us;
SCL=High;//拉高SCL让SDA上数据稳定,在稳定期间把SDA上的数据读走
Delay_2us;
RevByte=RevByte<<1;
if(SDA==High)
RevByte=RevByte+1;
Delay_2us;
}
SCL=Low;
Delay_2us;
return(RevByte);
}
void SendAsk_I2c(bit n)//发送应答信号
{
if(n==0)
SDA=Low;
else
SDA=High;
Delay_2us;
SCL=High;
Delay_5us;
SCL=Low;
Delay_2us;
}
bit SendByte_I2c_OneAd(unsigned char Ad,unsigned char Data)//向无子地址的设备发送一个字节数据,
{
Start_I2c();
SendByte_I2c(Ad);
if(Ask_I2c==0)
return(0);
SendByte_I2c(Data);
if(Ask_I2c==0)
return(0);
Stop_I2c();
return(1);
}
bit SendBytes_I2c_SonAds(unsigned char Chip_Ad,unsigned char Ad,unsigned char *s,unsigned char SendByte_Num)
{
unsigned char i;// 发送时Chip_Ad的最后一位为0;
Start_I2c();
SendByte_I2c(Chip_Ad);
if(Ask_I2c==0)
return(0);
SendByte_I2c(Ad);
if(Ask_I2c==0)
return(0);
for(i=0;i<SendByte_Num;i++)
{
SendByte_I2c(*s);
if(Ask_I2c==0)
return(0);
s++;
}
Stop_I2c();
return(1);
}
bit RevByte_I2c_OneAd(unsigned char Ad,unsigned char *s)//从无子地址的设备接收一个字节数据,
{
Start_I2c();
SendByte_I2c(Ad+1);//Ad可以事先定义好,以后的操作就不用考虑最后一位
if(Ask_I2c==0)
return(0);
*s=RevByte_I2c();
SendAsk_I2c(1);
Stop_I2c();
return(1);
}
bit RevBytes_I2c_SonAds(unsigned char Chip_Ad,unsigned char Ad,unsigned char *s,unsigned char SendByte_Num)
{
unsigned char i;// 发送时Chip_Ad的最后一位为0;
Start_I2c();
SendByte_I2c(Chip_Ad);
if(Ask_I2c==0)
return(0);
SendByte_I2c(Ad);
if(Ask_I2c==0)
return(0);
Start_I2c();
SendByte_I2c(Chip_Ad+1);
if(Ask_I2c==0)
return(0);
for(i=0;i<SendByte_Num-1;i++)
{
*s=RevByte_I2c();
SendAsk_I2c(0);
s++;
}
*s=RevByte_I2c();//特别注意这里,因为每次接收一个字节是数据后要发送一个"应答信号",因为这里数据要连续
SendAsk_I2c(1); //接收数据,所以接收时一直是发送的"非应答信号",而最后一个字节数据接收完了以后要发送
Stop_I2c(); //一个"应答信号",所以这里不能把接收部分全部放入循环中,而要单独放在外面
return(1); //呵呵。。。。。
}