给大神们贴出我的程序(也可以下载)
/**********************************************************/
/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
SCL_in;
SDA_in;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
SDA_out;
PORTA_PA1=0;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();/*起始条件建立时间大于4.7us,延时*/
SCL_out;
PORTA_PA2=0; /*发送起始信号*/
Delay_us();
Delay_us();/* 起始条件锁定时间大于4μs*/
}
/*******************************************************************
结束总线函数
函数原型: void Stop_I2c();
功能: 结束I2C总线,即发送I2C结束条件.
********************************************************************/
void Stop_I2c()
{
SDA_out;
Delay_us(); /*发送结束条件的时钟信号*/
SCL_in;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us(); /*结束条件建立时间大于4μs*/
SDA_in;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
}
/*******************************************************************
字节数据传送函数
函数原型: void SendByte(uchar c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((c<<BitCnt)&0x80)
{
SDA_in;
}
else
{
SDA_out;
}
Delay_us();
SCL_in;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us(); //保证时钟高电平周期大于4μs
SCL_out;
}
Delay_us();
Delay_us();
SDA_in;
Delay_us();
Delay_us() ;
SCL_in;
Delay_us();
Delay_us();
Delay_us();
if(PORTA_PA1==1)
ack=0;
else
ack=1; /*判断是否接收到应答信号*/
SCL_out;
Delay_us();
Delay_us();
}
void Ack_I2c(byte a)
{
if(a==0){
//要规范 要加括号!!!
SDA_out;//在此发出应答或非应答信号
}
else{
SDA_in;
}
Delay_us();
Delay_us();
Delay_us();
SCL_in;
Delay_us();
Delay_us(); //时钟低电平周期大于4μs
Delay_us();
Delay_us();
Delay_us();
SCL_out; //清时钟线,钳住I2C总线以便继续接收
Delay_us();
Delay_us();
}
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
SDA_in;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
Delay_us();
SCL_out;
Delay_us();
Delay_us();
Delay_us();
Delay_us();
Delay_us();
SCL_in;
Delay_us();
Delay_us();
retc=retc<<1;
Delay_us();
if(PORTA_PA1==1)retc=retc+1; //读数据位,接收的数据位放入retc中
Delay_us();
Delay_us();
}
//SCL_out;
Delay_us();
Delay_us();
return(retc);
}
/*====================================================================================
功能: I2C读出多个数据
输入参数:
sla : I2C地址
suba : 数据的地址
*s : 指向读出的内容
no : 读出数据的个数
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
========================================================================================*/
uchar I2C_Read(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(2);
SendByte(suba);
if(ack==0)return(3);
Delay_ms();
Delay_ms();
Start_I2c(); //重新启动总线
SendByte(sla+1);
if(ack==0)return(4);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); //保存 读出数据
Ack_I2c(0); //发送应答位
s++;
}
*s=RcvByte();
Ack_I2c(1); //发送非应位
Stop_I2c(); //结束总线
return(1);
}
//*******************************************************
|