2020-02-05 10:02 AM
Hello, I am having some trouble with getting I2C to work.
My code:
void i2c_init(void) {
/* Periph clock enable */
SysCtrl_PeripheralClockCmd(CLOCK_PERIPH_GPIO | CLOCK_PERIPH_I2C2, ENABLE);
// I2C2 pins
GPIO_InitI2c2ClkPin4(); // SCL at DIO4
GPIO_InitI2c2DataPin5(); // SDA at DIO5
I2C_InitType i2c_settings;
I2C_StructInit( & i2c_settings);
i2c_settings.I2C_ClockSpeed = 100000;
i2c_settings.I2C_OperatingMode = I2C_OperatingMode_Master;
I2C_Init(I2C2, & i2c_settings);
I2C_ClearITPendingBit(I2C2, I2C_IT_MSK);
I2C_Cmd(I2C2, ENABLE);
}
int i2c_write(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) {
I2C_TransactionType t;
// Write the slave address
t.Operation = I2C_Operation_Write;
t.Address = addr;
t.StartByte = I2C_StartByte_Disable;
t.AddressType = I2C_AddressType_7Bit;
t.StopCondition = I2C_StopCondition_Enable;
t.Length = 1 + len;
// Flush the slave address
I2C_FlushTx(I2C2);
while (I2C_WaitFlushTx(I2C2) == I2C_OP_ONGOING);
// Begin transaction
I2C_BeginTransaction(I2C2, & t);
// Fill TX FIFO with data to write
I2C_FillTxFIFO(I2C2, reg);
for (uint8_t i = 0; i < len; i++) {
I2C_FillTxFIFO(I2C2, data[i]);
}
// Wait loop
do {
if (I2C_GetStatus(I2C2) == I2C_OP_ABORTED) {
return ERROR;
}
} while (I2C_GetITStatus(I2C2, I2C_IT_MTD) == RESET);
// Clear pending bits
I2C_ClearITPendingBit(I2C2, I2C_IT_MTD | I2C_IT_MTDWS);
return SUCCESS;
}
int i2c_read(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) {
I2C_TransactionType t;
// Write the slave address
t.Operation = I2C_Operation_Write;
t.Address = addr;
t.StartByte = I2C_StartByte_Disable;
t.AddressType = I2C_AddressType_7Bit;
t.StopCondition = I2C_StopCondition_Disable;
t.Length = 1;
// Flush the slave address
I2C_FlushTx(I2C2);
while (I2C_WaitFlushTx(I2C2) == I2C_OP_ONGOING);
// Begin transaction
I2C_BeginTransaction(I2C2, & t);
// Fill TX FIFO with data to write
I2C_FillTxFIFO(I2C2, reg);
// Wait loop
do {
if (I2C_GetStatus(I2C2) == I2C_OP_ABORTED) {
// Here it returns ERROR
return ERROR;
}
} while (I2C_GetITStatus(I2C2, I2C_IT_MTDWS) == RESET);
// Clear pending bits
I2C_ClearITPendingBit(I2C2, I2C_IT_MTDWS);
// read data
t.Operation = I2C_Operation_Read;
t.Address = addr;
t.StartByte = I2C_StartByte_Disable;
t.AddressType = I2C_AddressType_7Bit;
t.StopCondition = I2C_StopCondition_Enable;
t.Length = len;
I2C_BeginTransaction(I2C2, & t);
// Wait loop
do {
if (I2C_OP_ABORTED == I2C_GetStatus(I2C2)) {
return ERROR;
}
} while (RESET == I2C_GetITStatus(I2C2, I2C_IT_MTD));
// Clear pending bits
I2C_ClearITPendingBit(I2C2, I2C_IT_MTD | I2C_IT_MTDWS);
// Get data from RX FIFO
while (len--) {
* data = I2C_ReceiveData(I2C2);
data++;
}
return SUCCESS;
}
For example, when I try to read a register using this i2c_read function, it returns ERROR when it checks status for I2C_OP_ABORTED in the write phase.r
I also tried the version with enabled interrupts and i2c_eot flag. The handler I2C2_Handler is never executed and it stucks when waiting in while(i2c_eot == RESET).
What am I doing wrong? I triple checked the wiring and it should be OK. Thanks.
Solved! Go to Solution.
2020-02-05 01:12 PM
OK, I solved this problem with help of logic analyzer. I was putting in the device address in 8-bit format, but it seems the I2C peripheral shifts it 1 bit left (it assumes 7-bit address). So adding line
addr >>= 1;
at the beggining of read and write methods solved the problem.
The next problem was missing pull-up resistors. Under Table 129 "IO functional map" in the BlueNRG-2 datasheet, there is a note you can easily miss, saying: "All the I2C pins require external pull-up". I didn't know before so it could not work properly...
2020-02-05 01:12 PM
OK, I solved this problem with help of logic analyzer. I was putting in the device address in 8-bit format, but it seems the I2C peripheral shifts it 1 bit left (it assumes 7-bit address). So adding line
addr >>= 1;
at the beggining of read and write methods solved the problem.
The next problem was missing pull-up resistors. Under Table 129 "IO functional map" in the BlueNRG-2 datasheet, there is a note you can easily miss, saying: "All the I2C pins require external pull-up". I didn't know before so it could not work properly...