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.