Имеется следующая связка, Arduino DUE, к которой по I2C подключена клавиатура, собраная на базе PCA9555 (на каждом входе сидит кнопка), так же по I2C подключен силовой блок, собранный так же на PCA9555 (на каждом выходе по силовому тразистору с обвязкой). Помимо этого еще штук 7 аналоговых датчиков. Впринципи всё работает, но из за времени на опросы датчиков и прочее, силовой блок не так резво реагирует на нажатия клавиатуры. У PCA9555 есть выход INT, на котором появляется сигнал, при нажатии одной из кнопок, пишут что этот сигнал для организации Аппаратного прерывания, вот и возникла мысль, выделить опрос клавиатуры и выдачу команд на силовой блок, в отдельный цыкл, запускаемый по прерыванию, что бы в основном цикле постоянно не происходило опроса кнопок. Запустить маргание диодом в отдельном цикле получилось, когда нажимаю кнопки, он маргает от сигнала INT, но вот вставить в этот цикл опрос кнопок и выдачу сигналов на силовой блок не выходит. Вот пример кода, тут в отдельный цикл вставлено только маргание, когда копирую в него действия из основного цикла, ничего не происходит, и DUE вешается. Код (Text): #include <Wire.h> #include <itoa.h> //Адреса #define A_Klap 0x21 //Клапанов #define A_Klav 0x20 //Клапанов //Клапана/Клавиатура #define K_INPUT0 0x00 //Конфигуратор Вход port0 #define K_INPUT1 0x01 //Конфигуратор Вход port1 #define K_OUTPUT0 0x02 //Конфигуратор Выход port0 #define K_OUTPUT1 0x03 //Конфигуратор Выход port0 #define K_INV0 0x04 //инверсия Выход port0 #define K_INV1 0x05 //инверсия Выход port1 #define K_CONFIG0 0x06 //Конфигурация клапанов port0 #define K_CONFIG1 0x07 //Конфигурация клапанов port1 //Кнопки #define B_UPL 0x01 //Подъём #define B_DPL 0x02 //Опускание #define B_UPP 0x10 //Подъём #define B_DPP 0x20 //Опускание #define B_UZL 0x04 //Подъём #define B_DZL 0x08 //Опускание #define B_UZP 0x40 //Подъём #define B_DZP 0x80 //Опускание //Клапана #define K_UPL 0x01 //Подъём #define K_DPL 0x80 //Опускание #define K_UPP 0x02 //Подъём #define K_DPP 0x40 //Опускание #define K_UZL 0x04 //Подъём #define K_DZL 0x20 //Опускание #define K_UZP 0x08 //Подъём #define K_DZP 0x10 //Опускание #define K_OFF 0x00 //выключены volatile int state = LOW; void setup(){ pinMode(13, OUTPUT); pinMode(2, INPUT); attachInterrupt(2,Klava,FALLING); //Прерывание на 2 ноге от INT клавиатуры Wire.begin(); Wire.beginTransmission(A_Klap); //Конфигурирование клапанов Wire.write(K_CONFIG0); Wire.write(0x00); //Порт0 все выхода Wire.write(0x00); //Порт1 все выхода Wire.endTransmission(); delay (30); Wire.beginTransmission(A_Klap); //Установка в ВЫКЛ Wire.write(K_OUTPUT0); //Выключаем Порт0 Wire.write(0x00); Wire.endTransmission(); Wire.beginTransmission(A_Klap); //Установка в ВЫКЛ Wire.write(K_OUTPUT1); //Выключаем Порт1 Wire.write(0x00); Wire.endTransmission(); Wire.beginTransmission(A_Klav); //Конфигурация клавиатуры Wire.write(K_CONFIG0); Wire.write(0xFF); //Порт0 все входа Wire.write(0xFF); //Порт1 все входа Wire.endTransmission(); delay (30); Wire.beginTransmission(A_Klav); //Инвертируем значение порт0 Wire.write(K_INV0); Wire.write(0xFF); Wire.endTransmission(); Wire.beginTransmission(A_Klav); //Инвертируем значение порт1 Wire.write(K_INV1); Wire.write(0xFF); // low byte Wire.endTransmission(); } void Klava() //Цикл запускаемый от прерывания Клавиатуры { //программная стабилизация "дребезга" от INT клавиатуры static unsigned long millis_prev; if(millis()-100 > millis_prev) state = !state; // меняем значение на противоположное millis_prev = millis(); } void loop(){ //Чтение Порт0 клавиатуры Wire.beginTransmission(A_Klav); Wire.write(K_INPUT0); Wire.endTransmission(); Wire.requestFrom(A_Klav, 1); byte Klav0 = Wire.read(); Wire.endTransmission(); //Чтение Порт1 клавиатуры Wire.beginTransmission(A_Klav); Wire.write(K_INPUT1); // set data pointer Wire.endTransmission(); Wire.requestFrom(A_Klav, 1); byte Klav1 = Wire.read(); Wire.endTransmission(); //Асоциация нажатия клавиши и включения клапана switch (Klav0){ case B_UPL: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT0); Wire.write(K_UPL); Wire.endTransmission(); break; case B_UPP: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT0); Wire.write(K_UPP); Wire.endTransmission(); break; case B_DPL: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT1); Wire.write(K_DPL); Wire.endTransmission(); break; case B_DPP: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT1); Wire.write(K_DPP); Wire.endTransmission(); break; case B_UZL: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT0); Wire.write(K_UZL); Wire.endTransmission(); break; case B_UZP: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT0); Wire.write(K_UZP); Wire.endTransmission(); break; case B_DZL: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT1); Wire.write(K_DZL); Wire.endTransmission(); break; case B_DZP: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT1); Wire.write(K_DZP); Wire.endTransmission(); break; default: Wire.beginTransmission(A_Klap); Wire.write(K_OUTPUT0); Wire.write(K_OFF); Wire.write(K_OFF); Wire.endTransmission(); } //Мигаем светодиодом, когда на INT клавиатуры сигнал о нажатии кнопки. digitalWrite(13,state); } Вопрос, можно ли по прерыванию опрашивать I2C девайсы, если да, то как примерно должен выглядить код? Пробовал в цикл по прерыванию вставлять только опрос клавиатуры: Код (Text): //Чтение Порт0 клавиатуры Wire.beginTransmission(A_Klav); Wire.write(K_INPUT0); Wire.endTransmission(); Wire.requestFrom(A_Klav, 1); byte Klav0 = Wire.read(); Wire.endTransmission(); //Чтение Порт1 клавиатуры Wire.beginTransmission(A_Klav); Wire.write(K_INPUT1); // set data pointer Wire.endTransmission(); Wire.requestFrom(A_Klav, 1); byte Klav1 = Wire.read(); Wire.endTransmission(); Что бы переменные Klav0 и Klav1 потом использовать в основном цикле, всёравно не работает, плата зависает. Когда всё в основном цикле, всё идеально работает... Тут нет опроса датчиков, что бы код был покороче.
У меня, конечно, никаких идей. Только вопрос: а зачем вы давите дребезг в прерывании? И вообще - в прерывании — только быстробыстробыстро работать надо) Может попробовать в прерывании просто выставлять какую-нибудь переменную в TRUE, а потом в главном цикле проверять - если она TRUE - считать с клавиатуры. Если нет - пропустить. Ну и дребезг, мне кажется, тут лишний. Еще вариант - вообще без прерываний (если дребезг-таки присутствует). Так же, в главном цикле проверять, не стоит ли этот int. И если стоит - выполнять опрос, а потом блокировать возможность опроса на те же 100 милисекунд. Нажатие клавиатуры - это не та штука которую сложно найти, легко потерять и невозможно забыть. Кнопка по определению нажата доооолго (для контроллера). Поэтому прерывание считаю тут лишним.
А еще для чтения кнопок с подавлением дребезга есть специально обученная библиотека. Кроме того, можно давить дребезг аппаратно и не грузить этим контроллер.
О, спасибо за наводку) Но тут уважаемый PIW2004 читает значения из i2c-расширителя портов. Поэтому тут нужно как-то по другому работать) Например, ловим мы этот int. Что это значит? Что где-то там, что-то шлёпнулось на землю. Естественно, оно шлёпнулось с подпрыгиванием, и когда мы будем читать значение пинов из i2c, не факт, что пины в этот момент не будут «в прыжке». Но мы знаем - что там у нас — кнопка. А где кнопка там и палец. А палец не может двигаться со скоростью контроллера. Поэтому прерывание можно было б не использовать вообще, использовать нашу «суперпетлю» как шумодав. Хотя можно и с millis() Код (Text): bool I2Cint = !(digitalRead(2)); if (I2Cint) { millis_prev=millis(); } if (I2Cint && (millis()-100 > millis_prev)) { klava(); }