Hello,
I am trying to get my TM4C1294NCPDT to work with an AD5667R DAC chip over I2C. It is not the only device I'm talking to over I2C. There are 7 other devices (ETC, SiliconID, External Temperature Sensor, Fan Controller, and so on) that work fine but this DAC consistently misbehaves.
I'm using the same communication API for all the devices. For the DAC, I'm writing a value into a control register and then read it back. The value that I read back is always shifted by one bit to the left. For example, if I wrote 0x05, I get 0x0A back. Or, if I wrote, 0x0F, I get 0x1E back.
As far as I can tell, the data becomes corrupted when I write as opposed to be corrupted in transmission when I read. The LSB in the original value is what I need to set but it never gets set judging from the behavior of the chip. It does not error out, which makes me think that the slave address and the command (the first byte of the transmission) make it through just fine. The error (missing bit?) takes place between the command byte and the first transmitted byte of the payload. The payload is seen shifted by one bit by the DAC chip.
With that, my question to the more experienced developers is this. Considering that the I2C communication is coded up correctly (7 devices work just fine), what could be the probable cause of the shift in payload by one bit for every attempted write operation into the slave?
Here is my draft code. It could be suboptimal or wrong, but I will greatly appreciate the feedback that would help to make it work without losing bits in transmission.
Thank you!
// slave_addr - slave address (7-bit) // reg - DAC control register number // tempArray - pointer to the payload // numOfBytes - payload length (this is always 2 in this example) uint32_t I2CController::I2CSendArray(uint32_t slave_addr, uint8_t reg, uint8_t* tempArray, uint32_t numOfBytes) { I2CMasterSlaveAddrSet(i2cConfig.base, slave_addr, false); //set write to slave if (WaitWhileMasterBusIsBusy(i2cConfig.base, COUNTS_BLOCK_TO_WAIT, MAX_COUNT_WAIT) != ERR_I2C_OK) return ERR_I2C_BUS_BUSY; I2CMasterDataPut(i2cConfig.base, reg); // register to write to be sent into fifo //initiate send of data from mcu I2CMasterControl(i2cConfig.base, I2C_MASTER_CMD_BURST_SEND_START); uint32_t err = GetStatusOfMasterOperation(); if(err != 0) return err; if (WaitWhileMasterIsBusy(i2cConfig.base, COUNTS_BLOCK_TO_WAIT, MAX_COUNT_WAIT) != ERR_I2C_OK) return ERR_I2C_MASTER_BUSY; uint32_t ind= 0; for (; ind < numOfBytes-1; ind++) { I2CMasterDataPut(i2cConfig.base, tempArray[ind]); // put data to be sent into the fifo I2CMasterControl(i2cConfig.base, I2C_MASTER_CMD_BURST_SEND_CONT); err = GetStatusOfMasterOperation(); if(err != 0) return err; if (WaitWhileMasterIsBusy(i2cConfig.base, COUNTS_BLOCK_TO_WAIT, MAX_COUNT_WAIT) != ERR_I2C_OK) return ERR_I2C_MASTER_BUSY; } //put the last piece of data into I2C FIFO I2CMasterDataPut(i2cConfig.base, tempArray[ind]); //send next data that was just placed into FIFO I2CMasterControl(i2cConfig.base, I2C_MASTER_CMD_BURST_SEND_FINISH); err = GetStatusOfMasterOperation(); if(err != 0) return err; if (WaitWhileMasterIsBusy(i2cConfig.base, COUNTS_BLOCK_TO_WAIT, MAX_COUNT_WAIT) != ERR_I2C_OK) return ERR_I2C_MASTER_BUSY; return 0; }