/** * @brief Reads an 8-bit register from an I2C slave */ uint8_t i2c_read_register(register uint8_t slaveId, register uint8_t registerAddress){ /* loop while the bus is still busy */ i2c_wait_while_busy(); /* send I2C start signal and set write direction, also enables ACK */ i2c_send_start(); /* send the slave address and wait for the I2C bus operation to complete */ i2c_send_byte(I2C_WRITE_ADDRESS(slaveId)); /* send the register address */ i2c_send_byte(registerAddress); /* signal a repeated start condition */ i2c_send_repeated_start(); /* send the read address */ i2c_send_byte(I2C_READ_ADDRESS(slaveId)); /* switch to receive mode but disable ACK because only one data byte will be read */ i2c_enter_receive_mode_without_ack(); /* read a dummy byte to drive the clock */ i2c_read_dummy_byte(); /* stop signal */ i2c_send_stop(); /* fetch the last received byte */ register uint8_t result = I2C0->D; return result; }
int i2c_read (uint8_t chip_id, uint8_t reg_addr, uint8_t* buffer, uint16_t len) { int status = 0; /* send chip internal register address (pointer register) */ if (status == 0) i2c_send_start (); if (status == 0) status = i2c_write_byte (chip_id << 1 | I2C_WRITE_OPER); if (status == 0) status = i2c_write_byte (reg_addr); if (status == 0) i2c_send_repeated_start (); /* send again chip id before to switch to read mode */ if (status == 0) status = i2c_write_byte ((chip_id << 1) | I2C_READ_OPER); if (status == 0) i2c_switch_to_read_operation(len > 1); /* read specified number of bytes */ if (status == 0) { while (len > 1) { *buffer++ = i2c_read_byte (--len > 1); } } i2c_send_stop (); if (status == 0) *buffer++ = i2c_read_byte (false); return status; }
/** * @brief Reads multiple 8-bit registers from an I2C slave * @param[in] slaveId The slave device ID * @param[in] startRegisterAddress The first register address * @param[in] registerCount The number of registers to read; Must be greater than or equal to two. * @param[out] buffer The buffer to write into * @return 0 is successful, 1 if not */ static int i2c_read_registers_internal(register uint8_t slaveId, register uint8_t startRegisterAddress, register uint8_t registerCount, uint8_t *const buffer){ if(registerCount < 2) return -1; /* loop while the bus is still busy */ i2c_wait_while_busy(); /* send I2C start signal and set write direction, also enables ACK */ i2c_send_start(); /* send the slave address and wait for the I2C bus operation to complete */ i2c_send_byte(I2C_WRITE_ADDRESS(slaveId)); /* send the register address */ i2c_send_byte(startRegisterAddress); /* signal a repeated start condition */ i2c_send_repeated_start(); /* send the read address */ i2c_send_byte(I2C_READ_ADDRESS(slaveId)); /* switch to receive mode and assume more than one register */ i2c_enter_receive_mode_with_ack(); /* read a dummy byte to drive the clock */ i2c_read_dummy_byte(); /* for all remaining bytes, read */ --registerCount; uint8_t index = 0; while (--registerCount > 0) { /* fetch and store value */ register uint8_t value = I2C0->D; buffer[index++] = value; /* wait for completion */ i2c_wait(); } /* disable ACK and read second-to-last byte */ i2c_disable_ack(); /* fetch and store value */ buffer[index++] = I2C0->D; /* wait for completion */ i2c_wait(); /* stop signal */ i2c_send_stop(); /* fetch the last received byte */ buffer[index++] = I2C0->D; return 0; }