Arduino DUE+I2C+Аппаратное прерывание

PIW2004
Offline
Зарегистрирован: 24.09.2013

Имеется следующая связка, Arduino DUE, к которой по I2C подключена клавиатура, собраная на базе PCA9555 (на каждом входе сидит кнопка), так же по I2C подключен силовой блок, собранный так же на PCA9555 (на каждом выходе по силовому тразистору с обвязкой).

Помимо этого еще штук 7 аналоговых датчиков.

Впринципи всё работает, но из за времени на опросы датчиков и прочее, силовой блок не так резво реагирует на нажатия клавиатуры.

У PCA9555 есть выход INT, на котором появляется сигнал, при нажатии одной из кнопок, пишут что этот сигнал для организации Аппаратного прерывания, вот и возникла мысль, выделить опрос клавиатуры и выдачу команд на силовой блок, в отдельный цыкл, запускаемый по прерыванию, что бы в основном цикле постоянно не происходило опроса кнопок.

Запустить маргание диодом в отдельном цикле получилось, когда нажимаю кнопки, он маргает от сигнала INT, но вот вставить в этот цикл опрос кнопок и выдачу сигналов на силовой блок не выходит.

Вот пример кода, тут в отдельный цикл вставлено только маргание, когда копирую в него действия из основного цикла, ничего не происходит, и DUE вешается.



#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); //У DUE вроде как любой вход можно назначить на прерывание
  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 девайсы, если да, то как примерно должен выглядить код?

Пробовал в цикл по прерыванию вставлять только опрос клавиатуры:



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 потом использовать в основном цикле, всёравно не работает, плата зависает.

Когда всё в основном цикле, всё идеально работает... Тут нет опроса датчиков, что бы код был покороче.

PIW2004
Offline
Зарегистрирован: 24.09.2013

Никаких идей? :(