2017-04-09 11:07 PM
Hi , I'm trying to make a inple I2C bus scanner ( re-writing simple arduino I2C scanner code )
I am not sure how to return the error if there a device address exits?
1st, am i trying to re-invent the wheel and there is already a working I2C bus code out there for ST32Fx ?
Sorry if my questions are a bit basic , i'm new to ST32
Here is my 1st attemps , I'm not even sure if the i2c bus definition I2C1 is correct.
The I2C bus should be initialised since I'm using the audio recorder playback application code from CubeMX that works with the codec IC. I'm just adding this code as a function in that example executing the function I2CSCANNER(); from the while loop.
void I2CSCANNER(void)
{
unsigned char error, address; int nDevices;nDevices = 0;
BSP_LCD_SetTextColor(LCD_COLOR_GREEN);
BSP_LCD_SetFont(&LCD_LOG_HEADER_FONT);BSP_LCD_DisplayStringAtLine(15, (uint8_t *)'Scanning...');
// do i need HAL_I2C_Master_Abort_IT(I2C1, devaddress); to make the write happen?
// how do I know if a device did acknowledge the address when I write to it ?
for(address = 01; address < 127; address++ ) { // print current device being scanned on screen sprintf(buffera, '0x%02x', address); BSP_LCD_ClearStringLine(20); BSP_LCD_DisplayStringAtLine(20, (uint8_t *)' .....device being scanned..'); BSP_LCD_DisplayStringAtLine(20, (uint8_t *) buffera); HAL_Delay(10);
BSP_LCD_Clear(LCD_COLOR_BLACK); // clear screen
uint16_t devaddress = address; // cast to uint16_t
uint32_t timeout = 10; uint16_t i2cpacketsize = 1; uint8_t rdata = 0; nulldata[0] = 0;error = HAL_I2C_Master_Transmit (I2C1, devaddress, nulldata, i2cpacketsize, timeout);
// can I used any of these ???????????
// HAL_I2C_Master_Receive(I2C1, devaddress, rdata, 1, timeout); // could i use this?
// error = Wire.endTransmission(); // original arduino scanner code // error = HAL_I2C_Master_Abort_IT(I2C1, devaddress); // does this return anything ?HAL_Delay(10);
if (error == 0)
{BSP_LCD_DisplayStringAtLine(16, (uint8_t *)'I2C device found at address 0x');
if (address<16)
BSP_LCD_DisplayStringAtLine(17, (uint8_t *)'0');
sprintf(buffera, '0x%02x', address) ;
BSP_LCD_DisplayStringAtLine(17, (uint8_t *) buffera) ; // make this hex code !!!!!!!!!!!!! BSP_LCD_DisplayStringAtLine(17, (uint8_t *)' !');nDevices++;
} else if (error==4) { BSP_LCD_DisplayStringAtLine(17, (uint8_t *)'Unknown error at address 0x');if (address<16)
BSP_LCD_DisplayStringAtLine(17, (uint8_t *)'0');sprintf(buffera, '0x%02x', address) ; // put the hex number in buffera string as a hex number
BSP_LCD_DisplayStringAtLine(17, (uint8_t *) buffera); // print the hex number being scanned } } if (nDevices == 0)BSP_LCD_DisplayStringAtLine(17, (uint8_t *)'No I2C devices found\n');
else BSP_LCD_DisplayStringAtLine(17, (uint8_t *)'done\n');HAL_Delay(1000); // wait for next scan
}
#i2c #bus #scanner #read #error2017-04-10 02:27 AM
Is the I2C bus having a connector, or slaves can be plugged/unplugged onto the bus?
2017-04-10 02:36 AM
Yer , there would be slaves on the Bus. Pins 88 & 89 I think SDA SCL. but i think if I scan the bus with correct code then the Codec IC should show up on the STM32F769Idiscovery board also ? but not sure what would return an ACK or error in my code to determin if there is something on the bus at a given address ( 0x00 to 0x7F hex ) or 0 - 127 in dec.
2017-04-10 03:00 AM
I have seen that on my scope from other scanners NACK=1 8th bit. So how would I read the NACK in my code ? just the NACK=0 for yes there is a device at given address would do. Did'nt know there were actual hardware I2C busses on ST32F7 as well as ones implimented in GPIO. Does HAL_I2C_Master_Transmit() return NACK ? or I need to do a read ?
2017-04-10 04:32 AM
I beleieve if I can scan / sweep the correct bus i should be able to detect these devices also,
TS_I2C_ADDRESS 0x54
TouchScreen FT6336G Slave I2C address 2
TS_I2C_ADDRESS_A02 0x70)Audio I2C Slave address
AUDIO_I2C_ADDRESS 0x34EEPROM I2C Slave address 1
EEPROM_I2C_ADDRESS_A01 0xA0EEPROM I2C Slave address 2
EEPROM_I2C_ADDRESS_A02 0xA6
2017-04-10 04:44 AM
Sweeping the slave addresses should work fine (as long as the rare 10 bit slaves are excluded).
Usually, to detect a specific slave, the ack of the slave address is the first step. Next step is to read a register to get an ID (such as the WHO_AM_I register in ST MEMs).
For plug-unplug situation, starting with an I2C by GPIO might be easier, before moving to an optimized one using the HW I2C.
When trying an inexistant slave address, the pull up on the bus will 'NACK = 1' will be read.
2017-04-10 07:30 AM
https://community.st.com/0D50X00009XkW1mSAF
This gives a SW I2C example with simple GPIO.
The I2C slave address sweep will let you know if ACK (0) or NACK (1) on the slave address.
I2C uses 8 bits of data one way and one ACK/NACK the other way.
If noone forces low level, the pull-up resistor on the bus will force high level (NACK).
Beware that for some EEPROM, some of the LSB of the address bus are used as internal memory MSB address bits between 512 and 2kbyte ==> Multiple addresses acknowledged by the same device.
In the addresses mentionned, you scan A0, A2, A4, ..... (A1, A3, A5 for read)
For the HW I2C HAL, not a specialist to give the right answer.
2017-04-10 08:27 AM
Thanks for the link , i'll try and look through the HAL_I2C_Master_Transmit code and see if there is a way to read the ack/nack there. otherwise if not i'll try and your i2c gpio code.
Anyone know how to read the ACK bit from using stm32f7xx_hal_i2c.c ? the definition of HAL_I2C_Master_Transmit says it returns 'HAL status' and I get 0x02 returned on both I2C1 & I2C4 instances which i think means ACK1 ( nothing there ) ?