Skip to main content
Visitor II
June 11, 2020
Question

STM8S00F3 to read/write I2C device

  • June 11, 2020
  • 5 replies
  • 3637 views

1. I have to read/write NAU7802 register, datasheet of which is attched.

2. STM8S is running at 16Mhz.

3. Write three functions:

a) i2c_init() : init the i2c peripheral

b) i2c_read_one_byte_data() : read from address of NAU7802 and read only one byte

c) i2c_write_data() : write buffer to NAU7802 to register specified

4. I am trying to read the registers of NAU7802 which return constant values, by i always gets error. What could be wrong in code?

#define I2C_TIMEOUT 10000 //this is not exact timing, just a counter
 
#define I2C_SPEED 100000
#define I2C_SLAVE_ADDRESS7 0x2A //this is random not to be used actually, STM8S used in master mode
#define NAU7802_ADD 0x54 //this is address of NAU7802, 8 bit address, last bit will be R/W
 
 
 
void i2c_init(void)
{
/* I2C Peripheral Disable */
 I2C_Cmd(DISABLE); 
 
/* I2C DeInit */ 
 I2C_DeInit();
 
/* I2C Peripheral clock disable */
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C , DISABLE); 
 
/* GPIO INIT */ 
 GPIO_Init(GPIOB , GPIO_PIN_4 , GPIO_MODE_IN_PU_NO_IT); 
 GPIO_Init(GPIOB , GPIO_PIN_5 , GPIO_MODE_IN_PU_NO_IT);
 
/* enable clock */ 
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C , ENABLE);
 
/* I2C configuration */
 I2C_Cmd( ENABLE);
 
/* sEE_I2C configuration after enabling it */
 I2C_Init(I2C_SPEED, I2C_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2, I2C_ACK_CURR,I2C_ADDMODE_7BIT, 16);
 
}
 
 
 
uint8_t i2c_read_one_byte_data(uint8_t *p_buffer , uint8_t read_addr)
{
 uint16_t timeout;
 uint8_t err = 0U;
 uint8_t break_loop;
 
 
/* While the bus is busy */
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 while( (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 1U;
 }
 }
 
 if(0U == err)
 {
 /* Send START condition */
 I2C_GenerateSTART( ENABLE); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV5 and clear it */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 2U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send NAU7802 address for write */
 I2C_Send7bitAddress(NAU7802_ADD , I2C_DIRECTION_TX); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV6 and clear it */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 3U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send reg address for write */
 I2C_SendData( read_addr ); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV8 and clear it */
 while( (I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 4U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send START condition a second time */ 
 I2C_GenerateSTART( ENABLE);
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 5U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send register address for read */
 I2C_Send7bitAddress(NAU7802_ADD, I2C_DIRECTION_RX);
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
 while( (I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 6U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Disable Acknowledgement */
 I2C_AcknowledgeConfig(I2C_ACK_NONE); 
 
 /* Call User callback for critical section start (should typically disable interrupts) */
 disableInterrupts(); 
 
 /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
 (void)I2C->SR3;
 
 /* Send STOP Condition */
 I2C_GenerateSTOP( ENABLE);
 
 /* Call User callback for critical section end (should typically re-enable interrupts) */
 enableInterrupts();
 
 
 /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 while( (I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 7U;
 }
 } 
 } 
 
 
 if(0U == err)
 {
 /* Read the byte received from the EEPROM */
 *p_buffer = I2C_ReceiveData(); 
 
 /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 while( (I2C->CR2 & I2C_CR2_STOP) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 8U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Re-Enable Acknowledgement to be ready for another reception */
 I2C_AcknowledgeConfig( I2C_ACK_CURR); 
 
 } 
 
 
/* if some error make sure to send stop */ 
 if(0U != err)
 {
 /* Send STOP Condition */
 I2C_GenerateSTOP( ENABLE); 
 } 
 
 
/* Perform a read on SR1 and SR3 register to clear eventually pending flags */
 (void)I2C->SR1;
 (void)I2C->SR3; 
 
 
 return err;
 
}
 
 
 
uint8_t i2c_write_data(uint8_t *p_buffer , uint8_t write_addr , uint8_t num_byte_to_write)
{ 
 uint16_t timeout;
 uint8_t err = 0U;
 uint8_t break_loop;
 
/* While the bus is busy */
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 while( (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 1U;
 }
 }
 
 
 if(0U == err)
 {
 /* Send START condition */
 I2C_GenerateSTART( ENABLE); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV5 and clear it */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 2U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send NAU7802 address for write */
 I2C_Send7bitAddress(NAU7802_ADD , I2C_DIRECTION_TX); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV6 and clear it */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 3U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 /* Send reg address for write */
 I2C_SendData( write_addr ); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV8 and clear it */
 while( (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err = 4U;
 }
 } 
 
 } 
 
 
 if(0U == err)
 {
 while(num_byte_to_write)
 { 
 /* Send data */
 I2C_SendData( *p_buffer ); 
 
 
 timeout = I2C_TIMEOUT;
 break_loop = 0U;
 
 /* Test on EV8 and clear it */
 /* Wait till all data have been physically transferred on the bus */
 while( (!I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED)) && (0U == break_loop) )
 {
 timeout--;
 if(!timeout)
 {
 break_loop = 1U;
 err++;
 }
 } 
 
 num_byte_to_write--;
 p_buffer++;
 }
 
 } 
 
/* Send STOP condition */
 I2C_GenerateSTOP(ENABLE);
 
/* Perform a read on SR1 and SR3 register to clear eventually pending flags */
 (void)I2C->SR1;
 (void)I2C->SR3;
 
 return err;
 
} /* function ends here */ 

    This topic has been closed for replies.

    5 replies

    Visitor II
    June 11, 2020

    MCU is STM8S003F3

    Here is code, with error handling removed, for better understanding:

    #define I2C_TIMEOUT 10000 //this is not exact timing, just a counter
     
    #define I2C_SPEED 100000
    #define I2C_SLAVE_ADDRESS7 0x54 //this is random not to be used actually, STM8S used in master mode
    #define NAU7802_ADD 0x54 //this is address of NAU7802, 8 bit address, last bit will be R/W
     
     
    void i2c_init(void)
    {
    /* I2C Peripheral Disable */
     I2C_Cmd(DISABLE); 
     
    /* I2C DeInit */ 
     I2C_DeInit();
     
    /* I2C Peripheral clock disable */
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C , DISABLE); 
     
    /* GPIO INIT */ 
     GPIO_Init(GPIOB , GPIO_PIN_4 , GPIO_MODE_IN_PU_NO_IT); 
     GPIO_Init(GPIOB , GPIO_PIN_5 , GPIO_MODE_IN_PU_NO_IT);
     
    /* enable clock */ 
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C , ENABLE);
     
    /* I2C configuration */
     I2C_Cmd( ENABLE);
     
    /* sEE_I2C configuration after enabling it */
     I2C_Init(I2C_SPEED, I2C_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2, I2C_ACK_CURR,I2C_ADDMODE_7BIT, 16);
     
    }
     
     
     
    uint8_t i2c_read_one_byte_data(uint8_t *p_buffer , uint8_t read_addr)
    {
    /* While the bus is busy */
     while( I2C_GetFlagStatus(I2C_FLAG_BUSBUSY) );
     
     
    /* Send START condition */
     I2C_GenerateSTART( ENABLE); 
    /* Test on EV5 and clear it */ 
     while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT);
     
    /* Send NAU7802 address for write */
     I2C_Send7bitAddress(NAU7802_ADD , I2C_DIRECTION_TX);
    /* Test on EV6 and clear it */
     while( !I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) ) 
     
     
    /* Send reg address for write */
     I2C_SendData( read_addr ); 
    /* Test on EV8 and clear it */
     while(I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET);
     
     
    /* Send START condition a second time */ 
     I2C_GenerateSTART( ENABLE);
    /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
     while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
     
     
    /* Send register address for read */
     I2C_Send7bitAddress(NAU7802_ADD, I2C_DIRECTION_RX);
    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
     while(I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET);
     
     
    /* Disable Acknowledgement */
     I2C_AcknowledgeConfig(I2C_ACK_NONE); 
    /* should typically disable interrupts) */
     disableInterrupts(); 
    /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
     (void)I2C->SR3; 
    /* Send STOP Condition */
     I2C_GenerateSTOP( ENABLE); 
    /* should typically re-enable interrupts) */
     enableInterrupts(); 
    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */ 
     while(I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET); 
     
     
    /* Read the byte received from the EEPROM */
     *p_buffer = I2C_ReceiveData(); 
     while( (I2C->CR2 & I2C_CR2_STOP) ); 
    /* Re-Enable Acknowledgement to be ready for another reception */
     I2C_AcknowledgeConfig( I2C_ACK_CURR); 
     
     
    /* if some error make sure to send stop */ 
     if(0U != err)
     {
     /* Send STOP Condition */
     I2C_GenerateSTOP( ENABLE); 
     } 
     
     
    /* Perform a read on SR1 and SR3 register to clear eventually pending flags */
     (void)I2C->SR1;
     (void)I2C->SR3; 
     
     
     return err;
     
    }
     
     
     
    uint8_t i2c_write_data(uint8_t *p_buffer , uint8_t write_addr , uint8_t num_byte_to_write)
    { 
    /* While the bus is busy */
     while( (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
     
     
    /* Send START condition */
     I2C_GenerateSTART( ENABLE); 
     while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
     
     
    /* Send NAU7802 address for write */
     I2C_Send7bitAddress(NAU7802_ADD , I2C_DIRECTION_TX); 
     while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 
     
     
    /* Send reg address for write */
     I2C_SendData( write_addr ); 
    /* Test on EV8 and clear it */
     while( (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); 
     
     
     while(num_byte_to_write)
     { 
     /* Send data */
     I2C_SendData( *p_buffer ); 
     
     /* Wait till all data have been physically transferred on the bus */
     while( (!I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED));
     
     num_byte_to_write--;
     p_buffer++;
     }
     
     
     
    /* Send STOP condition */
     I2C_GenerateSTOP(ENABLE);
     
    /* Perform a read on SR1 and SR3 register to clear eventually pending flags */
     (void)I2C->SR1;
     (void)I2C->SR3;
     
     return err;
     
    } /* function ends here */ 

    Visitor II
    June 12, 2020

    moveup..

    Visitor II
    June 14, 2020

    moveup..

    Visitor II
    July 13, 2020

    +1, any updates on this? I would like to use an AZ3166 dev board with the OpenScale project, however support with the ST processor is a blocking item.

    Link to Dev Board: https://en.mxchip.com/az3166

    Link to project depending on NAU7802: https://github.com/sparkfun/SparkFun_Qwiic_Scale_NAU7802_Arduino_Library

    Visitor II
    July 14, 2020

    I think no one in ST cares about its user, having issues and help them resolve it.

    This forum is opened just to show that they have a forum in place like other MCU companies, but no one in ST even remotely looks at it.

    But harsh here, but somehow doesnt seem to work this way.