📄 i2c.c
字号:
#include <pic.h>
#include "c:\test\delay.c"
#include "c:\test\i2c.h"
#define sim_on
/*
* Send stop condition
* - data low-high while clock high
*/
void
i2c_Stop(void)
{
/* assume SCL is high on entry */
SCL_DIR = I2C_OUTPUT;
SDA = 0; /* ensure the data is low first */
SDA_DIR = I2C_OUTPUT;
DelayUs(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
DelayUs(I2C_TM_STOP_SU);
SDA = 1; /* the low->high data transistion */
DelayUs(I2C_TM_BUS_FREE); /* bus free time before next start */
return;
}
/*
* Send (re)start condition
* - ensure data is high then issue a start condition
* - see also i2c_Start() macro
*/
void
i2c_Restart(void)
{
SDA_DIR = I2C_OUTPUT;
SCL_DIR = I2C_OUTPUT;
SCL = 1; /* ensure clock is low */
SDA = 1; /* ensure data is high */
asm("nop");
SDA = 0; /* the high->low transition */
asm("nop");
SCL=0;
return;
}
/*
* Send a byte to the slave
* - returns true on error
*/
unsigned char
i2c_SendByte(unsigned char byte)
{
signed char i;
for(i=7; i>=0; i--)
{
SCL_DIR = I2C_OUTPUT; /* drive clock low */
SCL=1;
SDA_DIR = I2C_OUTPUT;
SDA = ((byte>>i) & 0x01); /* bit to send */
SCL=0;
//DelayUs(I2C_TM_DATA_SU);
//asm("nop");
}
return 1;
}
/*
* send an address and data direction to the slave
* - 7-bit address (lsb ignored)
* - direction (FALSE = write )
*/
unsigned char
i2c_SendAddress(unsigned char address, unsigned char rw)
{
return i2c_SendByte(address | (rw?1:0));
}
/*
* Check for an acknowledge
* - returns ack or ~ack, or ERROR if a bus error
*/
signed char
i2c_ReadAcknowledge(void)
{
unsigned char ack;
//SCL_DIR = I2C_OUTPUT;
SDA_DIR = I2C_INPUT; /* disable data line - listen for ack */
//DelayUs(I2C_TM_SCL_TO_DATA); /* SCL low to data out valid */
asm("nop");
SCL=1;
asm("nop");
SCL=0;
ack = SDA; /* read the acknowledge */
if(ack!=0)
{
#ifndef sim_on
putst(" yes ! got ack \n");
#endif
asm("nop");
}
else
{
#ifndef sim_on
putst(" sorry ! can got ack :~ \n");
#endif
asm("nop");
}
}
/*
* Read a byte from the slave
* - returns the byte, or I2C_ERROR if a bus error
*/
unsigned char byte = 0;
int
i2c_ReadByte(void)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL_DIR = I2C_OUTPUT;
//DelayUs(I2C_TM_SCL_LOW); /* min clock low period */
asm("nop");
SDA_DIR = I2C_INPUT; /* release data line */
asm("nop");
byte = byte << 1; /* read the next bit */
byte |= SDA;
}
return (int)byte;
}
/*
* Send an (~)acknowledge to the slave
* - status of I2C_LAST implies this is the last byte to be sent
*/
void
i2c_SendAcknowledge(unsigned char status)
{
SCL_DIR = I2C_OUTPUT;
SDA = status?0:1; /* drive line low -> more to come */
SDA_DIR = I2C_OUTPUT;
DelayUs(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
DelayUs(I2C_TM_SCL_HIGH);
return;
}
/*
* Send a byte to the slave and acknowledges the transfer
* - returns I2C_ERROR, ack or ~ack
*/
signed char
i2c_PutByte(unsigned char data)
{
if(i2c_SendByte(data))
return I2C_ERROR;
return i2c_ReadAcknowledge(); /* returns ack, ~ack */
}
/*
* Get a byte from the slave and acknowledges the transfer
* - returns true on I2C_ERROR or byte
*/
int
i2c_GetByte(unsigned char more)
{
uchar byte;
if((byte = i2c_ReadByte()) == I2C_ERROR)
return I2C_ERROR;
i2c_SendAcknowledge(more);
return byte;
}
/*
* Send an array of bytes to the slave and acknowledges the transfer
* - returns number of bytes not successfully transmitted
*/
int
i2c_PutString(const unsigned char *str, unsigned char length)
{
signed char error;
while(length)
{
if((error = i2c_PutByte(*str)) == I2C_ERROR)
return -(int)length; /* bus error */
else
if(error)
return (int)length; /* non acknowledge */
str++;
length--;
}
return FALSE; /* everything OK */
}
/*
* Reads number bytes from the slave, stores them at str and acknowledges the transfer
* - returns number of bytes not successfully read in
*/
unsigned char
i2c_GetString(unsigned char *str, unsigned char number)
{
int byte;
while(number)
{
if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
return number; /* bus error */
else
*str = (unsigned char)byte;
str++;
number--;
}
return FALSE; /* everything OK */
}
/*
* Opens communication with a device at address. mode
* indicates I2C_READ or I2C_WRITE.
* - returns TRUE if address is not acknowledged
*/
unsigned char
i2c_Open(unsigned char address, unsigned char mode)
{
i2c_Start();
i2c_SendAddress(address, mode);
if(i2c_ReadAcknowledge())
return TRUE;
return FALSE;
}
#if 0
/*
* wait for the clock line to be released by slow slaves
* - returns TRUE if SCL was not released after the
* time out period.
* - returns FALSE if and when SCL released
*/
unsigned char
i2c_WaitForSCL(void)
{
/* SCL_DIR should be input here */
if(!SCL)
{
DelayUs(I2C_TM_SCL_TMO);
/* if the clock is still low -> bus error */
if(!SCL)
return TRUE;
}
return FALSE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -