2020-06-11 04: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 07: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 07:46 AM
moveup..
2020-06-14 06:22 AM
moveup..
2020-07-13 04: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 09: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.