我们先了解一下I2C总线基础知识.
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。
所谓类I2C总线,是指信号只通过SCL, SDA传输. 即两线――串行数据(SDA)和串行时钟 (SCL)线在连接到总线的器件间传递信息。
我们可以把这2条线连接到主控芯片的2条GPIO引脚上,用GPIO模拟方式来和I2C连接的外部器件通信.
下面是一些GPIO模拟I2C协议通信的基础函数.
#define SUCCESS (0)
#define FAILED (1)
#define CLK_OUT *(volatile unsigned int *)(GPIO_BASE_ADDR+0xC0 |= (1<<30)
#define CLK_HI *(volatile unsigned int *)(GPIO_BASE_ADDR+0xC4) |= (1<<30)
#define CLK_LO *(volatile unsigned int *)(GPIO_BASE_ADDR+0xC4) &= ~(1<<30)
#define DATA_OUT *(volatile unsigned int *)(GPIO_BASE_ADDR+0xF8) |=(1<<31)
#define DATA_IN *(volatile unsigned int *)(GPIO_BASE_ADDR+0xF8) &=~(1<<31)
#define DATA_HI *(volatile unsigned int *)(GPIO_BASE_ADDR+0xF4) |= 1<<31
#define DATA_LO *(volatile unsigned int *)(GPIO_BASE_ADDR+0xF4) &=~(1<<31)
void Delay(char cDelay)
{
while(cDelay>0) {
cDelay--;
}
}
void Clockhigh(void)
{
Delay(1);
CLK_HI;
Delay(1);
}
void Clocklow(void)
{
Delay(1);
CLK_LO;
Delay(1);
}
void ClockCycle(void)
{
Delay(1);
CLK_LO;
Delay(2);
CLK_HI;
Delay(1);
}
void ClockCycles(char cCount)
{
char i;
for (i = 0; i < cCount; ++i) ClockCycle();
}
void PowerOn(void)
{
int i;
GPIO_ENABLE(SCL_GPIO);
GPIO_ENABLE(SDA_GPIO);
DATA_OUT;
CLK_OUT;
CLK_LO;
DATA_HI;
ClockCycles(10);
}
void PowerOff(void)
{
Delay(1);
CLK_LO;
Delay(6);
}
void Start(void)
{
DATA_OUT;
Clocklow();
DATA_HI;
Delay(4);
Clockhigh();
Delay(4);
DATA_LO;
Delay(8);
Clocklow();
Delay(8);
}
void Stop(void)
{
DATA_OUT;
Clocklow();
DATA_LO;
Delay(4);
Clockhigh();
Delay(8);
DATA_HI;
Delay(4);
}
char Write(char cData)
{
char i;
DATA_OUT;
for(i=0; i<8; i++) {
Clocklow();
if (cData&0x80)
DATA_HI;
else
DATA_LO;
Clockhigh();
cData = cData<<1;
}
Clocklow();
DATA_IN;
Delay(8);
Clockhigh();
while(i>1) {
Delay(2);
if (DATA_RD) i--;
else i = 0;
}
Clocklow();
DATA_OUT;
return i;
}
char Read(void)
{
char i;
char rByte = 0;
DATA_IN;
DATA_HI;
for(i=0x80; i; i=i>>1)
{
ClockCycle();
if (DATA_RD)
rByte |= i;
Clocklow();
}
DATA_OUT;
return rByte;
}
void WaitClock(char loop)
{
char i, j;
DATA_LO;
for(j=0; j<loop; j++) {
Start();
for(i = 0; i<15; i++)
ClockCycle();
Stop();
}
}
void AckNak(char cAck)
{
DATA_OUT;
Clocklow();
if (cAck)
DATA_LO;
else
DATA_HI;
Delay(2);
Clockhigh();
Delay(8);
Clocklow();
}
void Ack(void)
{
DATA_OUT;
Delay(1);
CLK_LO;
Delay(1);
DATA_LO;
Delay(3);
CLK_HI;
Delay(9);
Clocklow();
}
char ReceiveData(char *cRecBuf, char cLen)
{
int i;
for(i = 0; i < (cLen-1); i++) {
cRecBuf[i] = Read();
AckNak(TRUE);
}
cRecBuf[i] = Read();
AckNak(FALSE);
Stop();
return SUCCESS;
}
char SendData(char *cSendBuf, char cLen)
{
int i;
for(i = 0; i< cLen; i++) {
if (Write(cSendBuf[i])==1)
return FAIL_WRDATA;
}
Stop();
return SUCCESS;
}