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

📄 xi2c_l.c

📁 Viertex 2 开发板的接口程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "xbasic_types.h"
#include "xio.h"
#include "xipif_v1_23_b.h"
#include "xi2c_l.h"


/***************************** XI2c_mClearIisr *****************************
 *
 * This macro clears the specified interrupt in the IPIF interrupt status
 * register.  It is non-destructive in that the register is read and only the
 * interrupt specified is cleared.  Clearing an interrupt acknowledges it.
 *
 * @param    BaseAddress contains the IPIF registers base address.
 * @param    InterruptMask contains the interrupts to be disabled.
 *
 * @return   None.
 *
 * Signature: void XIic_mClearIisr(Xuint32 BaseAddress,Xuint32 InterruptMask);
 *
 ***************************************************************************/
#define XI2c_mClearIisr(BaseAddress, InterruptMask)                 \
    XIIF_V123B_WRITE_IISR((BaseAddress),                            \
        XIIF_V123B_READ_IISR(BaseAddress) & (InterruptMask))


#define XI2c_mClearTXFifo(BaseAddress)                                 \
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,                         \
             XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_TX_FIFO_RESET_MASK); \
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET,                         \
             XIIC_CR_ENABLE_DEVICE_MASK);

/***************************** XI2c_mSend7BitAddr **************************
*
* This macro sends the address for a 7 bit address during both read and write
* operations. It takes care of the details to format the address correctly.
* This macro is designed to be called internally to the drivers.
*
* @param    SlaveAddress contains the address of the slave to send to.
* @param    Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION
*
* @return   None.
*
* Signature: void XI2c_mSend7BitAddr(Xuint16 SlaveAddress, Xuint8 Operation);
*
******************************************************************************/
#define XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, Operation) {       \
  Xuint8 LocalAddr = (Xuint8)(SlaveAddress << 1);                           \
  LocalAddr = (LocalAddr & 0xFE) | (Operation);                             \
  XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, LocalAddr);                   \
}


/************************* XI2c_mSendStartAddress ***************************/
#define XI2c_mSendStartAddress(BaseAddress, StartAddress) {                 \
  XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, StartAddress);                \
} 


/************************** Function Prototypes ****************************/
static Xuint8 RecvData(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		       Xuint8 *BufferPtr, Xuint8 ByteCount);
static Xuint8 SendData(Xuint32 BaseAddress, Xuint8 SlaveAddress,
		       Xuint8 *BufferPtr, Xuint8 ByteCount);
static Xuint8 TXSuccess(Xuint32 BaseAddress);
static Xuint8 RXSuccess(Xuint32 BaseAddress);
static Xuint8 SlaveRecvData(Xuint32 BaseAddress, Xuint8 *BufferPtr);
static Xuint8 SlaveSendData(Xuint32 BaseAddress, Xuint8 *BufferPtr);
static void PrintStatus(Xuint32 BaseAddress);

/****************************** XI2c_Recv *********************************
 *
 * Receive data as a master on the IIC bus.  This function receives the data
 * using polled I/O and blocks until the data has been received.  It only
 * supports 7 bit addressing and non-repeated start modes of operation.  The
 * user is responsible for ensuring the bus is not busy if multiple masters
 * are present on the bus.
 *
 * @param    BaseAddress contains the base address of the IIC device.
 * @param    Address contains the 7 bit IIC address of the device to send the
 *           specified data to.
 * @param    BufferPtr points to the data to be sent.
 * @param    ByteCount is the number of bytes to be sent.
 *
 * @return   The number of bytes received.
 *
 ****************************************************************************/
Xuint8 XI2c_Recv(Xuint32 BaseAddress, Xuint8 SlaveAddress,
		   Xuint8 *BufferPtr, Xuint8 ByteCount) {
  Xuint8 CtrlReg;

  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK;

  if( ByteCount == 1 ) {
    /** Set the rx_fifo depth to 1 (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);
    
    /** Send the slave device address **/
    XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);

    /** Enable no-ack for the single byte transfer **/
    CtrlReg |= XIIC_CR_NO_ACK_MASK;
  }
  else if( ByteCount > 1 ) {
    /** Set the rx_fifo to 1 less than the byte count (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, ByteCount-2);
    
    /** Send the slave device address **/
    XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);
  }

  /** Enable the device and begin the data transfer **/
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Clear this once the communication begins **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK);

  return RecvData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);
  
} // XI2c_Recv()


Xuint8 XI2c_RSRecv(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		   Xuint8 StartAddress, Xuint8 *BufferPtr, 
		   Xuint8 ByteCount) {
  Xuint8 CtrlReg;

  /** Clear any ISR values that may need clearing **/
  XI2c_mClearIisr(BaseAddress, 
		  XIIC_INTR_BNB_MASK | XIIC_INTR_RX_FULL_MASK | 
		  XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
		  XIIC_INTR_ARB_LOST_MASK);

  /** Send slave device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_WRITE_OPERATION);
  XI2c_mSendStartAddress(BaseAddress, StartAddress);
  
  /** Enable device and indicate data transmission **/
  CtrlReg = XIIC_CR_MSMS_MASK | XIIC_CR_ENABLE_DEVICE_MASK |
    XIIC_CR_DIR_IS_TX_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);
  
  /** Send the data **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_BNB_MASK | XIIC_INTR_TX_ERROR_MASK);
  if( !TXSuccess(BaseAddress) ) {
    //print("XI2c_RSRecv : 1 : TXFailure\r\n");
    //PrintStatus(BaseAddress);
    return 0;
  }

  /** Enable the repeated start **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK | XIIC_CR_MSMS_MASK |
    XIIC_CR_REPEATED_START_MASK;
  
  if( ByteCount == 1 ) {
    /** Set the rx_fifo depth to 1 (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);

    /** Enable the no-ack for the single byte transfer **/
    CtrlReg |= XIIC_CR_NO_ACK_MASK;
  }
  else if( ByteCount > 1 ) {
    /** SEt the rx_fifo depth to 1 less than ByteCount (zero-based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, ByteCount-2); 
  }
  
  /** Enable the device and begin the data transfer **/
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Send the slave device address **/
  XI2c_mSend7BitAddress(BaseAddress, SlaveAddress, XIIC_READ_OPERATION);

  return RecvData(BaseAddress, SlaveAddress, BufferPtr, ByteCount);

} // end XI2c_Recv()


static Xuint8 RecvData(Xuint32 BaseAddress, Xuint8 SlaveAddress, 
		       Xuint8 *BufferPtr, Xuint8 ByteCount) {

  Xuint8 IntrStatus, CtrlReg;
  Xuint8 count = 0;

  if( ByteCount > 1 ) {

    /** Receive the data **/
    if( !RXSuccess(BaseAddress) ) {
      //print("RecvData : 1 : RXFailure\r\n");
      return 0;
    }

    /** Set no-ack for the last byte **/
    CtrlReg = XIo_In8(BaseAddress + XIIC_CR_REG_OFFSET) |
      XIIC_CR_NO_ACK_MASK;
    XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

    /** Read in the data from the rx_fifo **/
    for( count = 0; count < (ByteCount-1); count++ ) {
      *(BufferPtr++) = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
      //xil_printf("Data received: %d\r\n", *(BufferPtr-1));
    }

    /** Clear the rx_full flag **/
    XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);

    /** Set the rx_fifo depth to 1 (zero based) **/
    XIo_Out8(BaseAddress + XIIC_RFD_REG_OFFSET, 0);
  
  }

  /** Receive the data **/
  if( !RXSuccess(BaseAddress) ) {
    //print("RecvData : 2 : RXFailure\r\n");
    return 0;
  }

  /** Set up for a clean release of the iic bus **/
  CtrlReg = XIIC_CR_ENABLE_DEVICE_MASK;
  XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, CtrlReg);

  /** Read in the data from the rx_fifo **/
  *BufferPtr = XIo_In8(BaseAddress + XIIC_DRR_REG_OFFSET);
  //xil_printf("Data received: %d\r\n", *BufferPtr); 

  /** Clear the rx_full mask **/
  XI2c_mClearIisr(BaseAddress, XIIC_INTR_RX_FULL_MASK);

  /* The receive is complete, disable the IIC device and return the number of
   * bytes that was received, we must wait for the bnb flag to properly
   * disable the device. THIS DOESN'T WORK RIGHT. */
/*    print("Waiting for bnb_high..."); */
/*    do { */
/*      IntrStatus = XIIF_V123B_READ_IISR(BaseAddress); */
/*    } while(!(IntrStatus & XIIC_INTR_BNB_MASK)); */
/*    print("done!\r\n"); */

  //XIo_Out8(BaseAddress + XIIC_CR_REG_OFFSET, 0);
  
  /* Return the number of bytes that was received */
  return ++count;

} // end RecvData()


/******************************* XI2c_Send *********************************
 *  
 * Send data as a master on the IIC bus.  This function sends the data
 * using polled I/O and blocks until the data has been sent.  It only supports
 * 7 bit addressing and non-repeated start modes of operation.  The user is
 * responsible for ensuring the bus is not busy if multiple masters are 
 * present on the bus.
 *
 * @param    BaseAddress contains the base address of the IIC device.
 * @param    Address contains the 7 bit IIC address of the device to send the
 *           specified data to.
 * @param    BufferPtr points to the data to be sent.
 * @param    ByteCount is the number of bytes to be sent.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -