📄 i2c.c
字号:
{
*ptr++ =I2CReadData(); // Fetch data byte by byte
rtnvar |=I2CReadAck(); /* ack all but last byte*/
}
*ptr++ = I2CReadData(); // Fetch last byte
/* and DON't Ack it */
I2CStop();
return rtnvar;
}
DLLEXPORT int I2CWriteData(byte data)
/******************************************************************
Processing: Send a data byte out.
Inputs: data is the byte to send
Outputs: return success or failure.
Side-effects None.
*******************************************************************/
{
int i;
unsigned int mask = 0x80;
int rtnvar;
// Send out LSB first
for (i = 0; i < 8; i++)
{
rtnvar = I2CBitWrite((byte )(data & mask) );
if (rtnvar)
break;
mask >>=1;
}
rtnvar |= I2CWriteAck();
return rtnvar;
}
DLLEXPORT byte I2CReadData(void)
/******************************************************************
Processing: read a data byte in.
Inputs: data is the byte to send
Outputs: return DATA BYTE READ.
Side-effects None.
*******************************************************************/
{
int i;
int newbyte ;
// Disable SDA OUT (just in case !)
clr_mcsrbit(SDA_OE);
// Receive MSB first
newbyte = I2CBitRead(); /* get 1st bit */
for (i = 0; i < 7; i++)
{
newbyte <<= 1; /* shift 7 times */
newbyte |= I2CBitRead(); /* don't shift last bit in */
}
return newbyte ;
}
DLLEXPORT int I2CStart()
/******************************************************************
Processing: Start of message.
Inputs:
Outputs: return success or clockstuck.
Side-effects None.
*******************************************************************/
{
int clockstuck;
clocklow();
set_mcsrbit(SDA | SDA_OE); /* Drive Data Line hi */
Delay (2);
clockstuck = clockhigh(); // Set SCL high
Delay (2);
clr_mcsrbit(SDA); /* take SDA low while clk hi */
// Delay 4 clock
Delay(4);
clocklow();
Delay(4);
return clockstuck;
}
DLLEXPORT int I2CStop()
/******************************************************************
Processing: End of message processing
Inputs:
Outputs: return success or clock stuck.
Side-effects None.
*******************************************************************/
{
int clockstuck;
clocklow();
clr_mcsrbit (SDA);
set_mcsrbit(SDA_OE); /* drive SDA low */
Delay(2);
clockstuck = clockhigh(); // Set SCL high
Delay(4);
set_mcsrbit(SDA); /* raise SDA while clock is hi */
Delay(2);
clr_mcsrbit(SDA_OE); /* Tristate the data line */
return clockstuck;
}
DLLEXPORT int I2CWriteAck()
/******************************************************************
Processing: Look for Ack
Inputs:
Outputs: return success or BAD_ACK or CLOCK STUCK
Side-effects None.
*******************************************************************/
{
int rtnvar;
int i;
int clockstuck;
int databit;
clocklow();
clr_mcsrbit(SDA_OE);
Delay(4);
clockstuck = clockhigh();
if (! clockstuck)
{
rtnvar = I2C_BAD_ACK; /* assume failure */
for (i =0; i < 10; i++)
{
Delay(1);
databit = *ptr2pal; /* read acknowledge bit from slave */
databit &= SDA; /* mask off all but SDA bit */
if (databit == 0)
{
rtnvar = SUCCESS;
break;
}
}
}
else
rtnvar = clockstuck;
clocklow();
return rtnvar;
}
DLLEXPORT int I2CReadAck()
/******************************************************************
Processing: Give the chip an ack.
Inputs:
Outputs: return success or clock stuck.
Side-effects None.
*******************************************************************/
{
int clockstuck;
clocklow();
clr_mcsrbit(SDA);
set_mcsrbit(SDA_OE); /* Drive SDA low */
// Delay 2 clock cycle
Delay(4);
clockstuck = clockhigh();
// Delay 2 clock cycle
Delay(2);
clocklow();
clr_mcsrbit(SDA_OE); /* Release Data Line */
return clockstuck;
}
DLLEXPORT int I2CBitWrite(byte bit)
/******************************************************************
Processing: Write single bit from I2cbus slave. Assert the
data bit on the data line, wait half period, assert
the clock, wait half period and remove clock.
Allow slave to request a delay by holding SCLock low.
SCLock has a pullup resistor and will go high if we
stop driving it AND the slave stops pulling it
down.
Inputs: bit to write. Not zero writes a 1, 0 writes a 0.
Outputs: As declared.
Side-effects None.
*******************************************************************/
{
int clockstuck;
// clocklow();
if (bit) // Set data bit before clock it out
set_mcsrbit(SDA);
else
clr_mcsrbit(SDA);
set_mcsrbit(SDA_OE); /* Drive SDA line */
clockstuck = clockhigh();
clocklow(); // Set SCL low
return clockstuck;
}
DLLEXPORT byte I2CBitRead()
/******************************************************************
Processing: Read single bit from I2cbus slave. Allow slave to
request a delay by holding SCLock low. SCLock
has a pullup resistor and will go high if we
stop driving it AND the slave stops pulling it
down. We MUST NOT drive SDAata line, to allow the
slave to talk to us.
Inputs: As declared.
Outputs: return 1 or 0 from I2Cbus slave
Side-effects None.
*******************************************************************/
{
byte bit;
int clockstuck;
clr_mcsrbit(SDA_OE);
clocklow();
clockstuck = clockhigh();
if (! clockstuck)
bit = (*ptr2pal & SDA) ? 1 : 0; /* Read data bit */
else
bit = (byte) clockstuck;
clocklow();
return bit;
}
#define DRIVE_HI TRUE
int clockhigh ()
/******************************************************************
Processing: Put the clock line high by tri stating it.
If it stays low someone else is driving it, or
it is stuck.
Inputs:
Outputs: return success or I2C_STUCK_CLK.
Side-effects None.
*******************************************************************/
{
int i; /* loop counter */
halfperiod (); /* wait 1/2 clock period */
#if DRIVE_HI
set_mcsrbit (SCL); /* Drive SCLock line high */
#else
clr_mcsrbit (SCL_OE); /* let SCLock line float high */
#endif
for (i = 0; i < 10; i++) /* Give slave 5 clocks to get rdy*/
{
halfperiod(); /* wait 1/2 clk period */
if (*ptr2pal & SCL)
return SUCCESS; /* OK, slave is ready */
/* else, wait for slave to*/
/* let go of SCLock */
}
return I2C_STUCK_CLK; /* Clock Line stuck down */
} /* end function */
void clocklow()
/******************************************************************
Processing: Make clock go low by driving it
Inputs: data is the byte to send
Outputs: return success or failure.
Side-effects None.
*******************************************************************/
{
halfperiod (); /* wait 1/2 clock period */
clr_mcsrbit(SCL); /* make clock bit low */
set_mcsrbit(SCL_OE); /* and drive clock line */
}
static word mcsr_image = 0; /* the PAL bits are write only
so we keep a copy of the last
thing we wrote to the PAL*/
DLLEXPORT word set_mcsrbit (word bits2set)
/******************************************************************
Processing: Set bits in the Main Control & Status register (PAL)
Inputs:
Outputs: return last thing written in case caller wants
to know what's in the mcsr.
Side-effects None.
*******************************************************************/
{
mcsr_image |= bits2set;
*ptr2pal = mcsr_image;
return mcsr_image;
}
DLLEXPORT word clr_mcsrbit (word bits2clr)
/******************************************************************
Processing: Inverse of set_mcsrbit();
Inputs:
Outputs: return last thing written.
Side-effects None.
*******************************************************************/
{
mcsr_image &= ~bits2clr;
*ptr2pal = mcsr_image;
return mcsr_image;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -