Здравствуйте. Возникли трудности в написании программы (я новичок в этом деле). Надеюсь получить ответ именно здесь. Суть в следующем: Идет сообщение по интерфейсу I2C. Имеется 1 MASTER (М) и 2 SLAVEа (S1, S2). М делает запрос к S1 и S2 по порядку, получает ответ и в зависимости от их состояния совершает определенные действия. Загвоздка в том, что в момент отправки запроса мастером, слейв может отключиться (по некоторым обстоятельствам), т.е. мастер ждет ответа, но ответ не приходит, и он зависает. Вопрос в следующем: можно ли каким-то образом, перед тем как делать запрос к слэйву, включить таймер на время равное максимальному времени прохождения функции по опросу состояния S1, по истечении которого программа продолжалась с проверки S2 (в случае зависания). И остановить таймер при нормальной работе после выполнения мастером действия, соответствующего ответу опрошенного слэйва. имеется рабочая программа: #include <Wire.h> // ----------------НАЗНАЧЕНИЕ ВЫВОДОВ------------------------------- int led_fail_1=3; // красный светодиод стенда 1 int led_ok_1=8; // зеленый светодиод стенда 1 int led_fail_2=9; // красный светодиод стенда 2 int led_ok_2=10; // зеленый светодиод стенда 2 int st_1=4; // работает стенд 1 int st_2=5; // работает стенд 2 int TWI_adr_1=3; // адрес опрашиваемого устройства 1 int TWI_adr_2=3; // адрес опрашиваемого устройства 2 char now_status; void setup() { // -----------------НАСТРОЙКА ВЫВОДОВ----------------------------- pinMode(led_fail_1, OUTPUT); digitalWrite(led_fail_1, LOW); pinMode(led_ok_1, OUTPUT); digitalWrite(led_ok_1, LOW); pinMode(led_fail_2, OUTPUT); digitalWrite(led_fail_2, LOW); pinMode(led_ok_2, OUTPUT); digitalWrite(led_ok_2, LOW); pinMode(st_1, INPUT_PULLUP); pinMode(st_2, INPUT_PULLUP); Wire.begin(); // подключаемся по I2C к ведомому устройству Serial.begin(9600); // start serial for output } void loop() { // ----------------------ОПРОС ПЕРВОГО СТЕНДА--------------------------------------------- { if (digitalRead(st_1)==LOW) // если стенд 1 включен { Wire.requestFrom(3, 1); // request 1 bytes from slave device #3 while(Wire.available()) // slave may send less than requested { char now_status = Wire.read(); // receive a byte as character switch(now_status) { case 0: // если статус ОК digitalWrite(led_fail_1,LOW); // гасим красный светодиод digitalWrite(led_ok_1,HIGH); // зажигаем зеленый светодиод break; case 1: // если СДУ<< digitalWrite(led_ok_1,LOW); digitalWrite(led_fail_1,HIGH); delay(250); digitalWrite(led_fail_1,LOW); delay(250); // мигаем красным светодиодом break; case 2: // если СДУ>> digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод digitalWrite(led_fail_1,HIGH); delay(250); digitalWrite(led_fail_1,LOW); delay(250); // мигаем красным светодиодом break; case 3: // ошибка digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод digitalWrite(led_fail_1,HIGH); // зажигаем красный светодиод break; } } } else { digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод digitalWrite(led_fail_1,LOW); // гасим красный светодиод } } // ----------------------ОПРОС ВТОРОГО СТЕНДА--------------------------------------------- { if (digitalRead(st_2)==LOW) // если стенд 1 включен { Wire.requestFrom(3, 1); // request 1 bytes from slave device #3 while(Wire.available()) // slave may send less than requested { char now_status = Wire.read(); // receive a byte as character switch(now_status) { case 0: // если статус ОК digitalWrite(led_fail_2,LOW); // гасим красный светодиод digitalWrite(led_ok_2,HIGH); // зажигаем зеленый светодиод break; case 1: // если СДУ<< digitalWrite(led_ok_2,LOW); digitalWrite(led_fail_2,HIGH); delay(250); digitalWrite(led_fail_2,LOW); delay(250); // мигаем красным светодиодом break; case 2: // если СДУ>> digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод digitalWrite(led_fail_2,HIGH); delay(250); digitalWrite(led_fail_2,LOW); delay(250); // мигаем красным светодиодом break; case 3: // ошибка digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод digitalWrite(led_fail_2,HIGH); // зажигаем красный светодиод break; } } } else { digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод digitalWrite(led_fail_2,LOW); // гасим красный светодиод } } } Заранее спасибо.
Существует как минимум одна альтернативная библиотека, "лишенная" такой проблемы https://github.com/rambo/I2C https://github.com/DSSCircuits/I2C-Master-Library Но вот соберется ли она под современной IDE - не знаю. Как минимум можно использовать как образец, что бы вправить мозг текущему Код (Text): // wait for read operation to complete while(TWI_MRX == twi_state){ continue; } в twi_readFrom https://code.google.com/p/arduino/source/browse/trunk/libraries/Wire/utility/twi.c?r=1092
может по аналогии? HTML: const int ledPin = 13; long previousMillis = 0; long interval = 10000; void setup() { pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop() { unsigned long currentMillis = millis(); while (!Serial.available()) { if (millis()-currentMillis > interval) break; } digitalWrite(ledPin, 1); }
Wire.requestFrom() вызывает twi_readFrom(), который и залипает. Снаружи это не разлепить без манипуляций с указателями стека и инструкции. А внутри приведенной библиотеки выполняется "разлипание" как раз показанным вами способом .