/*****************************************/
/*****I2C总线的驱动程序、数据传输程序********/
/*******!!!!!!记住硬件和软件一起在动作********/
/*****************************************/
#include<main.h>
#include<I2C.h>
#define nop _nop_()//tLOW的时间
//稍微长一点,但仍没有机器周期大,在此做个试验
uchar BitCnt;
sbit SDA=P2^1; //串行数据线
sbit SCL=P2^0; //串行时钟线
bit ack;// 应答标志位
/****************************************
I2C总线的驱动程序
程序原型:void start_I2C();
功能:通过单片机控制I2C总线的启动
*****************************************/
void start_I2C()
{
SDA=1; /*发送起始条件的数据信号*/
nop;
SCL=1;
nop; /*由于起始信号建立时间比较长,稍作延时*/
nop;
SDA=0;
nop;
SCL=0; /*钳住I2C总线,准备发送或接收数据 */
/******解释:I2C 总线在空闲状态下都是被上拉为高电平的,
所以当它们处于低电平时就表示忙的状态.***/
nop;
nop;
}
/*********************************************
I2C总线的停止程序
函数原型:void stop_I2C();
功能: 通过单片机控制I2C总线为停滞状态
*********************************************/
void stop_I2C()
{
SDA=0;
nop;
nop;
SCL=1;
nop;
nop;
SDA=1;
nop;
}
/*********************************************
I2C应答时序
函数原型:void acknowleg(bit ack);
功能:24C02工作于读模式时, 单片机发送应答位
**********************************************/
void acknowleg(bit a)
{
if(a==0) SDA=0; /*当a=0时发送的是应答信号,反之是非应答信号*/
else SDA=1;
nop;
nop;
SCL=1;
nop;
nop;
SCL=0;
nop;
nop;
}
/*******************************************************************
字节数据发送函数
函数原型: void SendByte( uchar c);
功能:
将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
**********************************************************************/
void SendByte( uchar c)
{
for(BitCnt=0;BitCnt<8;BitCnt++)
/*注意一定是一位一位的操作,共有八位,所以中间有一些复位操作*/
{
if((c<<BitCnt)&0x80) SDA=1;
else SDA=0;/*判断发送的数据到底是0还是1*/
nop;
SCL=1;
nop;
nop;
SCL=0;//参考时序,在前在后是有区别的,发送,一定在后,这个时序一定要注意
nop;
}
nop;
nop;
SDA=1;/*释放数据线*/
nop;
nop;
SCL=1;//释放时钟线
nop;
nop;
if(SDA==1) ack=0;
else ack=1;/*判断是否接到硬件应该为的总线的应答,
I2C 总线数据传送时每成功地传送一个字节数据后接收器都必须产生一个应答信号*/
SCL=0; //钳住总线
nop;
nop;
}
/*******************************************************************
字节数据接收函数
函数原型: uchar RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数应答从机。
********************************************************************/
uchar RcvByte()
{
uchar Reg=0;
SDA=1;//释放数据线
nop;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
nop;
SCL=1;
nop;
nop;
SCL=0;//刚开始少了这个,在前在后没区别
nop;
nop;
Reg=Reg<<1;
if(SDA==1) Reg++;
nop;
nop;
}
SCL=0; //钳住总线
nop;
nop;
return(Reg);
}