MCP23017 interrupt triggered by falling voltage on a GPIO pin.

Is this possible or do they only work through a rising voltage?

void CMCP23017::setIntPinPolarity(const bool bHigh)
{
	uint8_t nIOCONPort = PORT(IOCONA), nIOCONPortVal = readReg(nIOCONPort);


	if (bHigh)
	{
		writeReg(nIOCONPort, nIOCONPortVal & 0b11111101);
	}
	else
	{
		writeReg(nIOCONPort, nIOCONPortVal | 0b00000010);
	}
}

void CMCP23017::setIntMirroring(const bool bYes)
{
	uint8_t nIOCONPort = PORT(IOCONA), nIOCONPortVal = readReg(nIOCONPort);

	if (bYes)
		writeReg(nIOCONPort, nIOCONPortVal | 0b01000000);
	else
		writeReg(nIOCONPort, nIOCONPortVal & 0b10111111);
}

void CMCP23017::setIntOpenDrain(const bool bYes)
{
	uint8_t nIOCONPort = PORT(IOCONA), nIOCONPortVal = readReg(nIOCONPort);

	if (bYes)
		writeReg(nIOCONPort, nIOCONPortVal | 0b00000100);
	else
		writeReg(nIOCONPort, nIOCONPortVal & 0b11111011);
}


void CMCP23017::setInterruptBehavior(const bool bHigh, const bool bMirror, const bool bOpenDrain)
{
	setIntPinPolarity(bHigh);
	setIntMirroring(bMirror);
	setIntOpenDrain(bOpenDrain);
}


void CMCP23017::setInterrupt(const uint8_t nArduinoIntNo, void (* pointerISR)(), const uint8_t nPin, const bool bRising)
{
	uint8_t nGPINTENPort = getPort(nPin, GPINTENA, GPINTENB),
			nGPINTENPortVal = readReg(nGPINTENPort),
			nINTCONPort = getPort(nPin, INTCONA, INTCONB),
			nINTCONPortVal = readReg(nINTCONPort),
			nDEFVALPort = getPort(nPin, DEFVALA, DEFVALB),
			nDEFVALPortVal = readReg(nDEFVALPort),
			nPinMask = getPinMask(nPin);

	// Set the bit of this register, correspomding to GPIO pin, in order to allow that GPIO pin to generate interrupts.
	writeReg(nGPINTENPort, nGPINTENPortVal | nPinMask);

	// Clear the bit, corresponding to the GPIO pin, so that its state is compared to its previous state to determine whether or not to generate an interrupt.
	writeReg(nINTCONPort, nINTCONPortVal & ~nPinMask);

	// Set the pin as an input
	setInput(nPin);

	attachInterrupt(nArduinoIntNo, pointerISR, CHANGE);

	// If the interrupt is signalled by a LOW to HIGH transistion then...
	if (bRising)
	{
		setInterruptBehavior(false, false, false);

		setPullup(nPin, false);
	}
	// If the interrupt is signalled by a HIGH to LOW transistion then...
	else
	{
		setInterruptBehavior(true, false, false);

		setPullup(nPin, true);
	}
}

I have LEDs + resistors on each MCP GPIO pin so I can see whether or not the pullup resistors are on for each pin. And I can connect other LEDs to the INT pins to see if they are HI or LO

I seem to have the logic right...

In call to setInterrupt(...) :

  1. When bRising parameter is true, then the pullup resistor is off and the INT pins are LO.

  2. When bRising parameter is false, then the pullup resistors are on and the INT pins are HI.

But interrupts are happily triggered when bRising is true and I connect the GPIO pin to 5V, but not when it is false and I connect the GPIO pin to GND.

So, unless I am doing something wrong in the code above, then it appears that the MCP interrupts only work in one direction, i.e. when a GPIO pin goes from LO to HI.