Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

TWI reading and writing basics

Hello all, 

I have pinged the sensor on the "twi bus" successfully, now I am following the post on the read/write function that is needed to actually read the data off the sensor. This is what I am reading at the moment:  https://medium.com/vicara-hardware-university/setting-up-twi-on-nrf52xx-dcaf83a50baa

Indeed, I have the sensor's library , however, I am not really sure how to apply the following example and use the library.


/*
 * dev_addr -> Device address
 * reg_adddr -> Register address
 * data -> Buffer which holds data to be written
 * length -> Length of data to be written
 */
int8_t twi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t length)
{
    uint32_t err_code;

    uint8_t buffer[255] = {0};
    buffer[0] = reg_addr;
    memcpy(&buffer[1], data, length);
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, dev_addr, buffer, sizeof(length), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

   return err_code;
}

/*
 * dev_addr -> Device address
 * reg_adddr -> Register address
 * data -> Buffer where data read from TWI will be stored
 * length -> Length of data to be read
 */
int8_t twi_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t length)
{
    uint32_t err_code;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, dev_addr, &reg_addr, sizeof(reg_addr), true);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    m_xfer_done = false;
    err_code = nrf_drv_twi_rx(&m_twi, dev_addr, data, length);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    return err_code;

}

and obtain the data from the sensors registers.

BTW the library uses the i2c for the STM32 like this:

//STM32F specific I2C API call
#ifdef STM32F
	//All of the I2C API functions (For Example: HAL_I2C_Master_Transmit()) are being called from stm32f4xx_hal.h

	//hi2c1 - The variable to the I2C handler which is needed later in the Write and Read I2C function.
	//hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef hi2c1;.
	extern I2C_HandleTypeDef hi2c1;

	//Master sends I2C write command via pointer *Data from the Sensor API.
	//The function returns HAL_OK (=0) when there is no error and -1 when there is an error.
	int WriteI2C_Bus(struct TransferData *Data)
	{
		//Initialization of intial Error = 0
		int Error = 0;

		//Define an array of 3 Bytes to be sent as I2C Write Command as shown in Fig. 10 in the Datasheet Page 7
		uint8_t WData[3]={Data->RegisterAddress, Data->WData[0], Data->WData[1]};

		//Send I2C Write Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
		/*Format defined by STM:
		*HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout).
		*HAL_I2C_Master_Transmit() is used for transmitting data to the I2C device. It takes following arguments:
		*
		*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler. hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef *hi2c1;.
		*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
		*uint8_t *pData  - is the pointer to the data to be transmitted.
		*uint16_t Size  - is the size of the transmitted data in bytes.
		*uint32_t Timeout - timeout in millisecond in case of any error.
		*Return Error.
		*/
		Error = HAL_I2C_Master_Transmit(&hi2c1, (Data->Slave_Address)<<1, WData, 3, 100);

		//Return -1 when there is error and return HAL_OK (= 0) when no error
		if (Error != HAL_OK)
		{
			return -1;
		}
		else
		{
			return HAL_OK;
		}
	}

	//Master sends I2C Read command and save the read data via pointer *Data.
	//The function returns HAL_OK (=0) when no error and -1 when there is error.
	int ReadI2C_Bus (struct TransferData *Data)
	{
		//Initialization of intial Error = 0
		int Error = 0;

		//Send I2C Read Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
		/*Format defined by STM:
		*HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c1, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout).
		*HAL_I2C_Mem_Read () is used for reading data from the I2C device. It has been used instead of HAL_I2C_Master_Receive() because it sends restart condition
		*while the latter which sends stop condition and thus not working. It takes following arguments:
		*
		*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler.
		*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
		*uint16_t MemAddress - is the Internal memory address in the slave which is the register address.
		*uint16_t MemAddSize - the size of memory address (in Byte) which is the size of register address (In the case of Vishay's Sensor always 1 Byte).
		*uint8_t *pData  - is the pointer to the data to be received.
		*uint16_t Size  - is the size of the received data in bytes.
		*uint32_t Timeout - timeout in millisecond in case of any error.
		*Return Error.
		*
		*/
		Error = HAL_I2C_Mem_Read(&hi2c1, (Data->Slave_Address)<<1, Data->RegisterAddress, 1,Data->RData,2,100);

		//Return -1 when there is error and return HAL_OK (= 0) when no error
		if (Error !=HAL_OK)
		{
			return -1;
		}
		else
		{
			return HAL_OK;
		}
	}

	//Master sends I2C Gesture Read command and save the read data via pointer *Data.
	//The function returns HAL_OK (=0) when no error and -1 when there is error.
    int ReadI2C_Bus_Gesture_Mode(struct GestureTransferData *Data)
	{
		//Initialization of intial Error = 0
		int Error = 0;

		//Send I2C Gesture Read Command as shown in the Application Note Page 19 with Error checking.
		/*Format defined by STM:
		*HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout).
		*HAL_I2C_Master_Receive () is used for reading data from the I2C device. It has been used instead of HAL_I2C_Mem_Read() because no restart condition is *needed.
		*It takes following arguments:
		*
		*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler. hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef *hi2c1;.
		*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
		*uint8_t *pData  - is the pointer to the data to be received.
		*uint16_t Size  - is the size of the received data in bytes (For Gesture Stream 6 Bytes are needed).
		*uint32_t Timeout - timeout in millisecond in case of any error.
		*Return Error.
		*
		*/
		Error = HAL_I2C_Master_Receive(&hi2c1,(Data->Slave_Address)<<1,Data->RData,6,100);

		//Return -1 when there is error and return HAL_OK (= 0) when no error
		if (Error != HAL_OK)
		{
			return -1;
		}
		else
		{
			return HAL_OK;
		}
	}
#endif

So, I need to port the nrf twi and its sdk, right ? to eventually use the library with the nrf52dk?

In addition, I would like to use the pooling rather than interrupt. I guess as well this is done in the main() but within the while(true) loop?

Any ideas, example how to do, approach this?

Best.

PS yeah , I am new to this, just realized that I should write the code to read off the sensor in the while (true) loop :) where I am now printing text , juhej! 

Parents
  • Hi and thank you for your input, it really helps. Indeed, this example should be a good start and I will have a go, however, can this example as well be use to use the library , how, or is this just to use for predefined registers? Such as these: 

    #define LM75B_REG_TEMP 0x00U
    #define LM75B_REG_CONF 0x01U
    #define LM75B_REG_THYST 0x02U
    #define LM75B_REG_TOS 0x03U

    For example, the library defines all the registers including the values and methods, etc. So, it is of importance to use the library... However, you mentioned I can use the "twi_write and twi_read function" as posted above , can you be more specific, maybe an example of how to actually do this Slight smile

    Thank you in advance.

    PS while cloning the "project" I got an error when compiling, namely "C:/components/libraries/log/src/nrf_log_backend_rtt.c does not exist." do I have to clone it together with the whole directory path?

  • Hi Ahmed

    thank your for your input, of course, here is the datasheet vcnl4035x01.pdf (vishay.com) and I have the sensor on this address #define VCNL4035_ADDR 0x60 I have as well attached the init that I am using :

    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_vcnl4035_config = {
           .scl                = 27,
           .sda                = 26,
           .frequency          = NRF_DRV_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_vcnl4035_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }

    Here is the TWI handler , I guess this is the call back function ?

    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                    data_handler(m_sample);
                }
                m_xfer_done = true;
                break;
            default:
                break;
        }
    }

    Anyway, here is the library to make things easier VCNL4035X01 Fully Integrated Proximity and Ambient Light Sensor With I²C Interface and Interrupt Function for Gesture Applications | Vishay I have downloaded the code, trying to use it!

Reply
  • Hi Ahmed

    thank your for your input, of course, here is the datasheet vcnl4035x01.pdf (vishay.com) and I have the sensor on this address #define VCNL4035_ADDR 0x60 I have as well attached the init that I am using :

    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_vcnl4035_config = {
           .scl                = 27,
           .sda                = 26,
           .frequency          = NRF_DRV_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_vcnl4035_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }

    Here is the TWI handler , I guess this is the call back function ?

    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
                {
                    data_handler(m_sample);
                }
                m_xfer_done = true;
                break;
            default:
                break;
        }
    }

    Anyway, here is the library to make things easier VCNL4035X01 Fully Integrated Proximity and Ambient Light Sensor With I²C Interface and Interrupt Function for Gesture Applications | Vishay I have downloaded the code, trying to use it!

Children
No Data
Related