This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI: change SCL and SDA directly?

I am using the nRF52 Preview kit (PCA 10036 board) and SDK 0.9.2. Up to this point, I have been able to do everything I want with TWI using the hardware driver. This time I need to do something which is strange, at least to me.

I am working with an I2C sensor which has some settings that I can adjust. The sensor is a slave-only device. After programming my adjustments, the sensor needs to be powered off, or put into a sleep mode, and then restarted. Here is the procedure (ignore the part about the device's PWM mode, I'm not using it):

image description

I need to set SCL low and hold it there for a while (not sure how long, I plan to try 1.0 seconds). Then I need to set SCL high again. Finally, I need to pull SDA low for a time, tDDq, which the specification says is a minimum of 33 milliseconds. At this point, the device should be restarted.

I have been looking through both the TWI hardware driver API and the HAL documentation. So far I haven't found functions which would allow me to manipulate SCL directly. This makes some sense to me, since if such functions were exposed, it would be easy for someone who didn't know what they were doing to leave the TWI in a stuck state.

The initial step, pulling SCL low, should be easy. I will simply write my sleep command using nrf_drv_twi_tx(), with pending_transfer set to true. How to set SCL high again, and then how to toggle SDA, is not so clear. I could possibly accomplish these tasks by directly manipulating the GPIO registers connected to my TWI. Are there any hazards associated with doing so, besides the ones I already mentioned? I am concerned that, even if I manipulate the SCL and SDA correctly, that might trigger something in the TWI driver which would cause thing to get out of sync.

Is this method of sleeping and waking commonly used by I2C devices? It would appear that putting this device to sleep effectively requires me to lock down the entire TWI bus on which it resides. I'm annoyed that the sensor doesn't have a simpler way to be rebooted, such as an extra reset pin on the package. I may add an analog switch to my breadboard, so that I can control the sensor's power using a GPIO line.

In the long term, I plan to add multiple I2C sensors of different types to my device. Can I have multiple instances of TWI drivers, each talking to different pins?

  • Just wait until the TWI is finished, write 0xffffffff to the two pin registers to disconnect them, write the GPIO pins yourself with a simple delay to generate the reset you want, then put the pins back in the registers again. No need to be fancy about it.

  • Hello again RK, you seem to respond to most of my questions. Thanks for your help.

    I consulted Sections 18 (GPIO) and 47 (TWI) of the nRF52832 hardware specification. Section 47.2 mentions two registers, PSELSCL and PSELSDA, which are associated with connecting the TWI to GPIO. When you write, "write 0xffffffff to the two pin registers to disconnect them," are these the two registers you meant? I guess I would read the contents of these registers, store their values, then overwrite with 0xFFFFFFFF, then perform my sleep-and-wake procedure, and finally restore the register values.

    Alternately, I guess I could also call nrf_drv_twi_uninit(). Shouldn't that release the GPIO lines from TWI hardware control? Next, I would perform my sleep-and-wake procedure, then call nrf_drv_twi_init(). Is that a better or worse procedure than the above?

Related