[STM32][HAL][I2C] Problem z przerwaniami

Wszystko o co chcesz zapytać na temat mikrokontrolerów ARM firmy STMicroelectronics: problemy z pisaniem programu, problemy sprzętowe, niejasności w DS czy AN itp.
mikandrzej
Posty: 9
Rejestracja: piątek 23 lut 2018, 19:51

[STM32][HAL][I2C] Problem z przerwaniami

Postautor: mikandrzej » niedziela 07 paź 2018, 16:19

Panowie szanowni.

Borykam się z takim oto problemem.

Do magistrali I2C mogę podłączyć do czterech czujników temperatury ADT7420. Mają one dwa wejścia adresowe, stąd taka ilość. Jako, iż mają one być przyłaczane na "wtyczkę", to nie zawsze wszystkie cztery będą się na magistrali znajdowały. Do komunikacji z nimi używam biblioteki HAL, kod generuję w CubeMX. Sytuacja wygląda następująco:

Używam funkcji:

Kod: Zaznacz cały

HAL_I2C_Mem_Read_IT( );


Tak więc na początku odpytuję o temperaturę pierwszy czujnik. I teraz jeśli istnieje on na magistrali, to zwróci przerwanie
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) w którym to obrabiam otrzymane dane i znów używając komendy HAL_I2C_Mem_Read_IT( ) pytam kolejny czujnik o wartość rejestru.
Jeśli jednak czujnik nie istnieje na magistrali, otrzymuję przerwanie void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) i w nim również pytam kolejny czujnik o wartość rejestru z wynikiem pomiaru. Problem pojawia się w tym miejscu, gdyż kolejne przerwania z tej magistrali I2C, po wyrzuceniu przerwania ErrorCallback nie występują. Tak jakby trzeba było gdzieś znów zezwolić na przerwania, albo coś w ten deseń.

Czy jest mi w stanie ktoś pomóc?

Pozdrawiam,
mikandrzej

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: [STM32][HAL][I2C] Problem z przerwaniami

Postautor: Antystatyczny » niedziela 07 paź 2018, 16:24

W tej chwili zgaduję, ale może należy ręcznie skasować flagę "error"?
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

mikandrzej
Posty: 9
Rejestracja: piątek 23 lut 2018, 19:51

Re: [STM32][HAL][I2C] Problem z przerwaniami

Postautor: mikandrzej » niedziela 07 paź 2018, 20:01

Zaraz sprawdzę :)

Wysłane z mojego Redmi Note 4 przy użyciu Tapatalka

mikandrzej
Posty: 9
Rejestracja: piątek 23 lut 2018, 19:51

Re: [STM32][HAL][I2C] Problem z przerwaniami

Postautor: mikandrzej » niedziela 07 paź 2018, 21:57

Szczerze mówiąc to nie wiem...
Poniżej status rejestrów podczas poprawnej transmisji
Przechwytywanie.PNG


A teraz w momencie wystąpienia ErrorCalback:
Przechwytywanie2.PNG


W skrócie, jako porównanie:

Flaga ACK 1->0

Kod: Zaznacz cały

"Acknowledge enable
This bit is set and cleared by software and cleared by hardware when PE=0.
0: No acknowledge returned
1: Acknowledge returned after a byte is received (matched address or data)"


flaga Event Interrupt enable 0->1

Kod: Zaznacz cały

Bit 9
ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
– SB = 1 (Master)
– ADDR = 1 (Master/Slave)
– ADD10= 1 (Master)
– STOPF = 1 (Slave)
– BTF = 1 with no TxE or RxNE event
– TxE event to 1 if ITBUFEN = 1
– RxNE event to 1if ITBUFEN = 1


flaga Error interrupt enable 0->1

Kod: Zaznacz cały

Bit 8
ITERREN: Error interrupt enable
0: Error interrupt disabled
1: Error interrupt enabled
This interrupt is generated when:
–BERR = 1
–ARLO = 1
–AF = 1
–OVR = 1
– PECERR = 1
–TIMEOUT = 1
- SMBALERT = 1


flaga Bus Busy 0->1

Kod: Zaznacz cały

Bit 1
BUSY: Bus busy
0: No communication on the bus
1: Communication ongoing on the bus
– Set by hardware on detection of SDA or SCL low
– cleared by hardware on detection of a Stop condition.
It indicates a communication in progress on t
he bus. This information is still updated when
the interface is disabled (PE=0).


flaga MSL 0->1

Kod: Zaznacz cały

Bit 0
MSL: Master/slave
0: Slave Mode
1: Master Mode
– Set by hardware as soon as the
interface is in Master mode (SB=1).
– Cleared by hardware after detecting a Stop cond
ition on the bus or a loss of arbitration
(ARLO=1), or by hardware when PE=0.



Z powyższych nie potrafię wywnioskować jaką flagę skasować.
Gdyby ktoś chciałby pomóc to poniżej link do dokumentacj https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf strona 839

Pozdrawiam
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
ZbeeGin
User
User
Posty: 492
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: [STM32][HAL][I2C] Problem z przerwaniami

Postautor: ZbeeGin » poniedziałek 08 paź 2018, 13:27

mikandrzej pisze:Jeśli jednak czujnik nie istnieje na magistrali, otrzymuję przerwanie void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) i w nim również pytam kolejny czujnik o wartość rejestru z wynikiem pomiaru. Problem pojawia się w tym miejscu, gdyż kolejne przerwania z tej magistrali I2C, po wyrzuceniu przerwania ErrorCallback nie występują. Tak jakby trzeba było gdzieś znów zezwolić na przerwania, albo coś w ten deseń.


Nie ćwiczyłem tego, ale coś mi się wydaje, że źle to robisz już na etapie idei.

Piszesz, że czujniki są na wtykach i taki czujnik może nie być wpięty. Jeśli takie jest założenie projektowe, że jakiś czujnik może nie istnieć w jakieś tam wersji urządzenia, to raczej nie powinieneś się próbować z nim komunikować. Trzeba by przy starcie aplikacji dokonać "enumeracji" czujników, by wykryć, które są obecne a które nie. I później adresów tych nieobecnych po prostu nie odpytywać. Jak się nie mylę to jest do tego nawet specjalna funkcja HAL_I2C_IsDeviceReady().

Funkcja HAL_I2C_ErrorCallback() jest wywoływana jeśli transmisja się nie powiedzie. To jest informacja dla programu głównego, że coś jest nie tak. Z przykładów do bibliotek HAL wynika, że ten callback zostanie wywołany, ale Master będzie automatycznie dalej próbował transmisji. Stąd są tam np. wywoływania funkcji błędu, która sygnalizuje błąd - zapala diody - i wchodzi w nieskończoną pętlę.

Kod: Zaznacz cały

/**
  * @brief  I2C error callbacks.
  * @param  I2cHandle: I2C handle
  * @note   This example shows a simple way to report transfer error, and you can
  *         add your own implementation.
  * @retval None
  */
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
  /** Error_Handler() function is called when error occurs.
  * 1- When Slave don't acknowledge it's address, Master restarts communication.
  * 2- When Master don't acknowledge the last data transferred, Slave don't care in this example.
  */
  if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
  {
    Error_Handler();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn Off LED4 */
  BSP_LED_Off(LED4);

  /* Turn Off LED6 */
  BSP_LED_Off(LED6);

  /* Turn Off LED3 */
  BSP_LED_Off(LED3);

  /* Turn On LED5 */
  BSP_LED_On(LED5);
  while(1)
  {
  }
}


Wynika z tego, że powinieneś skorzystać z HAL_I2C_ErrorCallback() by w razie czego przerwać bieżącą transmisję, a nie wyzwalać kolejną na następnym adresie, która i tak się nie powiedzie, bo Master jest zajęty dalszymi próbami komunikacji.
Jest nawet funkcja HAL_I2C_Master_Abort_IT(), która moim zdaniem powinna przerwać bieżącą wymianę danych.

mikandrzej
Posty: 9
Rejestracja: piątek 23 lut 2018, 19:51

Re: [STM32][HAL][I2C] Problem z przerwaniami

Postautor: mikandrzej » poniedziałek 08 paź 2018, 19:52

ZbeeGin pisze:
mikandrzej pisze:Jeśli jednak czujnik nie istnieje na magistrali, otrzymuję przerwanie void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) i w nim również pytam kolejny czujnik o wartość rejestru z wynikiem pomiaru. Problem pojawia się w tym miejscu, gdyż kolejne przerwania z tej magistrali I2C, po wyrzuceniu przerwania ErrorCallback nie występują. Tak jakby trzeba było gdzieś znów zezwolić na przerwania, albo coś w ten deseń.


Nie ćwiczyłem tego, ale coś mi się wydaje, że źle to robisz już na etapie idei.

Piszesz, że czujniki są na wtykach i taki czujnik może nie być wpięty. Jeśli takie jest założenie projektowe, że jakiś czujnik może nie istnieć w jakieś tam wersji urządzenia, to raczej nie powinieneś się próbować z nim komunikować. Trzeba by przy starcie aplikacji dokonać "enumeracji" czujników, by wykryć, które są obecne a które nie. I później adresów tych nieobecnych po prostu nie odpytywać. Jak się nie mylę to jest do tego nawet specjalna funkcja HAL_I2C_IsDeviceReady().

Funkcja HAL_I2C_ErrorCallback() jest wywoływana jeśli transmisja się nie powiedzie. To jest informacja dla programu głównego, że coś jest nie tak. Z przykładów do bibliotek HAL wynika, że ten callback zostanie wywołany, ale Master będzie automatycznie dalej próbował transmisji. Stąd są tam np. wywoływania funkcji błędu, która sygnalizuje błąd - zapala diody - i wchodzi w nieskończoną pętlę.

Kod: Zaznacz cały

/**
  * @brief  I2C error callbacks.
  * @param  I2cHandle: I2C handle
  * @note   This example shows a simple way to report transfer error, and you can
  *         add your own implementation.
  * @retval None
  */
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
  /** Error_Handler() function is called when error occurs.
  * 1- When Slave don't acknowledge it's address, Master restarts communication.
  * 2- When Master don't acknowledge the last data transferred, Slave don't care in this example.
  */
  if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
  {
    Error_Handler();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn Off LED4 */
  BSP_LED_Off(LED4);

  /* Turn Off LED6 */
  BSP_LED_Off(LED6);

  /* Turn Off LED3 */
  BSP_LED_Off(LED3);

  /* Turn On LED5 */
  BSP_LED_On(LED5);
  while(1)
  {
  }
}


Wynika z tego, że powinieneś skorzystać z HAL_I2C_ErrorCallback() by w razie czego przerwać bieżącą transmisję, a nie wyzwalać kolejną na następnym adresie, która i tak się nie powiedzie, bo Master jest zajęty dalszymi próbami komunikacji.
Jest nawet funkcja HAL_I2C_Master_Abort_IT(), która moim zdaniem powinna przerwać bieżącą wymianę danych.


Dzięki!!!

Po pierwszych testach wygląda to bardzo obiecująco!

Generalnie układ dość skomplikowany, bo na jednej magistrali mam zamontowany "selektor magistrali" i po odpytaniu czterech adresów przełączam się na kolejne złącze i sprawdzam kolejne cztery. W sumie daje to 16 czujników na jednej magistralii. Na czterech wygląda na to, że działa poprawnie. Po pełnych testach dam znać co i jak.

Jeszcze raz dzięki :)


Wróć do „ARM STMicroelectronics”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 5 gości