2020-06-11 4:57 AM
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 */
2020-06-11 7:04 AM
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 */
2020-06-12 7:46 AM
moveup..
2020-06-14 6:22 AM
moveup..
2020-07-13 4:09 AM
+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
2020-07-13 9:11 PM
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.
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.