TWI slave

I am building a TWI slave with nRF52832.

I am attaching a part of twis_event_handler.

I can read even a 1-byte register value by executing i2c_read_register(SLAVE_ADDR, 0x11, &data); from the master side, but when I execute i2c_write_register(SLAVE_ADDR, 0x14, 0x05);
I can write the register address 0x14 to a variable, but I cannot write the register address 0x14.

The idea is to write the address with NRFX_TWIS_EVT_WRITE_REQ of twis_event_handler when i2c_write_register(SLAVE_ADDR, 0x14, 0x05); and then write the register with NRFX_TWIS_EVT_WRITE_DONE, but even if I execute err_code = nrf_drv_twis_rx_prepare(&m_twis, &m_twi_register[m_register_address], 1); the value of m_twi_register[0x14] does not change.

Is this the right idea?

void twis_event_handler(nrf_drv_twis_evt_t const * p_event)
{
    ret_code_t err_code;

    switch (p_event->type)
    {
        case NRFX_TWIS_EVT_WRITE_REQ:
            err_code = nrf_drv_twis_rx_prepare(&m_twis, &m_register_address, 1);
            APP_ERROR_CHECK(err_code);
            break;

        case NRFX_TWIS_EVT_READ_REQ:
            if (m_register_address + p_event->data.rx_amount > TWI_BUFFER_SIZE)
            {
                printf("Error: Attempt to read outside of buffer\n");
                return;
            }
            err_code = nrfx_twis_tx_prepare(&m_twis, &m_twi_register[m_register_address], p_event->data.rx_amount);  // 複数バイト送信
            APP_ERROR_CHECK(err_code);
            m_register_address++;
            break;

        case NRFX_TWIS_EVT_WRITE_DONE:
            if (p_event->data.tx_amount == 1)
            {
                uint32_t size = p_event->data.tx_amount;
                err_code = nrf_drv_twis_rx_prepare(&m_twis, &m_twi_register[m_register_address], 1);
                APP_ERROR_CHECK(err_code);
            }

Parents Reply Children
  • The code shown is incomplete, but I missed it when glancing over it.

    The idea is to give the WRITE_REQ event a bigger buffer than one byte - and then to handle it in the "WRITE_DONE" event when there was >1 byte transmitted.

    I recommend an oscilloscope / logic analyser. You should have seen the NACK  in the write transaction on the bus since the buffer was too small.

  • The TWI slave handler is created and executed as follows:

    void twis_event_handler(nrf_drv_twis_evt_t const * p_event)
    {
    static bool address_received = false; // Track whether the register address was received

    switch (p_event->type)
    {
    case NRFX_TWIS_EVT_READ_REQ:
    // If there is a read request from the master
    nrf_drv_twis_tx_prepare(&m_twis, &m_twi_register[m_register_address], TWI_BUFFER_SIZE - m_register_address);
    NRF_LOG_INFO("Read request: register address = 0x%02X", m_register_address);
    break;

    case NRFX_TWIS_EVT_WRITE_REQ:
    if (!address_received) {
    // If the register address has not yet been received, prepare to receive the register address
    NRF_LOG_INFO("Preparing to receive register address...");
    nrf_drv_twis_rx_prepare(&m_twis, &m_register_address, 1);
    } else {
    // If register address received, prepare to write data
    NRF_LOG_INFO("Register address received: 0x%02X", m_register_address);
    if (m_register_address < TWI_BUFFER_SIZE) {
    NRF_LOG_INFO("Preparing to write data to register 0x%02X", m_register_address);
    nrf_drv_twis_rx_prepare(&m_twis, &m_twi_register[m_register_address], TWI_BUFFER_SIZE - m_register_address);
    } else {
    NRF_LOG_ERROR("Invalid register address: 0x%02X", m_register_address);
    }
    }
    break;

    case NRFX_TWIS_EVT_WRITE_DONE:
    if (!address_received) {
    // If register address was received
    address_received = true; // Set flag
    NRF_LOG_INFO("Register address 0x%02X received", m_register_address);
    } else {
    // If data was written
    address_received = false; // Reset flag
    NRF_LOG_INFO("Data written to register 0x%02X: 0x%02X", m_register_address, m_twi_register[m_register_address]);
    }
    break;

    case NRFX_TWIS_EVT_READ_DONE:
    NRF_LOG_INFO("Read completed");
    break;

    case NRFX_TWIS_EVT_READ_ERROR:
    NRF_LOG_ERROR("TWIS EVT READ ERROR");
    break;

    case NRFX_TWIS_EVT_WRITE_ERROR:
    NRF_LOG_ERROR("TWIS EVT WRITE ERROR");
    break;

    case NRFX_TWIS_EVT_GENERAL_ERROR:
    NRF_LOG_ERROR("TWIS EVT GENERAL ERROR");
    break;

    default:
    break;
    }
    }

    Read works fine from the master side, but Write gives NRFX_TWIS_EVT_GENERAL_ERROR
    and does not write to the register properly.
    Please tell me the problem with the source.

Related