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

How to get command/data on I2C Slave, which has been send from I2C master.

Hi All,

I am trying to implement I2C Slave functionality on NRF52832, So NRF52832 will act as a I2C slave. 

So i found there is an example TWIS Slave and TWI Master Mode Drivers Example (https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v12.2.0%2Ftwi_master_with_twis_slave_example.html). 

This is geed example to start. 

But i have a doubt, i am not sure how to receive data/command from I2C master and I2C slave device should respond against that data.  

in the example there is twis_event_handler() callback function which handles read/write operation on I2C slave device, So whenever master has to read data it just send a request to the i2c slave and twis_event_handler() callback function will get triggered, we get p_event->type and p_event->data.buf_req. So in response to this I2C slave send the data to the master. 

But suppose i have to send following command/data  from master to request some data from i2c slave

1).  0xA1 0xA2  0x1 0x2

2)   0xA4 0xA5  

So, how and where i2c slave will receive this command, so that according to received data/command, i2c slave can respond to the master. It would be great help if i can get some example.

Thanks & Regards

Pradeep

  • Hi,

    You will receive events in the twis_event_handler both when a read/write is requested (TWIS_EVT_READ/WRITE_REQ) and when it is done (TWIS_EVT_READ/WRITE_DONE). When the TWI master is done writing the command, you can check the received command in the WRITE_DONE event and prepare the TX buffer with the appropriate response. When the TWI master starts the read operation, you can provide the buffer in the READ_REQ event.

    Best regards,
    Jørgen

  • Hi Jargen,

    I understood your point. But how can i receive and store the data. May you please share some code to fetch that data/command in TWIS_EVT_READ/WRITE_DONE, it would great help.

    Thanks & Regards,

    Pradeep

  • You define the receive buffers in the application, so it should be easy to keep track of what buffer is used, either a global buffer for all transfers or separate buffers along with a variable indicating which buffer is currently in use. You can then access this buffer directly in the WRITE_DONE event. The valid bytes in the buffer is indicated by the p_event->data.rx_amount variable.

  • Hi Jorgen,

    May you please confirm, is the following implementation correct


    uint8_t buffer[20] = {0};
    int i = 0;
    int j = 0;
    static void twis_event_handler(nrf_drv_twis_evt_t const * const p_event)
    {
    debug_printf(" \nevent handler");
    switch (p_event->type)
    {
    case TWIS_EVT_READ_REQ:
    if (p_event->data.buf_req)
    {
    buffer[i] = p_event->data.rx_amount;
    i++;
    }
    break;
    case TWIS_EVT_READ_DONE:
    i = 0;
    break;
    case TWIS_EVT_WRITE_REQ:
    if (p_event->data.buf_req)
    {

    buffer[j] = p_event->data.tx_amount;
    j++;
    break;
    }
    break;
    case TWIS_EVT_WRITE_DONE:
    j = 0;
    break;

    case TWIS_EVT_READ_ERROR:
    case TWIS_EVT_WRITE_ERROR:
    case TWIS_EVT_GENERAL_ERROR:
    m_error_flag = true;
    break;
    default:
    break;
    }
    }

  • That code seems to do nothing TWIS-related. I was thinking something in the line of this (not compiled/tested):

    #define TWIS_MAX_LENGHT 20
    uint8_t tx_buffer[TWIS_MAX_LENGHT] = {0};
    uint8_t rx_buffer[TWIS_MAX_LENGHT] = {0};
    
    uint8_t rx_length = 0;
    
    uint8_t command1[4] = {0xA1, 0xA2, 0x01, 0x02};
    uint8_t command2[2] = {0xA4, 0xA5};
    
    uint8_t command1_response[16] = {0x00};
    uint8_t command2_response[8] = {0x55};
      
    static void twis_event_handler(nrf_drv_twis_evt_t const * const p_event)
    {
    	debug_printf(" \nevent handler");
    	switch (p_event->type)
    	{
    	case TWIS_EVT_READ_REQ:
    		if (p_event->data.buf_req)
    		{
    		nrf_drv_twis_tx_prepare(&m_twis, tx_buffer, TWIS_MAX_LENGHT);
    		}
    		break;
    	case TWIS_EVT_READ_DONE:
    		if(p_event->data.tx_amount == 4 && memcmp(tx_buffer, command1, 4) == 0)
    		{
    			// Fill rx_buffer with correct response for command1
    			memcpy(rx_buffer, command1_response, sizeof(command1_response));
    			rx_length = sizeof(command1_response);
    		}
    		else if(p_event->data.tx_amount == 2 && memcmp(tx_buffer, command2, 2) == 0)
    		{
    			// Fill rx_buffer with correct response for command2
    			memcpy(rx_buffer, command2_response, sizeof(command2_response));
    			rx_length = sizeof(command2_response);
    		}
    		else
    		{
    			// Fill buffer with default char to tell master command is not supported/recognized
    			memset(rx_buffer, 0xFF, TWIS_MAX_LENGHT);
    			rx_length = TWIS_MAX_LENGHT
    		}
    		break;
    	case TWIS_EVT_WRITE_REQ:
    		if (p_event->data.buf_req)
    		{
    			nrf_drv_twis_rx_prepare(&m_twis, rx_buffer, rx_length);
    		}
    		break;
    	case TWIS_EVT_WRITE_DONE:
    		// Clear buffer
    		memset(rx_buffer, 0x00, TWIS_MAX_LENGHT);
    		break;
    
    	case TWIS_EVT_READ_ERROR:
    	case TWIS_EVT_WRITE_ERROR:
    	case TWIS_EVT_GENERAL_ERROR:
    		m_error_flag = true;
    		break;
    		default:
    		break;
    	}
    }

Related