Assigning I2C pins manually
In some hardware setups you may want to change the I2C pins (SDA & SCL) manually, different from the default one (P22-sda and P20-scl). To do that you would need to access the hardware configuration registers directly.
For I2C on the nRF51822, it's the NRF_TWI0->PSELSCL and the NRF_TWI0->PSELSDA you need to modify. Here is an example that I re-configure the pin to P1-SCL and P2-SDA:
void I2C_reconfigure_pins (void)
{
NRF_GPIO->PIN_CNF[p2] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos));
NRF_GPIO->PIN_CNF[p1] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos));
NRF_TWI0->PSELSCL = p1;//scl;
NRF_TWI0->PSELSDA = p2;//sda;
}
Since in the I2C library from mbed, the I2C pins got reset and reconfigured back to default one every time there is a unsuccessful transmission, we need to call I2C_reconfigure_pins() before every I2C API call.
Attached here is an example of a modified version of the MMA7660FC so that pin P1, and P2 is assigned for I2C pins: /media/uploads/nemovn/mma7660.cpp
Note: you still have to initiate MMA7660 MMA(p22, p20); with the default pin P22 and P20 otherwise you will receive the error from mbed since the pin wasn't correctly.
4 comments on Assigning I2C pins manually :
Please log in to post comments.

The need to call this before every I2C call makes it pretty awkward. I just modify the library sources when I need to change the I2C pins (though, of course, that is awkward for other reasons).