PCF8575 и прерывания

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Добрый день, камрады. Пытаюсь разобраться с расширителем портов PCF8575 и выводом INT. Схема такая:

скетч такой

#include <Wire.h>

#define ATMEGA_PIN_INT 2
#define PCF8575_ADDRESS 0x20                // адрес модуля на шине

uint8_t hi, lo;
uint16_t PCF8575_dataReceive;               // Данные, прочитанные из модуля
uint8_t PCF8575_dataLowByte;                // Младший байт (P00...P07) - выходы
uint8_t PCF8575_dataHighByte;               // Старший байт (P10...P17) - входы
volatile bool keyPress = 0;

void setup() {

  Wire.begin();
  Serial.begin(115200);
  Serial.println("Started...");
  PCF8575_dataHighByte = B11111111;                            // Высокий уровень во все входы PCF8575
  PCF8575_dataLowByte = B00000000;                             // Низкий уровень (вкл) во все выходы PCF8575
  pcf8575_write(PCF8575_dataLowByte, PCF8575_dataHighByte);    // выгружаем данные в модуль
  pinMode(ATMEGA_PIN_INT, INPUT);
  attachInterrupt(0, ISRgateway, FALLING);

}

void ISRgateway() {
  keyPress = 1;
}

void loop() {
  if (keyPress == 1) {
    PCF8575_dataReceive = pcf8575_read();
    PCF8575_dataHighByte = B11111111;                            // Высокий уровень во все входы PCF8575
    PCF8575_dataLowByte = B00000000;                             // Низкий уровень (вкл) во все выходы PCF8575
    pcf8575_write(PCF8575_dataLowByte, PCF8575_dataHighByte);    // выгружаем данные в модуль
    keyPress = 0;
    Serial.println("Button pressed");
  }
}

void pcf8575_write(uint8_t dtl, int8_t dth) {                    // Процедура записи байта в модуль
  Wire.beginTransmission(PCF8575_ADDRESS);
  Wire.write(dtl);                                               // Записываем младший байт (P00...P07)
  Wire.write(dth);                                               // Записываем старший байт (P10...P17)
  Wire.endTransmission();
}


int16_t pcf8575_read() {                                         // Процедура чтения байта из модуля
  Wire.beginTransmission(PCF8575_ADDRESS);
  Wire.endTransmission();
  Wire.requestFrom(PCF8575_ADDRESS, 2);
  lo = Wire.read();                                            // Читаем младший байт (P00...P07)
  hi = Wire.read();                                            // Читаем старший байт (P10...P17)
  return (word(hi, lo));                                       // Возвращаем длинное слово
}

Проблема в том, что прерывание срабатывает только один раз (при нажатии любой кнопки), и после отпускания кнопки, вывод INT PCF8575 не возвращается в высокое состояние. Если загрузить "пустой" скетч, то нажатия кнопок прижимает INT вниз, после отпускания кнопки вывод возвращается в высокое состояние. Что я делаю не так?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

да, в обработчике прерывания запись в PCF8575 - шаманские танцы с целью вернуть вывод INT в высокое состояние, которые ни к чему не привели

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Надеюсь, ты его к плюсу притянул?  (вывод INT)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

вот здеся: 

The PCF8575 provides an open-drain interrupt (INT) output, which can be connected to the interrupt input of a microcontroller. An interrupt is generated by any rising or falling edge of the port inputs in the input mode. After time, tiv, the signal INT is valid. Resetting and reactivating the interrupt circuit is achieved when data on the port is changed to the original setting, or data is read from or written to the port that generated the interrupt. Resetting occurs in the read mode at the acknowledge (ACK) bit after the rising edge of the SCL signal or in the write mode at the ACK bit after the falling edge of the SCL signal. Interrupts that occur during the ACK clock pulse can be lost (or be very short), due to the resetting of the interrupt during this pulse. Each change of the I/Os after resetting is detected and is transmitted as INT. Reading from or writing to another device does not affect the interrupt circuit. This device does not have internal configuration or status registers. Instead, read or write to the device I/Os directly after sending the device address

что непонятного?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

DetSimen пишет:

Надеюсь, ты его к плюсу притянул?  (вывод INT)

 

Да, возле разъема резистор висит )

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

DetSimen пишет:

вот здеся: 

The PCF8575 provides an open-drain interrupt (INT) output, which can be connected to the interrupt input of a microcontroller. An interrupt is generated by any rising or falling edge of the port inputs in the input mode. After time, tiv, the signal INT is valid. Resetting and reactivating the interrupt circuit is achieved when data on the port is changed to the original setting, or data is read from or written to the port that generated the interrupt. Resetting occurs in the read mode at the acknowledge (ACK) bit after the rising edge of the SCL signal or in the write mode at the ACK bit after the falling edge of the SCL signal. Interrupts that occur during the ACK clock pulse can be lost (or be very short), due to the resetting of the interrupt during this pulse. Each change of the I/Os after resetting is detected and is transmitted as INT. Reading from or writing to another device does not affect the interrupt circuit. This device does not have internal configuration or status registers. Instead, read or write to the device I/Os directly after sending the device address

что непонятного?

Да собственно все: "Resetting and reactivating the interrupt circuit is achieved when data on the port is changed to the original setting, or data is read from or written to the port that generated the interrupt"

when data on the port is changed to the original setting - это я так понимаю кнопка должна быть отпущена (не реагирует)

data is read from - PCF8575_dataReceive = pcf8575_read() - тоже безрезультатно

or written to the port that generated the interrupt - pcf8575_write(PCF8575_dataLowByte, PCF8575_dataHighByte); - тоже нифига.

или я не могу правильно интерпретировать написанное по-басурмански :(

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Там родным по белому написано, хочешь флаг прерыания сбросить - прочитай, матьтваю, регитр вызвавший прерывание. Не помогло, ищи ошибку в схеме. По крайней мере у меня 8574 так работает. Правда, 8575 я не щюпал. 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Не гневитесь - я не настоящий сварщик, маску на стройке нашел (только осваиваю программирование), поэтому не знаю как это (матьмаю) прочитать регистр. Как это сделать?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Щас взрослые придут, пацкажут. 

Komandir
Онлайн
Зарегистрирован: 18.08.2018

для чего строки 49 и 50 ? Запросили запись и ничего не записали ?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Komandir пишет:

для чего строки 49 и 50 ? Запросили запись и ничего не записали ?

Это остатки моих безуспешных попыток сбросить прерывание.

Komandir
Онлайн
Зарегистрирован: 18.08.2018

А вы с адресом не напутали ничего ? Какой адрес находит скетч i2C scanner ?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

с адресом все нормально, один раз прерывание срабатывает и нажатие кнопки читается. При работе через библиотеку все тоже работает, но хочется понять как это работает непосредственно. по прерыванию я допустим считываю.

P.S. а не, похоже я все же со схемой намудрил.