Skip to content

The MCP23017 expander is an excellent GPIO extension for the Raspberry Pi. It features 16 additional GPIOs that can be configured as output and input pins. This mcp23017 class simplifies working with the I2C interface, configuring the MCP, and switching the pins for your project.

License

Notifications You must be signed in to change notification settings

dsmurph/mcp23017

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🛸 MCP23017 C++ Library – Build Keypads, Sensors, Relays & Interrupt Systems

The MCP23017 expander is an excellent GPIO extension for Raspberry Pi, Microcontroller and many other platforms with I2C interface.

It features 16 additional GPIOs that can be configured as output and input pins.

This MCP23017 C++ API simplifies working with the I2C interface, configuring the MCP, and switching the pins for your project.

The functions are kept simple and restore all the functionalities of the expander.

Perfect for students, hobbyists and projects where GPIO control is simply needed –without having to delve deeper into the expander's registers.


✨ Features

✔️ Simple GPIO input/output

✔️ One-line pin configuration

✔️ Interrupt support (RISING, FALLING, BOTH)

✔️ Interrupt read and capture pin level

✔️ Interrupt Pin Output Mode (Rising/Falling POL, Open-Drain, Separate A/B Output Pins)


❗Basic

📱 A fast way!

The basic functions are simple and clearly designed.

Just three lines of code will get the MCP working for you and complete your project.

1️⃣ Configure

2️⃣ Write

3️⃣ Read

🥵 You want to make an LED sweat?

No problem! Use the pinMode() function and assign any MCP pin as the output.

With pinWrite(), you can animate the LED by switching it between high and low.

🔥 Or perhaps you'd like to make a button glow red-hot?

Use pinMode() and configure a pin as an input.

Want a stable high for your low flag but don't have a resistor ready to hand?

Extend the input pin with an internal pull-up resistor.

And now what? Yes, pinRead() keeps you informed, button pressed or released.

There are no limits to the output and further processing.


🤖 Interrupts

💡 You don't have to configure everything.

The interrupt function is very easy to use – for more control, you can also enable fine-tuning options like mirroring, open-drain, or slow edges.

The process is always the same:

1️⃣ Set the mode (output behavior and trigger type)

2️⃣ Enable interrupt

3️⃣ Query what happened

4️⃣ Optionally reset or confirm

Nothing is lost.

Whether you query the level live, view the bitmask, or use the capture function – the information remains stored until you explicitly delete it or confirm it by reading GPIO.

Capture is like a photo.

The getIntCapture() function records the state that was on the pin at the exact moment the interrupt was triggered.

Perfect if you want to know why the interrupt occurred – not just that it happened.

Deleting is optional.

All query functions have an optional clear parameter.

You decide: read values only, or also acknowledge and clear them.

Single pin or all at once.

There are dedicated functions like clearInterrupt(pin) for individual pins,

and convenient functions like clearInterrupts() to clear everything at once.

📝 A point for users to understand:

The interrupts on the MCP23017 are not "actively running," but rather "reporting and waiting."

Once an event is triggered, it remains stored—until you say:

"Thanks, I see."

That's exactly what the clear functions are for.


🧩 Provided Functions

Function Description
pinMode(pin, OUTPUT, INPUT, INPUT_PULLUP) Configures pin direction
pinWrite(pin, HIGH/LOW) Sets pin output state
pinRead(pin) Reads digital input
enableInt(pin, true/false) Enable/Disable Interrupts on Pin
intOutputMode(HIGH/LOW, ODR true, MIRROR true) (**) Level, open-drain, seperate A/B
intTriggerMode(RISING, FALLING, BOTH) Rising, Falling, Both -Flags
getInterruptFlags(INTFA/B clear true)(**) Outputs Int events as bitmask
getInterruptPins(INTFA/B clear true)(**) Outputs Int events as pinnum
getIntCapture(INTCAPA/B clear true)(**) Edge of the interrupt event
clearIntCapture(pin) Reset the capture bit
clearInterrupts() Reset Int configure and values
(**) optional -> default as false

🎁 Take a look at the examples.

Exemplares as inspiration and ideas for your project.

📁 examples/

 ├── blink.cpp      // Make individual LEDs blink
 ├── taster.cpp     // Query buttons
 ├── highlow.cpp    // Set Pin high/low
 ├── interrupt.cpp  // Interrupt on pins
 └── keypad.cpp     // A keypad matrix example


📐The functions explained

/* Set pin mode Output/Input
*
*  pinMode(PIN, OUTPUT/INPUT/INPUT_PULLUP)
*
*  Output       = You can use this setting for a high and low output signal
*  Input        = For connections with defined high/low signal or external pullup/pulldown resistor
*  Input_Pullup = An input pin set to pull-up can be queried for a low signal.
*
*/


/* Set pin to HIGH/LOW signal 
*
*  pinWrite(PIN, HIGH/LOW)
*
*  High = Signal at the level of the operating voltage, most 3.3 or 5 volts.
*  Low  = Signal indicating the absence of a voltage close to ~0 volts.
*/


/* Set pin to read a signal 
*
*  pinRead(PIN)
*
*  It reproduces the signal that is present at the pin.
*/


/* Set interrupt output pins
*
*  intOutputMode(HIGH/LOW, ODR true **, MIRROR true **)
*
*  INTPOL  = The output pin can be set to either a falling or rising edge.
*            HIGH: Interrupt pin goes HIGH on event
*            LOW:  Interrupt pin goes LOW on event
*  ODR     = True: For external pull-up, INTPOL is automatically set to default.
*  MIRROR  = True: INTA and INTB Pins separately, default is false. 
*
*  ** If you don't need this setting, you can leave it out.
*
*/


/* Set interrupt input pins
*
*  intTriggerMode(PIN, CHANGE/RISING/FALLING)
*
*  CHANGE   = Every change of flank
*  RISING   = On rising flank
*  FALLING  = On a falling flank
*
*/


/* Enable/Disable the Interrupt Pin
*
*  enableInt(PIN, TRUE/FALSE)
*
*  Enable or disable a pin as an interrupt
*
*/


/* Interrupt output as Pinnums
*
*  getInterruptPins(clear ture **)
*
*  Outputs of active interrupt pins as pin number
*
*/


/* Interrupt output as bitmask
*
*  getInterruptFlags(clear ture **)
*
*  Outputs of active interrupt pins as a bitmask
*
*/


/* Interrupt Capture reproduces the state of the pins during an interrupt.
*
*  getIntCapture(clear ture **)
*
*  Outputs the state of the interrupt pin at the time of an edge transition.
*
*/


/* Interrupt flag as boolean
*
*  isInterruptOnPin(PIN, clear ture **)
*
*  Outputs a Boolean value on a pin interrupt
*
*/

// ** Optionally clear, the values can be reset after output with true, default is false. If you don't need this setting, you can leave it out.


/* Interrupt Capture reset a specific pin.
*
*  clearIntCapture(PIN)
*
*  INTCAP can only be read, but according to the datasheet, reading the GPIOs is sufficient for resetting.
*  
*/


/* Interrupt clean up.
*
*  clearInterrupts()
*
*  All interrupt settings and values ​​will be reset.
*  
*/

/********** MCP configure **********

*  enableSlewRateControl(true/false)
*
*  DISSLW = true: Only in cases of long cable runs or EMI problems I2C SDA.


*  setSequentialOperation(true/false) 
*
*  SEQOP = true: Useful when a register needs to be continuously queried (read) or changed (written).


📄 License

MIT License
You are free to use, modify, and distribute this project.


🤝 Contributions

Pull requests and improvements are welcome.
Feel free to fork, enhance, or suggest features.


⭐ If this lib helps your project — consider starring it on GitHub!

About

The MCP23017 expander is an excellent GPIO extension for the Raspberry Pi. It features 16 additional GPIOs that can be configured as output and input pins. This mcp23017 class simplifies working with the I2C interface, configuring the MCP, and switching the pins for your project.

Topics

Resources

License

Stars

Watchers

Forks