//头文件
#ifndef SOFT_I2C_H
#define SOFT_I2C_H
#include "../lib/microchip/include/GenericTypeDefs.h"
typedef struct
{
BYTE pinSCL;
BYTE pinSDA;
WORD Delay;
}SOFT_I2C_DEF;
void I2C_Init(const SOFT_I2C_DEF *def);
void I2C_Start(const SOFT_I2C_DEF *def);
void I2C_Stop(const SOFT_I2C_DEF *def);
BOOL I2C_CheckAcknowledge(const SOFT_I2C_DEF *def);
void I2C_WriteByte(const SOFT_I2C_DEF *def,BYTE b);
BOOL I2C_WriteNBytes(const SOFT_I2C_DEF *def,BYTE *buffer,int n);
BYTE I2C_ReadByte(const SOFT_I2C_DEF *def);
BOOL I2C_ReadNBytes(const SOFT_I2C_DEF *def,BYTE SlaveAdr,int n,BYTE *buffer);
#endif
//源文件
#include "soft_i2c.h"
#include "features.h"
#include "pins.h"
static inline void SDAset(const SOFT_I2C_DEF *def,BOOL v)
{
SetDigitalOutLevel(def->pinSDA,v);
}
static inline void SCLset(const SOFT_I2C_DEF *def,BOOL v)
{
SetDigitalOutLevel(def->pinSCL,v);
}
static inline BOOL SDAget(const SOFT_I2C_DEF *def)
{
return PinGetPort(def->pinSDA);
}
static inline BOOL SCLget(const SOFT_I2C_DEF *def)
{
return PinGetPort(def->pinSCL);
}
static inline void I2C_DELAY(WORD t)
{
volatile int i,j;
for(i=0;i<t;i++)for(j=0;j<1;j++);
}
static void I2C_SEND_0(const SOFT_I2C_DEF *def)
{
//发送0,在SCL为高电平时使SDA信号为低
SDAset(def,0);
SCLset(def,1);
I2C_DELAY(def->Delay);
SCLset(def,0);
I2C_DELAY(def->Delay);
}
static void I2C_SEND_1(const SOFT_I2C_DEF *def)
{
//发送1,在SCL为高电平时使SDA信号为高
SDAset(def,1);
SCLset(def,1);
I2C_DELAY(def->Delay);
SCLset(def,0);
I2C_DELAY(def->Delay);
}
void I2C_Init(const SOFT_I2C_DEF *def)
{
SetPinDigitalOut(def->pinSDA,1,TRUE);
SetPinDigitalOut(def->pinSCL,1,TRUE);
}
void I2C_Start(const SOFT_I2C_DEF *def)
{
//启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变
SDAset(def,1);
SCLset(def,1);
I2C_DELAY(def->Delay);
SDAset(def,0);
I2C_DELAY(def->Delay);
SCLset(def,0);
I2C_DELAY(def->Delay);
}
void I2C_Stop(const SOFT_I2C_DEF *def)
{
//终止I2C总线,当SCL为高电平时使SDA产生一个正跳变
SDAset(def,0);
SCLset(def,1);
I2C_DELAY(def->Delay);
SDAset(def,1);
I2C_DELAY(def->Delay);
SCLset(def,0);
I2C_DELAY(def->Delay);
}
BOOL I2C_CheckAcknowledge(const SOFT_I2C_DEF *def)
{
//发送完一个字节后检验设备的应答信号
SDAset(def,1);
SCLset(def,1);
I2C_DELAY(def->Delay/2);
BYTE F0=SDAget(def);
I2C_DELAY(def->Delay/2);
SCLset(def,0);
I2C_DELAY(def->Delay);
if(F0==1)return FALSE;
return TRUE;
}
void I2C_WriteByte(const SOFT_I2C_DEF *def,BYTE b)
{
//向I2C总线写一个字节
BYTE i;
for(i=0;i<8;i++)
{
if((b<<i)&0x80)I2C_SEND_1(def);
else I2C_SEND_0(def);
}
}
BOOL I2C_WriteNBytes(const SOFT_I2C_DEF *def,BYTE *buffer,int n)
{
//向I2C总线写n个字节
BYTE i;
I2C_Start(def);
for(i=0;i<n;i++)
{
I2C_WriteByte(def,buffer[i]);
if(!I2C_CheckAcknowledge(def))
{
I2C_Stop(def);
return(i==n);
}
}
I2C_Stop(def);
return TRUE;
}
BYTE I2C_ReadByte(const SOFT_I2C_DEF *def)
{
//从I2C总线读一个字节
BYTE b=0,i;
for(i=0;i<8;i++)
{
SDAset(def,1); //释放总线
SCLset(def,1); //接受数据
I2C_DELAY(def->Delay);
BYTE F0=SDAget(def);
I2C_DELAY(def->Delay);
SCLset(def,0);
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
BOOL I2C_ReadNBytes(const SOFT_I2C_DEF *def,BYTE SlaveAdr,int n,BYTE *buffer)
{
//从I2C总线读n个字节
int i;
I2C_Start(def);
I2C_WriteByte(def,SlaveAdr); //向总线发送接收器地址
if(!I2C_CheckAcknowledge(def)) //等待接收器应答信号
return FALSE;
for(i=0;i<n;i++)
{
buffer[i]=I2C_ReadByte(def);
if(i!=n)
I2C_SEND_0(def); //发送应答
else
I2C_SEND_1(def); //发送非应答
}
I2C_Stop(def);
return TRUE;
}