⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 用MSP430 IO 口模拟I2C通讯
💻 C
📖 第 1 页 / 共 2 页
字号:

#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 + -