#include "51all.h"
#include <intrins.h>
#define NOP _nop_()
#define Clk_delay(); _nop_();_nop_();_nop_();_nop_();_nop_(); //低时钟时适当减少_nop_()个数
void I2C_delay(unsigned char ); //I2C_DELAY
void I2C_START();
void I2C_STOP();
unsigned char I2C_CheckAck(); //检验I2C总线应答信号,有应答则返回1,否则返回0,超时值取255
void I2C_SendAck(); //主控制器进行应答信号
void I2C_SendNoAck(); //主控制器进行非应答信号
void I2C_W_byte(unsigned char ); //写一个BYTE
unsigned char I2C_R_byte(); //读一个BYTE
void I2C_Wdat(unsigned int , unsigned char *, unsigned int ); //写一快数据 起始地址,数据首地址,数据长度
void I2C_Wbyte(unsigned int , unsigned char ); //往一个具体知地址写一个BYTE 起始地址,数据
void I2C_Wadd(unsigned int ); //写地址
void I2C_Rdat(unsigned int , unsigned char *, unsigned int ); // 读一快数据 起始地址,数据存放首地址,数据长度
unsigned char I2C_Rbyte(unsigned int ); // 读一个字节
sbit SDA = P1^3; //模拟I2C数据传输位
sbit SCL = P1^2; //模拟I2C时钟控制位
bit I2C_Ack = 1;
/*******************************I2C_START************************************/
//启动I2C总线,即发送I2C初始条件
void I2C_START()
{
SDA = 1;
SCL = 1; //延时>4.7us
Clk_delay();
Clk_delay();
SDA = 0; //延时>4.7us
Clk_delay();
Clk_delay();
SCL = 0;
Clk_delay();
}
/*******************************I2C_STOP************************************/
// 停止I2C总线
void I2C_STOP()
{
SDA = 0;
SCL = 1; //延时>4.7us
Clk_delay();
Clk_delay();
SDA = 1; //延时>4.7us
Clk_delay();
}
/*******************************I2C_ACK************************************/
//检验I2C总线应答信号,有应答则返回1,否则返回0,超时值取255
unsigned char I2C_CheckAck()
{
unsigned char errtime = 255; // 因故障接收方无 Ack,超时值为255
SCL = 0; // 延时
Clk_delay();
SDA = 1; //读取SDA时,先置1;
NOP;NOP;
SCL = 1;
Clk_delay();
while(SDA)
{
errtime--;
if(errtime==0)
{
I2C_STOP();
break;
}
}
SCL = 0;
if(SDA) return(0);
else return(1);
}
/*******************************I2C_SendAck************************************/
//主控制器进行应答信号
void I2C_SendAck()
{
SCL = 0;
Clk_delay();
SDA = 0;
Clk_delay();
SCL = 1;
Clk_delay();
SCL = 0;
}
/*******************************I2C_SendNoAck************************************/
//主控制器进行非应答信号
void I2C_SendNoAck()
{
SCL = 0;
Clk_delay();
SDA = 1;
Clk_delay();
SCL = 1;
Clk_delay();
SCL = 0;
}
/*******************************I2C_Wbyte************************************/
//写一个BYTE
void I2C_W_byte(unsigned char c)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
Clk_delay();
SDA=(bit)((c<<i)&0x80);
SCL = 1;
Clk_delay();
}
SCL = 0;
I2C_Ack=I2C_CheckAck();
}
/*******************************I2C_Rbyte************************************/
//读一个BYTE
unsigned char I2C_R_byte()
{
unsigned char i,Rbyte = 0;
SDA = 1; //在读取SDA的电平时,先给SDA置1;
for(i=0; i<8; i++)
{
SCL = 0;
Clk_delay();
SCL = 1;
Clk_delay();
Rbyte<<=1;
if(SDA)
Rbyte=Rbyte+0x01;
}
SCL = 0;
return (Rbyte);
}
/*******************************I2C_Wadd************************************/
// 写16bit数据地址
void I2C_Wadd(unsigned int start_add)
{
I2C_W_byte((char)(start_add>>8));
I2C_W_byte((char)start_add);
}
/*******************************I2C_Wbyte************************************/
//往一个具体知地址写一个BYTE
void I2C_Wbyte(unsigned int start_add, unsigned char dat )
{
I2C_START();
I2C_W_byte(0xa0); //device address
if(!I2C_Ack) ;//return (0);
I2C_Wadd(start_add); //16位地址
I2C_W_byte(dat); //写数据
if(!I2C_Ack) ;//return (0);
I2C_STOP();
I2C_delay(5);
}
/*******************************I2C_Rbyte************************************/
// 读一个字节
unsigned char I2C_Rbyte(unsigned int start_add)
{
unsigned char i;
I2C_START();
I2C_W_byte(0xa0); //device addr
if(!I2C_Ack) return (0); //I2C_Ack==0,没有接受到ACK,退出该函数。
I2C_Wadd(start_add); //数据地址
I2C_START();
I2C_W_byte(0xa1);
if(!I2C_Ack) return 0;
i=I2C_R_byte();
I2C_SendNoAck();
I2C_STOP();
I2C_delay(5);
return i;
}
/*******************************I2C_Wdat************************************/
//写一快数据
void I2C_Wdat(unsigned int start_add, unsigned char *dat, unsigned int dat_len )
{
I2C_START();
I2C_W_byte(0xa0); //device address
if(!I2C_Ack) ;//return (0);
I2C_Wadd(start_add); //16位地址
for(; dat_len!=0; dat_len--) //写数据
{
I2C_W_byte(*dat);
if(!I2C_Ack) ;//return (0);
dat++;
}
I2C_STOP();
I2C_delay(5);
}
/*******************************I2C_Rdat************************************/
// 读一快数据
void I2C_Rdat(unsigned int start_add, unsigned char *dat_put, unsigned int len)
{
unsigned int i=0;
if(len>0)
{ len--;
I2C_START();
I2C_W_byte(0xa0);
//if(!I2C_Ack) return (0); //I2C_Ack==0,没有接受到ACK,退出该函数。
I2C_Wadd(start_add); //数据地址
I2C_START(); //再启动
I2C_W_byte(0xa1); //开始读
//if(!I2C_Ack) ; return 0;
while(len--)
{
*(dat_put+i)=I2C_R_byte(); //连续读出1BYTE
I2C_SendAck(); //送ACK
i++;
}
*(dat_put+i)=I2C_R_byte(); //读出1BYTE
I2C_SendNoAck(); //送无效ACK
I2C_STOP();
}
I2C_delay(5);
}
/////////////////////////////////////////////////////////////////////////////////////
/*******************************I2C_DELAY************************************/
void I2C_delay(unsigned char i)
{
unsigned char j;
while(i--)
{j=10;
while(j--) NOP;
}
}
评论0