📄 i2c.c
字号:
#include "I2C.h" // common definitions
#include "msp430x22x4.h"
#include "Delay.h"
extern unsigned char IRpulseBuff1[];
/****************** Public Variables ***********************************/
unsigned char ucI2C_Err;
/****************** Private Variables **********************************/
static char cI2C_Status; // Status code
// used also to indicating if
// Data has been sent / received
/**************** Private Functions Definitions **********************/
void I2C_SendStop ( void ); // sends stop signal
void I2C_SendStart ( void ); // sends start signal
// clears error code !!!
void I2C_SCL_High ( void ); // sets SCL = 1 and checks if it is high
// if it is not, there is a vDelay
// error is generated if SCL is hold low
// for certain duration
void I2C_SendByte ( unsigned char ucData );
// sends 1 byte, checks ACK / NACK
unsigned char I2C_GetByte ( unsigned char ucLastByteFlag );
// receives 1 byte.
// If ucLastByteFlag > 0 receives last byte - sends NACK
// at the end of the transmission
/********************** Public Functions ****************************/
/******** Initialization procedure *************/
void vInitI2C ( void )
{
I2C_PORT_DIR &= ~I2C_MASK; // set SCL and SDA to inputs = high SCL and SDA lines
I2C_PORT_OUT &= ~I2C_MASK; // SDA and SCL outputs low
// output pin is controled only by I2C_PORT_DIR
// configured as output = 0
// input = 1
vDelay ( I2C_DELAY );
}
/*********************************************/
void I2C_DelayWriteByte ( unsigned char ucDevAddr,
unsigned char ucDataAddr,
unsigned char ucData,
unsigned int uivDelay )
{
I2C_MASK_IE_PORT &= ~I2C_IRQ_MASK; // forbid IRQ
vDelay ( uivDelay );
// move IRQ mask here ????
I2C_SendStart();
if ( cI2C_Status == I2C_OK )
{
I2C_SendByte( ucDevAddr );
I2C_SendByte( ucDataAddr );
I2C_SendByte( ucData );
}
I2C_SendStop();
ucI2C_Err = cI2C_Status;
I2C_MASK_IE_PORT |= I2C_IRQ_MASK; // allow IRQ
}
/*********************************************/
void vI2C_DelayWrite4Bytes (unsigned char ucDevAddr,
unsigned char ucDataAddr,
unsigned long ulData,
unsigned int uivDelay )
{
char i;
I2C_MASK_IE_PORT &= ~I2C_IRQ_MASK; // forbid IRQ
vDelay ( uivDelay );
// move IRQ mask here ???
I2C_SendStart();
if ( cI2C_Status == I2C_OK )
{
I2C_SendByte( ucDevAddr );
I2C_SendByte( ucDataAddr );
for ( i = 0; i < 4; i++ ) // does not check cI2C_Status for bytes
{
I2C_SendByte( (unsigned char) (ulData >>(24-8*i)) );
}
}
I2C_SendStop();
ucI2C_Err = cI2C_Status;
I2C_MASK_IE_PORT |= I2C_IRQ_MASK; // allow IRQ
}
/*********************************************/
void I2C_DelayWriteByteNum ( unsigned char ucDevAddr,
unsigned char ucDataAddr,
unsigned char const *pucData,
unsigned char ucNumBytes,
unsigned int uivDelay )
{
char i;
I2C_MASK_IE_PORT &= ~I2C_IRQ_MASK; // forbid IRQ
vDelay ( uivDelay );
// move IRQ mask here ???
I2C_SendStart();
if ( cI2C_Status == I2C_OK )
{
I2C_SendByte( ucDevAddr );
I2C_SendByte( ucDataAddr );
for ( i = 0; i < ucNumBytes; i++ ) // does not check cI2C_Status for bytes
I2C_SendByte( *(pucData + i) );
}
I2C_SendStop();
ucI2C_Err = cI2C_Status;
I2C_MASK_IE_PORT |= I2C_IRQ_MASK; // allow IRQ
}
/********************************************/
unsigned char I2C_ReadByte ( unsigned char ucDevAddr,
unsigned char ucDataAddr)
{
unsigned char ucData;
I2C_MASK_IE_PORT &= ~I2C_IRQ_MASK; // forbid IRQ
_NOP();
I2C_SendStart();
if ( cI2C_Status == I2C_OK )
{
I2C_SendByte( ucDevAddr ); // write address !!
I2C_SendByte( ucDataAddr );
I2C_SendStop();
I2C_SendStart();
I2C_SendByte( ucDevAddr | I2C_READ ); // read address
//ucData = I2C_Get_two_Bytes( I2C_LAST_BYTE ); // return value
ucData = I2C_GetByte( I2C_LAST_BYTE ); // return value
//I2C_SendStop();
//I2C_SendStart();
//I2C_SendByte( ucDataAddr );
//I2C_SendStop();
//I2C_SendStart();
//I2C_SendByte( ucDevAddr | I2C_READ ); // read address
//ucData = I2C_GetByte( I2C_LAST_BYTE ); // return value
}
I2C_SendStop();
ucI2C_Err = cI2C_Status;
I2C_MASK_IE_PORT |= I2C_IRQ_MASK; // allow IRQ
return ucData;
}
/****************** Private Functions ******************************/
/******** Start Signal procedure ************/
void I2C_SendStart ( void ) // check if I2C bus is being used
{ // must be high state at both SCL and SDA
unsigned char ucvDelay = I2C_WAIT;
cI2C_Status = I2C_OK; // Clear previous error ... new try
I2C_SCL_High(); //
/**/
while ( (( I2C_PORT_IN & I2C_MASK) != I2C_MASK) // both SCL and SDA must be high to continue
&& ( ucvDelay != 0 )) // vDelay - waiting for the BUS to become available
{
ucvDelay--;
}
if ( ucvDelay == 0 ) // uivDelay = 0 => time-out
cI2C_Status = I2C_BUSY; // error
else // no error
{
cI2C_Status = I2C_OK;
I2C_PORT_DIR |= SDA; // SDA pin = 0
vDelay ( I2C_DELAY ); // vDelay
I2C_PORT_DIR |= SCL; // SCL pin = 0
}
}
/********** Set SCL high *****************/
void I2C_SCL_High ( void )
{
unsigned int uiCycle = SCL_MAX_WAIT_CYCLES; // maximum waiting cycles
vDelay ( I2C_DELAY ); // Delay
_NOP();
I2C_PORT_DIR &= ( ~SCL ); // SCL pin = 1
vDelay ( I2C_DELAY ); // Delay
_NOP();
while ( !(I2C_PORT_IN & SCL) ) // is the slave IC holding SCL = 0 ?
{
uiCycle--;
vDelay ( 1*MS_DELAY ); // each cycle approximately = 1ms
if ( uiCycle == 0 )
{
cI2C_Status = I2C_SCL_LOW; // time-out => SCL line is stuck low for too long
return;
}
}
}
void I2C_SCL_High_for_CP_writting ( void )
{
unsigned int uiCycle = SCL_MAX_WAIT_CYCLES; // maximum waiting cycles
vDelay ( 10 ); // Delay
_NOP();
I2C_PORT_DIR &= ( ~SCL ); // SCL pin = 1
vDelay ( 10 ); // Delay
_NOP();
while ( !(I2C_PORT_IN & SCL) ) // is the slave IC holding SCL = 0 ?
;
vDelay ( 10 ); // Delay
}
/*********** Stop procedure ****************/
void I2C_SendStop (void )
{
I2C_PORT_DIR |= SDA; // SDA pin = 0
vDelay ( I2C_DELAY );
I2C_SCL_High (); // SCL pin = high
vDelay ( I2C_DELAY );
I2C_PORT_DIR &= ( ~SDA ); // SDA pin = high
vDelay ( I2C_DELAY );
}
/************** Send Byte *******************/
void I2C_SendByte ( unsigned char ucData )
{
register unsigned char i;
if ( cI2C_Status != I2C_OK ) // error -> do not send Byte, BUS is not free
return; // this error check can be embedded in the "for" loop
// to cover errors that occured during transmision
for ( i=0; i<8; i++ )
{
if ( ucData & 0x80 ) // bit 7 - check and -> if(bit==1) ...
{ // set data line to the MSB (bit 7)
I2C_PORT_DIR &= ~SDA; // SDA pin = 1
} else {
I2C_PORT_DIR |= SDA; // SDA pin = 0
}
vDelay ( I2C_DELAY );
I2C_SCL_High (); // SCL pin = 1
vDelay ( I2C_DELAY );
I2C_PORT_DIR |= SCL; // SCL pin = 0
vDelay ( I2C_DELAY );
ucData = ucData << 1; // next bit will be 6 ... 0
}
// vDelay ( I2C_Delay );
I2C_PORT_DIR &= ~SDA; // SDA pin = high - listen for ACK
vDelay ( I2C_DELAY );
I2C_SCL_High (); // SCL pin = high
vDelay ( I2C_DELAY );
if ( I2C_PORT_IN & SDA ) // bit check and -> if(bit==1) SDA is high = NACK
{
cI2C_Status = I2C_NACK; // NACK
}
// vDelay ( I2C_Delay );
I2C_PORT_DIR |= SCL; // SCL pin = 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -