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

TWI handler with nrf_drv_twi_tx()

I have created a library for HD44780 Hitachi LCD, and I can transmit data to the LCD through an IO Expander without any problem over TWI lines. Right now I am not using any TWI Handler function for transmitting data.

I have functions within lcd_init() and lcd_print("") that call expanderWrite(uint8_t buffer) to send data to LCD and they work fine.

So, my question is do I really need a TWI Handler function? If yes, can I make a function like this?

/* Indicates if sending data has ended. */
static volatile bool xfer_completed = false;

static const nrf_drv_twi_t m_twi_hd44780 = NRF_DRV_TWI_INSTANCE(0);
 
/**
 * @brief TWI initialization.
 */
 void twi_init (void)
 {
    ret_code_t err_code;

   const nrf_drv_twi_config_t twi_hd44780_config = {
       .scl                = TWI_SCL_M,
       .sda                = TWI_SDA_M,
       .frequency          = NRF_TWI_FREQ_400K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH
    };

    err_code = nrf_drv_twi_init(&m_twi_hd44780, &twi_hd44780_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi_hd44780);
}

static ret_code_t expanderWrite(uint8_t buffer)
{
	return nrf_drv_twi_tx(&m_twi_hd44780, LCD_addr, &buffer, sizeof(buffer), false);     
}

void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{   
    if ((p_event->type == NRF_DRV_TWI_EVT_DONE) &&
        (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX))
        {
            xfer_completed = true;
        }
    else
        {
           xfer_completed = false;
        }
}


int main(void)
{
    lcd_init();
    while(xfer_completed == false);
    xfer_completed = false;
    lcd_print("Hello, world!");
    while(xfer_completed == false);
    xfer_completed = false;
}

By the way, regardless of setting the last parameter of function nrf_drv_twi_tx() (bool xfer_pending) to "true" or "false", my code works fine. Is it better practice to keep it "true" or "false"?

If you need more pieces of code to be able to help me please let me know.

Thanks

  • Hi,

    No, you don't really need it if you don't care about current consumption or the fact that without a handler nrf_drv_twi_tx() will block the CPU from performing other tasks during the TWI transfer. If you use a handler you can save power by entering sleep mode while the TWI is doing its thing. Or you can let the CPU work on other tasks and get more stuff done faster.

    Your code should work. However, if you just wait for the transfer to complete in a while() loop you lose the benefit of using a handler. Your CPU will continuously check whether xfer_completed is true or false unable to work on other things and consuming power.

    By using xfer_pending you can tell the driver that you want to generate a stop condition after a transfer. If you issue a stop condition after a transfer it indicates to all devices on the TWI bus that you are done with all transfers and that the bus is free to use. If you don't issue a stop condition it means that you, as the TWI master, want to keep control of the bus because you expect to send more data. So as long as you are only communicating with one slave I don't think it matters if you use xfer_pending or not.

  • Hi Martin,

    Thanks for your great explanation.

    I don't really care about current consumption, but just wanted to learn how create a proper twi_handler() function. Later on, I will add a RFID Card Reader device on the same TWI line along with this LCD.

    I tried the twi_handler() function above and worked like you said. But as you pointed out if I just wait for the transfer to complete in a while() loop I lose the benefit of using a handler. So, how should I change my code to take advantage of twi_handler() function?

    Do I have to use the a condition similar to this piece of code to take advantage of twi_handler() function, or not necessarily?

       `do
        {
            __WFE();
        }while(xfer_completed == false);
        nrf_drv_twi_tx(&m_twi_hd44780, LCD_addr, &buffer, sizeof(buffer), false);
        xfer_completed = false;`
    

    Thanks

  • Yes, that is right. If you haven't done so already you can take a look at the twi_sensor example in the SDK. It does exactly as you suggest. You can also see that they start the TX in the main while(true) loop and then start the RX from within the twi_handler() to read data from the sensor.

Related