2018-01-19 12:59 PM
Hi All,
First post on here and a newbie with the STM32 family of devices (I come from a PIC background - sorry about that)
I have just received my first STM32 board design back from the sub contractors and am having a little trouble and am hoping someone can point me in the right direction.
First of all, I'm using keil as the IDE/Compiler. I have configured the micro using CUBE and am using the HAL libraries.
My issue is that I cannot get I2C_MEM_WRITE or READ to work.
On the first use of > if(HAL_I2C_IsDeviceReady(&hi2c1, I2C_ROM, 1, 100) == HAL_OK)
I get an OK. When I try a mem_write it fails (that is HAL_OK returns 0).
I have check my soldering and even shortened the i2c bus by truncating it immediately after the cat24c512 with a craft knife (and adding 2x10k resistors to vcc), but still no luck.
The device address (I2C_ROM) is defined as 0xA0. I have tried playing with the timeout also.
I notice that in CUBE things like rise and fall time can be set - not idea what to set these to (didn't have to worry about that in the world of PIC).
Any pointers would be most appreciated.
Here is the code:-
uint8_t WriteConfigToI2C(void)
{ char buffer[5] = 'TEST'; uint8_t i; if(HAL_I2C_IsDeviceReady(&hi2c1, I2C_ROM, 1, 100) == HAL_OK) //i2c address of eeprom = 0b1010000 = 0xa0 {HAL_UART_Transmit(&hlpuart1, (uint8_t*)'\r\nWrite', 7, 1000); //(uint8_t*)'\r\nready'
HAL_Delay(100); if(HAL_I2C_Mem_Write(&hi2c1, I2C_ROM, 0x00, 0xFFFF, (uint8_t*)buffer, strlen(buffer), 100) == HAL_OK) // write 'buffer' to I2C mem { HAL_UART_Transmit(&hlpuart1, (uint8_t*)': OK', 4, 1000); // send 'OK' to uart if success HAL_Delay(100); // wait for eeprom to commit / finish // clear buffer for(i = 0; i < 50; i++) { buffer[i] = 0; } // read the memory and write it back out on uart HAL_I2C_Mem_Read(&hi2c1, I2C_ROM, 0x00, 0xFFFF, (uint8_t*)buffer, 5, 100); // read back eeprom and put into 'i2cBuffer' HAL_UART_Transmit(&hlpuart1, (uint8_t*)buffer, strlen(buffer), 1000); // write 'i2cBuffer' to uart } else { HAL_UART_Transmit(&hlpuart1, (uint8_t*)': FAIL', 6, 1000); // failed to write } } else { HAL_UART_Transmit(&hlpuart1, (uint8_t*)'\r\nNotReady', 10, 1000); } }2018-01-20 03:48 PM
a newbie with the STM32 ... I have just received my first STM32 board design back from the sub contractors
So have you first prototyped this on a Discovery or Nucleo or other Dev Board?
That should give you a working reference point ...
Have you scoped the pins to see what - if anything - is actually happening on the wires?
2018-01-21 07:10 PM
this works for me,
after the cube is setup, I use blocking mode to send the frame.
the last line sends the data in blocking mode.
#define MCP4728_DacAddress 0x60 << 1
struct DacIIC {
uint8_t DacTxBuffer[4];
uint8_t DacRxBuffer[16];
};
struct DacIIC MCP4728IIC;
HAL_StatusTypeDef IIC_Response;
char channel;
char use2xGain = false;
char powerDownMode = false;
char UseInternalVRef = false;
int Dac_Value;
channel = 0;
Dac0_Value = (4096 * 1) / 5; // 1V
MCP4728IIC.DacTxBuffer[0] = 0x40 | ((channel & 0x3) << 1);
MCP4728IIC.DacTxBuffer[1] = ((uint8_t)UseInternalVRef << 7) | ((powerDownMode & 0x3) << 5) | ((uint8_t)use2xGain << 4);
MCP4728IIC.DacTxBuffer[1] |= (Dac0_Value & 0x0f00)>>8;
MCP4728IIC.DacTxBuffer[2] = Dac0_Value & 0xff;
//DAC_IIC.write(DAC_ADDR + (Dac_Address << 1), buf, 3, 0) == 0; //mbed
IIC_Response = HAL_I2C_Master_Transmit(&hi2c1, MCP4728_DacAddress, &MCP4728IIC.DacTxBuffer[0], 3, 10);�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-01-25 02:38 AM
Hi Andrew,
Thank you for your response. Yes. I hooked SDA/SCL up to a scope and checked out the signals. The rise looked a bit woolly, so I reduced the pull-ups to 1K.
Above shows the trace when running the IsDeviceReady() on 0xA0 (the CAT24C512).
However, if I try to write to the device afterwards, It still fails to write. Then the mem device appears to lock up - that is I get a not ready response if I try another IsDeviceReady().
Not quite sure where to go with this at the moment. I have an I2C bus analyser on the way, maybe that will shed more light - but I've never had to use one in the 10years of my using I2C on other controllers.
thanks,
Peter
2018-01-25 04:25 AM
Can't your scope give you a screenshot directly?
Peter Curtis wrote:
Not quite sure where to go with this at the moment.
Verify that scope waveform against the I2C spec.
Again, have you tried it on a known-good board (Nucleo, Disco, etc) with a known-good example for that board?
2018-01-25 01:42 PM
'it fails to write'
can you read data and status from the flash CAT24C512 ?
I suggest that you stop using : HAL_I2C_IsDeviceReady
and use something like my suggestion above :
HAL_I2C_Master_Transmit(&hi2c1, MCP4728_DacAddress, &MCP4728IIC.DacTxBuffer[0], 3, 10);
HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
2018-01-26 08:27 AM
Hi TJ,
Thank you for your reply - but it doesn't look possible to use this function with a memory device as I need to set the internal address to write to, before writing data.
Many thanks,
Peter
2018-01-26 08:37 AM
Hi Andrew,
My scope was purchased sometime ago and the application that came with it does not work with windows 10 unfortunately. However, I have just received my smartscope and have captured the following:-
Comparing against the i2c spec, the start condition is correct as are the 'ack's. The slave address and the internal address to write to (0x00FF) are also correct.
The interesting thing to note from the trace above is that everything seems to be going swimmingly until its time to write the data - then the clock stops (SCL stays low).
I do, in the depth of my bits box somewhere, have a disco476, so will dig it out over the weekend. I don't believe it has an I2C memory device on it though.
Kind regards,
Peter
2018-01-26 06:54 PM