?? dev_i2c_main.c
字號:
/*=========================================================================== 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 + -