Прерывания
Как было указано в самом начале, у модуля есть два специальных контакта IA и IB. При смене уровня на контактах расширителя, на IA и IB возникнет импульс, который можно использовать для активации прерывания на микроконтроллере.
Зачем нужны прерывания мы говорили в уроке про прерывания.
Если коротко, то при использовании прерываний контроллер не будет общаться с расширителем постоянно, и все ресурсы будет тратить на основную задачу. Как только сработает прерывание, контроллер прочитает состояние нужного контакта на расширителе по I2C шине, вызовет обработчик этого события и продолжит опять выполнять свои рутинные дела.
Пишем программу.
#include <Adafruit_MCP23017.h>
Adafruit_MCP23017 mcp;
// к этому контакту Arduino подключен встроенный светодиод
const byte ledPin = 13;
// к этому контакту расширителя подключен внешний светодиод
const byte mcpPin = 0;
// к этому контакту Arduino подключен контакт IA расширителя
const byte arduinoIntPin = 3;
// на 3-м контакте Arduino обслуживается прерывание №1
const byte arduinoInterrupt = 1;
// переменная - флаг, которая примет значение true
// при возникновении прерывания
volatile boolean awakenByInterrupt = false;
void setup(){
// настраиваем режим контакта для прерывания Arduino
pinMode(arduinoIntPin,INPUT);
// инициализируем расширитель с адресом 7
mcp.begin(7);
// настраиваем прерывания расширителя
// режим зеркалирования отключен - false
// режим открытого стока отключен - false
// инверсия сигнала включена - LOW
mcp.setupInterrupts(false, false, LOW);
mcp.pinMode(mcpPin, INPUT); // установка режима
mcp.pullUp(mcpPin, HIGH); // подтяжка контакта к питанию
// активируем прерывание расширителя на контакте mcpPin
// в режиме детектирования спада импульса - FALLING
mcp.setupInterruptPin(mcpPin, FALLING);
// настраиваем режим контакта для светодиода
pinMode(ledPin, OUTPUT);
// активируем прерывание Arduino под номером arduinoInterrupt
// с вызовом функции intCallBack
// в режиме детектирования спада импульса - FALLING
attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
}
// обработчик прерывания Arduino
void intCallBack(){
awakenByInterrupt = true;
}
void handleInterrupt(){
// отключаем прерывание на время пока выполняется обработчик
detachInterrupt(arduinoInterrupt);
// мигаем один раз светодиодом
digitalWrite(ledPin,HIGH);
delay(100);
digitalWrite(ledPin,LOW);
delay(100);
// ждём, пока кнопку не отпустят
while( !mcp.digitalRead(mcpPin));
// сбрасываем флаг нажатия
awakenByInterrupt = false;
// включаем прерывание обратно
attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
}
void loop(){
// если прерывание сработало и флаг истина
if(awakenByInterrupt){
// делаем, что задумали
handleInterrupt();
}
}
Загружаем программу на Ардуино и проводим тест: нажимаем кнопку — в отчет, встроенный светодиод должен мигнуть один раз.