cancel
Showing results for 
Search instead for 
Did you mean: 

STM8S00F3 to read/write I2C device

vindhyachal
Associate II

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 */ 

5 REPLIES 5
vindhyachal
Associate II

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 */ 

vindhyachal
Associate II

moveup..

vindhyachal
Associate II

moveup..

PSo.1
Associate

+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

vindhyachal
Associate II

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.