This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I have no trouble reading a single byte from a register on I2C device, but my following problem obviously has some bug when reading 2 bytes. Could anyone give me a pointer? Thanks!
int I2CReceive(uint32_t slave_chn, uint8_t reg, uint8_t num_of_args)
{
int iTemp;
//specify that we are writing (a register address) to the slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);
//specify register to be read
I2CMasterDataPut(I2C2_BASE, reg);
//send control byte and register address byte to slave device
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//SysCtlDelay(6000);
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);
if (num_of_args==1){
//This section works!
//send control byte and read from the register we
//specified
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
return (short)I2CMasterDataGet(I2C2_BASE);
}
else{
//num_of_args==2, this won't work
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= I2CMasterDataGet(I2C2_BASE);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;
return iTemp;
}
}
I took your suggestion and still have problem
From the logic analyzer, I expect 4 bytes on the bus in a group, but often the master refuses the ACK often, so I see 2 or 3-byte groups
_____________
int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
{
int iTemp;
//specify that we are writing (a register address) to the slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);
//specify register to be read
I2CMasterDataPut(I2C2_BASE, reg);
//send control byte and register address byte to slave device
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);
I2CMasterBurstLengthSet(I2C2_BASE, 2);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= I2CMasterDataGet(I2C2_BASE);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;
return iTemp;
}
I2C is new to me, do we need to use burst mode at all? I just need to read two bytes from a register (I need to read Temperature from Microchip's MCP9600, see timing below)
I2C is new to me, do we need to use burst mode at all? I just need to read two bytes from a register (I need to read Temperature from Microchip's MCP9600)
Attached is a screen shot, and you can see the master (TM1294) refused to ACK the first byte read from the device, the X marks the place the master should ACK at this point
BTW, I separate the read routine to make it a little easier to read:
//read specified register on slave device
int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
{
int iTemp;
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);
I2CMasterBurstLengthSet(I2C2_BASE, 2);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= I2CMasterDataGet(I2C2_BASE);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
iTemp= iTemp| I2CMasterDataGet(I2C2_BASE)<<8;
return iTemp;
}
After I use I2C_MASTER_CMD_BURST_RECEIVE_CONT (see codes attached), at least the master will ACK the second byte.
but new problem shows up
For the above capture, we can see the second byte is 0x01 and the third byte is 0x89, which matches the readings from MCP9600
When I exam the readings from I2CReceiveWord, I found out the first byte is 0x88 and the second byte 0x1, and I have no clue what they are
Even the attempt to flush FIFO by calling I2CMasterDataGet eight times first won't help, the data is unpredictable (but the output from MCP9600 looks perfectly fine). Any pointer?
int I2CReceiveWord(uint32_t slave_chn, uint8_t reg)
{
int iTemp;
int i, i1, i2, i3;
//specify that we are writing (a register address) to the
//slave device
//I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, false);
//specify register to be read
//I2CMasterDataPut(I2C2_BASE, reg);
//send control byte and register address byte to slave device
//I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START);
//wait for MCU to finish transaction
//while ((I2CMasterBusy(I2C2_BASE)));
//for (i=0; i<8; i++) I2CMasterDataGet(I2C2_BASE); //Do we need to flush the FIFO?
///SysCtlDelay(6000);
//specify that we are going to read from slave device
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_BASE+slave_chn, true);
I2CMasterBurstLengthSet(I2C2_BASE, 2);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
i1= I2CMasterDataGet(I2C2_BASE);
iTemp=(i1&0xff)<<8;
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C2_BASE));
//return data pulled from the specified register
i2=I2CMasterDataGet(I2C2_BASE);
iTemp= iTemp| (i2&0xff);
while(I2CMasterBusy(I2C2_BASE));
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
if (iTemp==257){
iTemp=-1;
}
return iTemp;
}