2017-07-27 03:47 AM
Hallo,
I am trying to Read GPS data from a uBlox LEA via I2C with a STM32L073RZ (Nucleo Board). I am able to read EEPROMs with the HAL Libraries in Blocking and Interrupt Mode. The EEPROM i am using is a 24LC64 and it is not critical to I2C Specifications so I can read it using a HAL_transmit to tell the Adress I want to read and then use a HAL_read to read the number of Bytes. Unfortunately the HAL functions automatically generates a STOP condition after using it! My problem is, that the GPS chip I want to read strictly follows the I2C specifications and does Expect a RESTART/START condition in between the Transmit – Read actions and does not accept a STOP.
Here I come the Combined Transactions from HAL Lib into the game. With these functions I was able to solve the I2C combined transaction Problem using the Transfer Options provided.
HAL_I2C_Master_Sequential_Transmit_IT
(hi2c, DevAddress, addr, 1, I2C_FIRST_FRAME);
HAL_I2C_Master_Sequential_Receive_IT
(hi2c, DevAddress, pData, len, I2C_LAST_FRAME);
Using my Logic Analyzer, I can See the I2C connection working and transfer Data correctly. The Data decrypted via the logic analyzer makes sense. All Adresses and read / write transactions are correct on the logic analyzer. My Problem is, that the HAL_I2C_Master_Sequential_Reveive_IT function doesn’t write Data in via the Pointer pData back in Buffer! So I can see everything works, but I don’t get the data back ? Did I just encounter a Library Bug? Do I use the function correctly?
Function:
HAL_StatusTypeDef I2C_uBlox_Read_SQ(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t len) {
HAL_StatusTypeDef returnValue; uint8_t addr[2];addr[1] = (uint8_t) ((MemAddress & 0xFF00) >> 8);
addr[0] = (uint8_t) (MemAddress & 0xFF);returnValue = HAL_I2C_Master_Sequential_Transmit_IT(hi2c, DevAddress, addr, 1, I2C_FIRST_FRAME);
if(returnValue != HAL_OK) return returnValue; HAL_Delay(1); returnValue = HAL_I2C_Master_Sequential_Receive_IT(hi2c, DevAddress, pData, len, I2C_LAST_FRAME); return returnValue;}Function Call:
#define BUFFER_SIZE 500
uint8_t bufferI2C_uint8[BUFFER_SIZE];
I2C_uBlox_Read_SQ(&hi2c1, UBLOX_I2C_SHIFTED_ADRESS, 0xFD , bufferI2C_uint8, (2) );
I2C_uBlox_Read_SQ(&hi2c1, UBLOX_I2C_SHIFTED_ADRESS, 0xFF , bufferI2C_uint8, (200 ) );
2017-07-27 06:32 AM
Hello!!
You use the non blocking version of theese transaction functions. (HAL_I2C_Master_Sequential_Receive_IT)
Normaly you must check the callback function after transaction completion. You introduce an 1 ms delay
between the transactions . Is it enough?
You define also' addr' at two bytes array but transmit one byte . is it your intention?
You try to get 200 bytes from GPS Is it capable to transmit 200 bytes? (and finaly finish your transaction? )
Did you tried HAL_I2C_Mem_Read_IT? for Random Read Access.? UBlox support it.
2017-07-27 07:24 AM
Hi,
1. is it really a MUST to check or even implement callback functions? Usually it would be to clear at least a Interrupt Flag... I just changed from PIC32, so not experienced on STM32. My callbacks look like:
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c){
__NOP();//test if we reach this position}void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c){
__NOP();//test if we reach this position}2. 1ms delay is just a wild guess. It works fine regarding to my Logic Analyzer output. Actually i wanted to use the
HAL_I2C_IsDeviceReady function instead/later.
3. well, the two byte array is a relict from the EEPROM Code which needed 16 bits adresses, its not really necessary here, but does the job
4. Yes, the GPS is able to be read with even more bytes. I can read exactly this GPS with I2C using the online mbed comiler generated code. 200 bytes here are only for Test purpose, usually i would first get the number of bytes stored in the gps at a certain adress, then i would read that number ob bytes at another adress
5. I did not try HAL_I2C_Mem_Read_IT . I will, but i wanted to code this manually, which i always did on other plattforms and microcontrollers
2017-07-27 09:57 AM
Hi!
1. It is not a must ofcourse.. In such a case it's better to use the blocking functions (not to have the delay issue)
2. One millisecond (calculated ofcourse) is not enough in my opinion. I had a lot of pitfalls because of a single one ms.! (when i calculate 1 , i put 3 at least(when timing is not critical)
check if HAL_I2C_MasterRxCpltCallback is called ( finished transaction) or return an error HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) and what error is it. .
2017-08-17 12:57 AM
Hi,
So I2C with uBlox works now. I solved the communication problem by using the HAL Memory I2C functions. I am pretty sure that HAL I2C Sequential is not correct implemented for L0 prozessors, which also Carmine Noviello in his book Mastering STM32 in the I2C chapter on page 486 describes.