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

📄 dev_i2c_main.c

📁 i2c总线接口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*===========================================================================    Copyright 2000, 2001 Holley Communications. All rights reserved.*//***************************************************************************** * * DEV_I2C_MAIN.C - I2C Communication Interface: Main Driver * * PURPOSE: *    To provide a generic communication interface to devices on an *    'Inter-IC Communications' (I2C) bus. This file contains the *    communication service routines available to clients needing *    to talk to I2C devices attached to this bus via the CDMA+ processor. * *    In this implementation, this module assumes the role of the I2C Bus *    Master and provides read/write access to slave devices. Access to *    the underlying 3-wire I2C interface (clock, data and ground) is *    provided through functions in the file DEV_I2C_IO.C. * *    At the physical layer, two directional General-purpose I/O lines *    are used for the SDA and SDL signal paths. The signal directions *    are dynamically switched at the appropriate times to effect *    half-duplex communication with the slave devices (as opposed to using *    the traditional open-collector interface). * * HISTORY: * * GLOBAL FUNCTIONS: *    'dev_i2c_initialize'  - Initialize I2C Communication Interface *    'dev_i2c_write'       - Write Data to I2C Slave Device *    'dev_i2c_read'        - Read Data from I2C Slave Device * * LOCAL FUNCTIONS: *    None * * INTERNAL FUNCTIONS: *    'dev_i2c_txdevaddr'   - Transmit I2C Device Address *    'dev_i2c_busstate'    - Get I2C Bus State *    'dev_i2c_txdatabyte'  - Send Data Byte on I2C Bus *    'dev_i2c_txstartbit'  - Send Start Bit *    'dev_i2c_txstopbit'   - Send a Stop Bit *    'dev_i2c_txdatabit'   - Send Data Bit *    'dev_i2c_rxdatabyte'  - Receive Data Byte From I2C Slave *    'dev_i2c_rxdatabit'   - Receive Data Bit *    'dev_i2c_rxackbit'    - Receive Acknowledgement Bit *    'dev_i2c_wait4sclrls' - Wait for SCL Release * * NOTE: *    The basic timing functions are currently tied to the clock speed *    of the processor. Hence changes in clock speed will produce *    changes in I2C signal timing ! * *    Multiple bus mastering is not currently supported. * *    The I2C timing produced by this logic is for 'standard mode'. In *    this mode the maximum SCL Clock frequency is 100 KHz. This corresponds *    to a SCL Clock period of 10 us. All clock related timing is based *    on this clock period. * * *****************************************************************************//* ------------------ D e f i n i t i o n   F i l e s --------------------- */#include "main_system.h"            /* System Environment */#include "main_io_cdmap.h"#include "pub_PIO.h"/* I2C Module Definitions */#include "dev_I2c_Global.h"             /* Global */#include "dev_i2c_local.h"              /* Local */#include "dev_i2c_main.h"               /* Internal */#ifndef HOST_BUILD/* ------------------------ L o c a l   D a t a --------------------------- *//* --------------------- I n t e r n a l   D a t a ------------------------ *//***************************************************************************** * * DEV_I2C_INITIALIZE - Initialize I2C Communication Interface * * PURPOSE: *    To initialize the signalling I/O hardware and then analyze the state *    of the Inter-IC (I2C) bus to ensure that is viable and ready for use. * * PARAMETERS: *    'parm' is a 32-bit user defined parameter (not currently used) * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS   => I2C bus is ready for use *    DEV_I2C_RETCODE_IOINITERR => I/O line initialization error *    DEV_I2C_RETCODE_BUSBUSY   => Error: bus is in use *                             (possible physical layer fault) * * NOTE: *    This function must be called before calling any other functions in *    this facility and before any of the modules that support I2C devices. * *****************************************************************************/#endifInt16 dev_i2c_initialize ( Long parm ){#ifndef HOST_BUILD   /* Initialize the signalling I/O hardware */   dev_i2c_io_initialize ();   /* If the I2c bus is not being driven (i.e. it's idle) */   if ( dev_i2c_busstate () == DEV_I2C_BUS_IDLE )   {      /* SUCCESS: Bus is free */      return ( DEV_I2C_RETCODE_SUCCESS );   }   else   {      /* ERROR: Bus is in use */      return ( DEV_I2C_RETCODE_BUSBUSY );   }#else   return DEV_I2C_RETCODE_SUCCESS;#endif}#ifndef HOST_BUILD#if !BOARD_PHOENIX/***************************************************************************** * * DEV_I2C_WRITE - Write Data to I2C Slave Device * * PURPOSE: *    To write a buffer of bytes to a specified slave device on *    the I2C bus. * * PARAMETERS: *    'deviceaddr' is the I2C slave device address *    'databufp' -> the data buffer to send *    'len' is the number of bytes in the buffer * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS   => Data sent successfully *    DEV_I2C_RETCODE_BUSBUSY   => Error: bus is in use; data not sent *    DEV_I2C_RETCODE_NOADDRACK => Error: address byte not acknowledged *                             (device not present, address incorrect, *                              or physical layer fault) *    DEV_I2C_RETCODE_NODATAACK => Error: data byte not acknowledged *                             (possible physical layer fault) * * NOTE: *    A write request with a data length of zero can be used to determine *    whether the specified device is installed. * *    The I2C device write protocol is as follows: *        1) check for an idle bus *        2) send start bit *        3) send slave address byte with Read/Write* (R/W*) bit clear *        4) check for a ACK to the address byte *        5) send each data byte checking for ACK bit *        6) send stop bit * *****************************************************************************/Int16 dev_i2c_write ( Byte deviceaddr, Byte *databufp, Word len ){   Word i;   /* If could not deliver the address byte */   if ( dev_i2c_txdevaddr ( deviceaddr, DEV_I2C_WRITE ) < 0 )   {      /* ERROR: Address byte not acknowledged */      return ( DEV_I2C_RETCODE_NOADDRACK );   }   /* For each byte in the message */   for ( i = 0; i < len; i++ )   {      /* If the byte is sent but not acknowledged */      if ( dev_i2c_txdatabyte ( *databufp++ ) < 0 )      {         /* ERROR: Data byte not acknowledged */         return ( DEV_I2C_RETCODE_NODATAACK );      }   }   /* Send a stop bit */   dev_i2c_txstopbit ();   /* SUCCESS: Data transmitted */   return ( DEV_I2C_RETCODE_SUCCESS );}/***************************************************************************** * * DEV_I2C_TXDEVADDR - Transmit I2C Device Address * * PURPOSE: *    To transmit the device address preamble prior to performing a read *    or write operation to an I2C device. * *    This operation includes: *         1) checking that the bus is currently free *         2) transmitting the start bit *         3) transmitting the address byte with the device address *            properly positioned and the R/W* bit set or reset based *            on the subsequent bus operation to be performed * * PARAMETERS: *    'deviceaddr' is the device's DEV_I2C address *    'operation' is the subsequent bus operation to be performed *              DEV_I2C_READ  => read operation *              DEV_I2C_WRITE => write operation * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS  => Device addressed *    DEV_I2C_RETCODE_BUSBUSY  => Error: bus is in use; data not sent *    DEV_I2C_RETCODE_NOACK    => Error: acknowledgement not received *                            (device not present, address incorrect, *                             or physical layer fault) *    DEV_I2C_RETCODE_SCLRLSTO => Error: Slave SCL release timeout error *                            (possible physical layer fault) *     * NOTE: *     *****************************************************************************/Int16 dev_i2c_txdevaddr ( Byte deviceaddr, Bool operation ){   Byte addrbyte;                   /* I2C address byte */   /* If the bus is currently in use */   if ( dev_i2c_busstate () == DEV_I2C_BUS_BUSY )   {      /* ERROR: Failed to acquire the bus */      return ( DEV_I2C_RETCODE_BUSBUSY );   }   /* Put the I2C device address in position in the address byte */   addrbyte = ( deviceaddr << 1 );   /* If this is a write operation */   if ( operation == DEV_I2C_WRITE )   {      /* Clear the Read/Write* (R/W*) bit */      addrbyte &= ~DEV_I2C_BIT_RDWRNOT;   }   else   {      /* Set the Read/Write* (R/W*) bit */      addrbyte |= DEV_I2C_BIT_RDWRNOT;   }    /* Send a start bit */     dev_i2c_txstartbit ();    /* Transmit the address byte, check for acknowledgement and return status */   return ( dev_i2c_txdatabyte ( addrbyte ) );}/***************************************************************************** * * DEV_I2C_TXDATABYTE - Send Data Byte on I2C Bus * * PURPOSE: *    To send an 8-bit data byte on the I2C bus and then monitor the *    slave device for the acknowledgement handshake. * * PARAMETERS: *    'data' is Byte to send to bus * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS  => Byte sent successfully *    DEV_I2C_RETCODE_NOACK    => Error: acknowledgement not received *                            (device not present, address incorrect, *                             or physical layer fault) *    DEV_I2C_RETCODE_SCLRLSTO => Error: Slave SCL release timeout error *                            (possible physical layer fault) * * NOTE: *     A slow device may hold the SCL line low for a protracted period *     of time prior to delivering the ACK bit to achieve a quasi- *     'wait state' effect. * *****************************************************************************/Int16 dev_i2c_txdatabyte ( Byte data ){   Int16 retcode;                   /* Bit transmit return code */   Word i;   /* For each bit in the data byte */   for ( i = 0; i < 8; i++ )   {      /* Send the current data bit */      retcode = dev_i2c_txdatabit ( data & 0x80 );      /* If the bit was not successfully transmitted */      if ( retcode < 0 )      {         /* ERROR: Bit transmit error */         return ( retcode );      }      /* Shift the data */      data = data << 1;   }   /* Finally, receive the Ack bit and return status */   return ( dev_i2c_rxackbit () );}/***************************************************************************** * * DEV_I2C_TXSTARTBIT - Send Start Bit * * PURPOSE: *    To signal the start of a transmission by sending a start bit on *    the I2C bus. * * PARAMETERS: *    None * * RETURNS: *    Nothing * * NOTE: *    The I2C bus should by determined to be idle prior to calling *    this function. *     *    A start bit is signalled as follows: *       > drive       SDA low  for a 1/2 clock period (5.0 us) *       > drive       SCL low *     *****************************************************************************/void dev_i2c_txstartbit ( void ){   /* Drive the data line (SDA) low */   dev_i2c_io_sdalow ();   /* Drive the clock line (SCL) low */   dev_i2c_io_scllow ();}/***************************************************************************** * * DEV_I2C_TXSTOPBIT - Send a Stop Bit * * PURPOSE: *    To signal the end of a transmission by sending a stop bit on *    the I2C bus. * * PARAMETERS: *    None * * RETURNS: *    Nothing * * NOTE: *    The I2C bus should by determined to be idle prior to calling *    this function. *     *    A stop bit is signalled as follows: *       > drive       SCL low  for a 1/4 clock period (2.5 us) *       > drive       SDA low  for a 1/4 clock period (2.5 us) *       > tri-state   SCL high for a 1/2 clock period (5.0 us)  *       > tri-state   SDA high *     *****************************************************************************/void dev_i2c_txstopbit ( void ){   /* Drive the clock line (SCL) low */   dev_i2c_io_scllow ();   /* Drive the data line (SDA) low */   dev_i2c_io_sdalow ();   /* Tri-state the clock line (SCL) (it will be pulled high) */   dev_i2c_io_scltristate ();   /* Tri-state the data line (SDA) (it will be pulled high) */   dev_i2c_io_sdatristate ();}/***************************************************************************** * * DEV_I2C_TXDATABIT - Send Data Bit * * PURPOSE: *    To send a data bit to the currently addressed I2C slave device. * * PARAMETERS: *    'bit' is the bit value to send * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS  => Data bit sent *    DEV_I2C_RETCODE_SCLRLSTO => Error: Slave SCL release timeout error *                            (possible physical layer fault) * * NOTE: *    When sending a '1' bit the SDA should not be driven. Instead tri- *    state the line and let the external pull-up signal a '1' to the *    slave. This technique is essential to correct signalling on I2C *    buses with voltage translation. * *    A data bit is transmitted as follows: *       > drive       SCL low  for a 1/4 clock period (2.5 us) *   '0' > drive       SDA low  for a 1/4 clock period (2.5 us), or, *   '1' > tri-state   SDA high for a 1/4 clock period (2.5 us)  *       > tri-state   SCL high *       > wait for    SCL high (slave release) *       > wait for    for a 1/2 clock period (5.0 us)  * *     A slow device may hold the SCL line low for a protracted period *     of time prior to accepting a data bit to achieve a quasi- *     'wait state' effect. * *****************************************************************************/Int16 dev_i2c_txdatabit ( Byte bit ){   Int16 retcode;                   /* SCL release return code */   /* Drive the clock line low */   dev_i2c_io_scllow ();   /* If the data bit is a 'high' */   if ( !bit )   {      /* Drive the data line (SDA) low */      dev_i2c_io_sdalow ();   }   else   {      /* Tri-state the data line (SDA) high (it is pulled high externally) */      dev_i2c_io_sdatristate ();   }   /* Tri-state the clock (SCL) line */   dev_i2c_io_scltristate ();   /* Wait for the slave to release the SCL signal */   retcode = dev_i2c_wait4sclrls ();   /* If SCL was not released */   if ( retcode < 0 )   {      /* ERROR: Slave failed to release SCL */      return ( retcode );   }   /* SUCCESS: Data bit transmitted */   return ( DEV_I2C_RETCODE_SUCCESS );}/***************************************************************************** * * DEV_I2C_RXACKBIT - Receive Acknowledgement Bit * * PURPOSE: *    To wait for an acknowledgement bit from the slave device on I2C bus. * * PARAMETERS: *    None * * RETURNS: *    DEV_I2C_RETCODE_SUCCESS  => Got the ACK bit *    DEV_I2C_RETCODE_NOACK    => Error: acknowledgement not received *                            (device not present, address incorrect, *                             or physical layer fault) *    DEV_I2C_RETCODE_SCLRLSTO => Error: Slave SCL release timeout error *                            (possible physical layer fault) * * NOTE: *    An ACK bit is received as follows: *       > drive       SCL low  for a 1/4 clock period (2.5 us) *       > tri-state   SDA high for a 1/4 clock period (2.5 us)  *       > tri-state   SCL high *       > wait for    SCL high (slave release) *       > wait for    for a 1/4 clock period (2.5 us)  *       > read SDA line *       > wait for    for a 1/4 clock period (2.5 us)  *       > '0'         SDA low  => ACK received *       > '1'         SDA high => no ACK * *     A slow device may hold the SCL line low for a protracted period *     of time prior to delivering the ACK bit to achieve a quasi- *     'wait state' effect. *     *****************************************************************************/Int16 dev_i2c_rxackbit ( void ){   Bool sdastate;                   /* SDA signal state */   Int16 retcode;                   /* Wait operation return code */   /* Set the clock line (SCL) low */   dev_i2c_io_scllow ();   /* Tri-state the data (SDA) line */   dev_i2c_io_sdatristate ();   /* Tri-state the clock (SCL) line */   dev_i2c_io_scltristate ();   /* Wait for the slave to release the SCL signal */   retcode = dev_i2c_wait4sclrls ();   /* If SCL was not released */   if ( retcode < 0 )

⌨️ 快捷键说明

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