NRF52840 I2C ADDRESS.

Hello Everyone,

                           I am working on NRF52840 development kit. I am trying to run I2c master. My main goal is to send some data to slave via I2C lines. I am using the example code "TWI scanner" from the sdk examples. I have attached the slave microcontroller (ATSAMD20) and I am running i2c slave code on it. The Slave address is 0x54. I have set it as 0x54 in the slave code. Now when I try to scan the devices from NRF52840, the device is found at 0x28 address. Why is it so?? 

Parents
  • Thanks for your reply Kenneth. Something weird is happening at my side. I agree with your left bit shifting. I tried to test the code again. Now NRF52840 is scanning 2 addresses. 

    my code is as follows:-

    int main(void){

    ret_code_t err_code;
    uint8_t address = (0x54U); 
    uint8_t data;
    bool detected_device = false;
    bool result = false;

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("TWI scanner started.");
    NRF_LOG_FLUSH();
    twi_init();
    nrf_delay_ms(1000); // give some delay

    for (address = 1; address <= TWI_ADDRESSES; address++)
    {
    err_code = nrf_drv_twi_rx(&m_twi, address, &data, sizeof(data));
    if (err_code == NRF_SUCCESS)
    {
    detected_device = true;
    NRF_LOG_INFO("TWI device detected at address 0x%x...0x%x", address,data);
    NRF_LOG_FLUSH();
    send_data();
    }
    NRF_LOG_FLUSH();
    }


    void send_data(void)
    {
    ret_code_t err_code;
    uint8_t address = (0x54U);
    uint8_t sample_data=0xaa;
    uint8_t sample_data1;


    err_code = nrf_drv_twi_tx(&m_twi, address, &sample_data, sizeof(sample_data), true);
    //Wait for the transmission to get completed
    //while (m_xfer_done == false){}
    nrf_delay_ms(1000); // give some delay


    // If transmission was not successful, exit the function with false as return value
    if (NRF_SUCCESS != err_code)
    {
    NRF_LOG_INFO("FAILED 1.");
    NRF_LOG_FLUSH();
    }
    else
    {
    NRF_LOG_INFO("SUCCESS 1.");
    NRF_LOG_FLUSH();
    }

    }

    This is my log on nrf module :- 

    <info> app: TWI scanner started.
    <info> app: TWI device detected at address 0x28...0x0
    <info> app: SUCCESS 1.
    <info> app: TWI device detected at address 0x54...0xAA
    <info> app: SUCCESS 1.

    0XAA is the data which I had sent to the slave. Now why is it scanning 2 addresses when I have attached only one slave with address 0x54?? 

  • I think I read somewhere that the ATSAMD20 can support multiple (e.g. 2) i2c slave addresses?

    Kenneth

  • Thanks, I got it. I had one question. I tested my code with SDA and SCL lines as p026 and p027. Now if I want to use SCL pin as P1.09 and SDA pin as P0.11 how do I configure port 1 and port 0 seperately?

  • You can use the following macro from nrf_gpio.h:

    /** @brief Macro for mapping port and pin numbers to values understandable for nrf_gpio functions. */
    #define NRF_GPIO_PIN_MAP(port, pin) (((port) << 5) | ((pin) & 0x1F))

    e.g. scl = NRF_GPIO_PIN_MAP(1,9);

  • Hi Kenneth,

             Thanks for your reply. I solved that issue. Now my question is I have 3 slaves connected to NRF52840 on the same I2C lines SCL pin as P1.09 and SDA pin as P0.11. I am able to connect to slave 1. Now for adding slave 2 and slave 3 do I need to add something extra or I can read all 3 slaves from the same instance?? 

    Warm Regards,

    Snehal.

  • Hi,

    Good to hear you have solved it. There should be nothing in specific needed to handle 3 slaves, you only need to update the address for each slave, and also I suggest wait for the previous transaction to complete before starting the next.

    Kenneth

  • Hi Kenneth,

                         I had one question. I have a I2c slave device SAMD20, I am able to initiate a connection with samd20. Now I want to send sample data "0xaa" through I2c. SAMD20 has no registers. It is directly configured as a slave device with slave id 0x54. How can i send data through i2c?? 

    I am trying to use this code:- 

    bool samd20_register_write(uint8_t register_address, uint8_t value)
    {
    ret_code_t err_code;
    uint8_t tx_buf[SAMD20_ADDRESS_LEN+1];

    //Write the register address and data into transmit buffer
    tx_buf[0] = register_address;
    tx_buf[1] = value;

    //Set the flag to false to show the transmission is not yet completed
    m_xfer_done = false;

    //Transmit the data over TWI Bus
    err_code = nrf_drv_twi_tx(&m_twi, SAMD20_ADDRESS, tx_buf, SAMD20_ADDRESS_LEN+1, false);

    //Wait until the transmission of the data is finished
    while (m_xfer_done == false)
    {
    }

    // if there is no error then return true else return false
    if (NRF_SUCCESS != err_code)
    {
    return false;
    }

    return true;
    }

    But I am confused what should I pass as register address?? I have only slave address configured in the slave which is 0x54. SAMD20_ADDRESS =0x54. How do I send data ?? 

    samd20_register_write(register_address, 0xaa); 

    Please help me on this. 

Reply
  • Hi Kenneth,

                         I had one question. I have a I2c slave device SAMD20, I am able to initiate a connection with samd20. Now I want to send sample data "0xaa" through I2c. SAMD20 has no registers. It is directly configured as a slave device with slave id 0x54. How can i send data through i2c?? 

    I am trying to use this code:- 

    bool samd20_register_write(uint8_t register_address, uint8_t value)
    {
    ret_code_t err_code;
    uint8_t tx_buf[SAMD20_ADDRESS_LEN+1];

    //Write the register address and data into transmit buffer
    tx_buf[0] = register_address;
    tx_buf[1] = value;

    //Set the flag to false to show the transmission is not yet completed
    m_xfer_done = false;

    //Transmit the data over TWI Bus
    err_code = nrf_drv_twi_tx(&m_twi, SAMD20_ADDRESS, tx_buf, SAMD20_ADDRESS_LEN+1, false);

    //Wait until the transmission of the data is finished
    while (m_xfer_done == false)
    {
    }

    // if there is no error then return true else return false
    if (NRF_SUCCESS != err_code)
    {
    return false;
    }

    return true;
    }

    But I am confused what should I pass as register address?? I have only slave address configured in the slave which is 0x54. SAMD20_ADDRESS =0x54. How do I send data ?? 

    samd20_register_write(register_address, 0xaa); 

    Please help me on this. 

Children
  • I believe you are mixing a bit the Device (slave) address with the Register address(es). There are two typical sequences in 2-wire (I2C) transactions, to illustrate the write and read operations you can look at the below Figures:

    I suggest that you add a logic analyzer to the 2-wire (I2C) pins to see the actual data.

    Kenneth

  • Hi Kenneth,

        I am not having logic analyzer. I am not confusing between 2 addresses. I understand that slave address is used as an identifier by the master and register address is internal addresses of the slave device. But in my case, I dont have any registers in my slave device. So how to send data?? What to put in place of register address?

    Thanks & Regards,

    Snehal.

  • Looking at the api for nrf_drv_twi_tx() there is nothing preventing you from just set the first byte of p_data to your value instead of register_adress.

    /**
     * @brief Function for sending data to a TWI slave.
     *
     * The transmission will be stopped when an error occurs. If a transfer is ongoing,
     * the function returns the error code @ref NRF_ERROR_BUSY.
     *
     * @param[in] p_instance Pointer to the driver instance structure.
     * @param[in] address    Address of a specific slave device (only 7 LSB).
     * @param[in] p_data     Pointer to a transmit buffer.
     * @param[in] length     Number of bytes to send.
     * @param[in] no_stop    If set, the stop condition is not generated on the bus
     *                       after the transfer has completed successfully (allowing
     *                       for a repeated start in the next transfer).
     *
     * @retval NRF_SUCCESS                  If the procedure was successful.
     * @retval NRF_ERROR_BUSY               If the driver is not ready for a new transfer.
     * @retval NRF_ERROR_INTERNAL           If an error was detected by hardware.
     * @retval NRF_ERROR_INVALID_ADDR       If the EasyDMA is used and memory adress in not in RAM.
     * @retval NRF_ERROR_DRV_TWI_ERR_ANACK  If NACK received after sending the address in polling mode.
     * @retval NRF_ERROR_DRV_TWI_ERR_DNACK  If NACK received after sending a data byte in polling mode.
     */
    __STATIC_INLINE
    ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance,
                              uint8_t               address,
                              uint8_t const *       p_data,
                              uint8_t               length,
                              bool                  no_stop);

    Best regards,
    Kenneth

  • Hi Kenneth,

                  I tried doing that also but no luck. The strange part is when I try to initialize it using the function below, I get a SUCCESS message, but when I try to send data to samd20 nothing is being received on samd20.

    SAMD20_ADDR = 0X54;

    bool samd20_i2c_init(void)
    {
    ret_code_t err_code;
    // uint8_t address = 0x54;
    uint8_t sample_data = 0x00;

    err_code = nrf_drv_twi_rx(&m_twi,SAMD20_ADDR,&sample_data,sizeof(sample_data));
    if(err_code == NRF_SUCCESS)
    {
    NRF_LOG_INFO("SUCCESS 999");
    //flag_led = 1;
    return true;
    }
    else
    {
    NRF_LOG_INFO("FAILED");
    return false;
    }

    }

    I don't understand why I am not receiving anything on SAMD20.I am really stuck here badly and not understanding how to proceed.

    Thanks & Regards,

    Snehal.

  • Please get a logic analyzer so you can observe the data. 

    Kenneth

Related