I'm having an issue with handling multiple interrupts. I have a Microchip I2C I/O expander connected to my Arduino board. The INT pin of the MCP is connected to pin 2 on the Arduino (Interrupt 0), and the I/O pins on the MCP are connected to switches and other junk that I want to capture interrupts from. This side works fine, they're all working properly. The Interrupts on the Arduino are enabled, and it works if I ground the line myself... the problem is that the MCP23008 should be doing this itself. I've gone through the data sheet several times, trying to figure it out, and I just can't seem to make it all work properly.
Can anyone offer any advice/suggestions? Here is the code I'm using. The Lcd functions are in a separate file, work perfectly fine by themselves, and don't touch anything except LCD pins and such. : |
/* Alarm clock "Proof of concept"
*/
#include <Wire.h> // I2C library from Wire.
//#include <avr/pgmspace.h> // Program memory from Atmel
#include <stdio.h> // printf and family
/*-----------------------------------------------------------------
-- LCD communication pin definitions --
-----------------------------------------------------------------*/
const int int_pin = 2; // Pin Arduino is using Interrupts on
const int lcd_rs = 3; // RS pin of LCD
const int lcd_rw = 4; // R/W pin of LCD
const int lcd_en = 5; // Enable pin of LCD
const int lcd_db[] = {6, 7, 8, 9, 10, 11, 12, 13}; // LCD data pins
const int lcd_db_size = 8; // # data pins in array
/*-----------------------------------------------------------------
-- Strings and buffers --
-----------------------------------------------------------------*/
char string_buffer[17]; // 16 characters + null
const char str_12hr_time[] = " %2x:%02x:%02x%cM ";
const char str_24hr_time[] = " %02x:%02x:%02x ";
const char str_date[] = " %3s, %3s %02x ";
const char str_weekday[][4] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"};
const char str_months[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
/*-----------------------------------------------------------------
-- Interrupt Shennanigans --
-----------------------------------------------------------------*/
volatile bool int_flag; // Place to hold interrupt flag
byte int_mask; // Bit mask of each interrupt line that was toggled.
const byte int_active = B00011111; // I/O expander lines with something that triggers interrupts
// Interrupt service function
void Interrupt()
{
// All we need to do is indicate that an interrupt's been fired.
int_flag = true;
}
// Setup junk.
void setup()
{
// Set up I2C first.
Wire.begin(12);
Serial.begin(9600);
pinMode(2, INPUT);
Serial.println("Yo!");
// Configure RTC for 1Hz Clockout
Wire.beginTransmission(0x51);
Wire.send(0x0D);
Wire.send(0x83);
Wire.endTransmission();
// Set up the I/O Expander to produce interrupts
Wire.beginTransmission(0x20);
Wire.send(0x00);
Wire.send(0xFF);
Wire.send(0x00);
Wire.send(int_active);
Wire.send(int_active);
Wire.send(int_active);
Wire.send(0x04);
Wire.endTransmission();
// Fire up the LCD
LcdInit();
//Wire.beginTransmission(0x20);
//Wire.send(0x00);
//Wire.endTransmission();
Wire.requestFrom(0x51, 11);
while (Wire.available())
{
Serial.println(Wire.receive(), BIN);
}
// Start interrupts to falling edge
attachInterrupt(0, Interrupt, FALLING);
}
// The main guts.
void loop()
{
// Check if an interrupt has fired.
if (int_flag)
{
// Clear the interrput flag now - if our routine takes too long, we might (will) miss
// the next interrupt, which WILL fuck things up.
int_flag = false;
// Get data from the I/O expander to see which buggers fired.
Wire.beginTransmission(0x20);
Wire.send(0x07);
Wire.endTransmission();
Wire.requestFrom(0x20, 2);
Serial.println(int_mask = Wire.receive(), BIN);
Serial.println(Wire.receive(), BIN);
// Do ... something.
if (int_mask & 0x01)
{
byte sec, mins, hrs, day, wkd, mth;
// CLKOUT fired. Update LCD.
Wire.beginTransmission(0x51);
Wire.send(0x02);
Wire.endTransmission();
Wire.requestFrom(0x51, 6);
sec = Wire.receive() & B01111111;
mins = Wire.receive() & B01111111;
hrs = Wire.receive() & B00111111;
day = Wire.receive() & B00111111;
wkd = Wire.receive() & B00000111;
mth = Wire.receive() & B00011111;
// Write new time
LcdSetPos(0,0);
sprintf(string_buffer, str_24hr_time, hrs, mins, sec);
Serial.println(string_buffer);
LcdPrint(string_buffer);
sprintf(string_buffer, str_date, str_weekday[wkd], str_months[mth - 1], day);
Serial.println(string_buffer);
LcdSetPos(1, 0);
LcdPrint(string_buffer);
}
}
}