/********************************************************************* * @fn hali2cReceive * @brief reads data into a buffer * @param address: linear address on part from which to read * @param buffer: target array for read characters * @param len: max number of characters to read * @return void */ STATIC void hali2cReceive( uint8 address, uint8 *buffer, uint16 len ) { //uint8 ch; uint16 i; if (!len) { return; } hali2cSendDeviceAddress(address); //ch = OCM_ADDRESS_BYTE(0, OCM_READ); //hali2cSend(&ch, 1, SEND_START, NOSEND_STOP); for ( i = 0; i < len-1; i++ ) { // SCL may be high. set SCL low. If SDA goes high when input // mode is set the slave won't see a STOP hali2cClock(0); OCM_DATA_HIGH(); buffer[i] = hali2cReceiveByte(); hali2cWrite(SMB_ACK); // write leaves SCL high } // condition SDA one more time... hali2cClock(0); OCM_DATA_HIGH(); buffer[i] = hali2cReceiveByte(); hali2cWrite(SMB_NAK); hali2cStop(); }
/********************************************************************* * @fn hali2cStart * @brief Initiates SM-Bus communication. Makes sure that both the * clock and data lines of the SM-Bus are high. Then the data * line is set high and clock line is set low to start I/O. * @param void * @return void */ STATIC void hali2cStart( void ) { uint8 retry = HAL_I2C_RETRY_CNT; // set SCL to input but with pull-up. if slave is pulling down it will stay down. hali2cClock(1); do { // wait for slave to release clock line... if (OCM_SCL) // wait until the line is high... { break; } hali2cWait(1); } while ( --retry ); // SCL low to set SDA high so the transition will be correct. hali2cClock(0); OCM_DATA_HIGH(); // SDA high hali2cClock(1); // set up for transition hali2cWait(1); OCM_DATA_LOW(); // start hali2cWait(1); hali2cClock( 0 ); }
/********************************************************************* * @fn hali2cStop * @brief Terminates SM-Bus communication. Waits unitl the data line * is low and the clock line is high. Then sets the data line * high, keeping the clock line high to stop I/O. * @param void * @return void */ STATIC void hali2cStop( void ) { // Wait for clock high and data low hali2cClock(0); OCM_DATA_LOW(); // force low with SCL low hali2cWait(1); hali2cClock( 1 ); OCM_DATA_HIGH(); // stop condition hali2cWait(1); }
/********************************************************************* * @fn hali2cWrite * @brief Send one bit to SM-Bus device * @param dBit - data bit to clock onto SM-Bus * @return void */ STATIC void hali2cWrite( bool dBit ) { hali2cClock( 0 ); hali2cWait(1); if ( dBit ) { OCM_DATA_HIGH(); } else { OCM_DATA_LOW(); } hali2cClock(1); hali2cWait(1); }
/********************************************************************* * @fn hali2cSendByte * @brief Serialize and send one byte to SM-Bus device * @param dByte - data byte to send * @return ACK status - 0=none, 1=received */ STATIC _Bool hali2cSendByte( uint8 dByte ) { uint8 i; for ( i = 0; i < 8; i++ ) { // Send the MSB hali2cWrite( dByte & 0x80 ); // Next bit into MSB dByte <<= 1; } // need clock low so if the SDA transitions on the next statement the // slave doesn't stop. Also give opportunity for slave to set SDA hali2cClock( 0 ); OCM_DATA_HIGH(); // set to input to receive ack... hali2cClock( 1 ); hali2cWait(1); return ( !OCM_SDA ); // Return ACK status }
void ADXL345ReadBytes(uint8 startAddr, uint8* buffer, uint8 len) { // wait turns to receive the slave ack uint8 retry = HAL_I2C_RETRY_CNT; // 7-bit address and W/R bit byte firstByte = 0x00; byte i = 0; // Send start condition hali2cStart(); // Send the slave address and wirte bit firstByte = 0xA6; // seven-bit slave address and write bit '0', 0x1111_1110 do { if ( hali2cSendByte(firstByte) ) // takes care of ack polling { retry = HAL_I2C_RETRY_CNT; break; } } while ( --retry ); // Send the reg address do { if ( hali2cSendByte(startAddr) ) // takes care of ack polling { retry = HAL_I2C_RETRY_CNT; break; } } while ( --retry ); // this is the repeat start condition hali2cStart(); // Send the slave address and read bit firstByte = 0xA7; do { if ( hali2cSendByte(firstByte) ) // takes care of ack polling { retry = HAL_I2C_RETRY_CNT; break; } } while ( --retry ); // read several bytes for ( i = 0; i<len-1; i++ ) { // SCL may be high. set SCL low. If SDA goes high when input // mode is set the slave won't see a STOP hali2cClock(0); OCM_DATA_HIGH(); buffer[i] = hali2cReceiveByte(); hali2cWrite(SMB_ACK); // write leaves SCL high } // condition SDA one more time... // hali2cClock(0); // OCM_DATA_HIGH(); // buffer[i] = hali2cReceiveByte(); // hali2cWrite(SMB_NAK); // Send stop condition hali2cStop(); }