Basic library to interface to a Microchip MCP23016 I/O expander using I2C

Testing code to blink 2 lights

#include "mbed.h"
#include "MCP23016.h"

MCP23016 PortExpand(D4, D5, 0);
DigitalOut myled(LED1);

int main() {
    PortExpand.pinMode(0, DIR_OUTPUT);
    PortExpand.pinMode(8, DIR_OUTPUT);
    while(1) {
        PortExpand.digitalWrite(0, 1);
        PortExpand.digitalWrite(8, 0);
        myled = 1; // LED is ON
        wait(1); // 200 ms
        PortExpand.digitalWrite(0, 0);
        PortExpand.digitalWrite(8, 1);
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

Files at this revision

API Documentation at this revision

Comitter:
davidr99
Date:
Tue Jan 19 23:50:23 2016 +0000
Commit message:
MCP23016 Library

Changed in this revision

MCP23016.cpp Show annotated file Show diff for this revision Revisions of this file
MCP23016.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 133b7e09bbe7 MCP23016.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23016.cpp	Tue Jan 19 23:50:23 2016 +0000
@@ -0,0 +1,216 @@
+/*  MCP23016 library
+    Based on MCP23017 library for arduino by David Pye <davidmpye@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "MCP23016.h"
+#include "mbed.h"
+
+union {
+    uint8_t  value8[2];
+    uint16_t value16;
+} tmp_data;
+
+/*-----------------------------------------------------------------------------
+ *
+ */
+MCP23016::MCP23016(PinName sda, PinName scl, int i2cAddress)  : _i2c(sda, scl) {
+    MCP23016_i2cAddress = I2C_BASE_ADDRESS + i2cAddress;
+    reset();                                  // initialise chip to power-on condition
+}
+
+/*-----------------------------------------------------------------------------
+ * reset
+ * Set configuration (IOCON) and direction(IODIR) registers to initial state
+ */
+void MCP23016::reset() {
+//
+// set direction registers to inputs
+//
+    writeRegister(IODIR0, (unsigned short)0xFFFF);
+//
+// set all other registers to zero (last of 10 registers is OLAT)
+//
+    for (int reg_addr = OLAT0 ; reg_addr <= IPOL1 ; reg_addr+=2) {
+        writeRegister(reg_addr, (unsigned short)0x0000);
+    }
+//
+// Set the shadow registers to power-on state
+//
+    shadow_IODIR = 0xFFFF;
+    shadow_GPIO  = 0;
+    shadow_IPOL  = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * write_bit
+ * Write a 1/0 to a single bit of the 16-bit port
+ */
+void MCP23016::write_bit(int value, int bit_number) {
+    if (value == 0) {
+        shadow_GPIO &= ~(1 << bit_number);
+    } else {
+        shadow_GPIO |= 1 << bit_number;
+    }
+    writeRegister(OLAT0, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * Write a combination of bits to the 16-bit port
+ */
+void MCP23016::write_mask(unsigned short data, unsigned short mask) {
+    shadow_GPIO = (shadow_GPIO & ~mask) | data;
+    writeRegister(OLAT0, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * read_bit
+ * Read a single bit from the 16-bit port
+ */
+int  MCP23016::read_bit(int bit_number) {
+    shadow_GPIO = readRegister(GP0);
+    return  ((shadow_GPIO >> bit_number) & 0x0001);
+}
+
+/*-----------------------------------------------------------------------------
+ * read_mask
+ */
+int  MCP23016::read_mask(unsigned short mask) {
+    shadow_GPIO = readRegister(GP0);
+    return (shadow_GPIO & mask);
+}
+
+/*-----------------------------------------------------------------------------
+ * Config
+ * set direction and pull-up registers
+ */
+void MCP23016::config(unsigned short dir_config, unsigned short polarity_config) {
+    shadow_IODIR = dir_config;
+    writeRegister(IODIR0, (unsigned short)shadow_IODIR);
+    shadow_IPOL = polarity_config;
+    writeRegister(IPOL0, (unsigned short)shadow_IPOL);
+}
+
+/*-----------------------------------------------------------------------------
+ * writeRegister
+ * write a byte
+ */
+void MCP23016::writeRegister(int regAddress, unsigned char data) {
+    char  buffer[2];
+
+    buffer[0] = regAddress;
+    buffer[1] = data;
+    _i2c.write(MCP23016_i2cAddress, buffer, 2);
+}
+
+/*----------------------------------------------------------------------------
+ * write Register
+ * write two bytes
+ */ 
+void MCP23016::writeRegister(int regAddress, unsigned short data) {
+    char  buffer[3];
+
+    buffer[0] = regAddress;
+    tmp_data.value16 = data;
+    buffer[1] = tmp_data.value8[0];
+    buffer[2] = tmp_data.value8[1];
+
+    _i2c.write(MCP23016_i2cAddress, buffer, 3);
+}
+
+/*-----------------------------------------------------------------------------
+ * readRegister
+ */
+int MCP23016::readRegister(int regAddress) {
+    char buffer[2];
+
+    buffer[0] = regAddress;
+    _i2c.write(MCP23016_i2cAddress, buffer, 1);
+    _i2c.read(MCP23016_i2cAddress, buffer, 2);
+
+    return ((int)(buffer[0] + (buffer[1]<<8)));
+}
+
+/*-----------------------------------------------------------------------------
+ * pinMode
+ */
+void MCP23016::pinMode(int pin, int mode) {
+    if (mode == DIR_INPUT) {
+        shadow_IODIR |= 1 << pin;
+    } else {
+        shadow_IODIR &= ~(1 << pin);
+    }
+    writeRegister(IODIR0, (unsigned short)shadow_IODIR);
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalRead
+ */
+int MCP23016::digitalRead(int pin) {
+    shadow_GPIO = readRegister(GP0);
+    if ( shadow_GPIO & (1 << pin)) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWrite
+ */
+void MCP23016::digitalWrite(int pin, int val) {
+    // This will set the OUTPUT voltage
+    //as appropriate.
+    bool isOutput = !(shadow_IODIR & 1<<pin);
+
+    if (isOutput) {
+        //This is an output pin so just write the value
+        if (val) shadow_GPIO |= 1 << pin;
+        else shadow_GPIO &= ~(1 << pin);
+        writeRegister(OLAT0, (unsigned short)shadow_GPIO);
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWordRead
+ */
+unsigned short MCP23016::digitalWordRead() {
+    shadow_GPIO = readRegister(GP0);
+    return shadow_GPIO;
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWordWrite
+ */
+void MCP23016::digitalWordWrite(unsigned short w) {
+    shadow_GPIO = w;
+    writeRegister(OLAT0, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * inputPolarityMask
+ */
+void MCP23016::inputPolarityMask(unsigned short mask) {
+    writeRegister(IPOL0, mask);
+}
+
+/*-----------------------------------------------------------------------------
+ * inputoutputMask
+ */
+void MCP23016::inputOutputMask(unsigned short mask) {
+    shadow_IODIR = mask;
+    writeRegister(IODIR0, (unsigned short)shadow_IODIR);
+}
+
diff -r 000000000000 -r 133b7e09bbe7 MCP23016.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23016.h	Tue Jan 19 23:50:23 2016 +0000
@@ -0,0 +1,136 @@
+/*  MCP23016 library
+    Based on MCP23017 library for arduino by David Pye <davidmpye@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef     MBED_MCP23016_H
+#define     MBED_MCP23016_H
+
+#include    "mbed.h"
+
+#define GP0     0x00    // Access to GP0
+#define GP1     0x01    // Access to GP1
+#define OLAT0   0x02    // Access to OLAT0
+#define OLAT1   0x03    // Access to OLAT1
+#define IPOL0   0x04    // Access to IPOL0
+#define IPOL1   0x05    // Access to IPOL1
+#define IODIR0  0x06    // Access to IODIR0
+#define IODIR1  0x07    // Access to IODIR1
+#define INTCAP0 0x08    // Access to INTCAP0 (Read-Only)
+#define INTCAP1 0x09    // Access to INTCAP1 (Read-Only)
+#define IOCON0  0x0A    // Access to IOCON0
+#define IOCON1  0x0B    // Access to IOCON1
+
+#define     I2C_BASE_ADDRESS    0x40
+
+#define     DIR_OUTPUT      0
+#define     DIR_INPUT       1
+
+/** MCP23016 class
+ *
+ * Allow access to an I2C connected MCP23016 16-bit I/O extender chip
+ * Example:
+ * @code
+ *      MCP23016     *par_port; 
+ * @endcode
+ *
+ */
+class MCP23016 {
+public:
+    /** Constructor for the MCP23016 connected to specified I2C pins at a specific address
+     *
+     * 16-bit I/O expander with I2C interface
+     *
+     * @param   sda         I2C data pin
+     * @param   scl         I2C clock pin
+     * @param   i2cAddress  I2C address
+     */
+    MCP23016(PinName sda, PinName scl, int i2cAddress);
+
+    /** Reset MCP23016 device to its power-on state
+     */    
+    void reset(void);
+
+    /** Write a 0/1 value to an output bit
+     *
+     * @param   value         0 or 1
+     * @param   bit_number    bit number range 0 --> 15
+     */   
+    void write_bit(int value, int bit_number);
+      
+    /** Write a masked 16-bit value to the device
+     *
+     * @param   data    16-bit data value
+     * @param   mask    16-bit mask value
+     */       
+    void write_mask(unsigned short data, unsigned short mask);
+
+    /** Read a 0/1 value from an input bit
+     *
+     * @param   bit_number    bit number range 0 --> 15
+     * @return                0/1 value read
+     */       
+    int  read_bit(int bit_number);
+    
+    /** Read a 16-bit value from the device and apply mask
+     *
+     * @param   mask    16-bit mask value
+     * @return          16-bit data with mask applied
+     */     
+    int  read_mask(unsigned short mask);
+
+    /** Configure an MCP23016 device
+     *
+     * @param   dir_config         data direction value (1 = input, 0 = output)
+     * @param   polarity_config    polarity value (1 = flip, 0 = normal)
+     */           
+    void config(unsigned short dir_config, unsigned short polarity_config);
+
+    void writeRegister(int regAddress, unsigned char  val);
+    void writeRegister(int regAddress, unsigned short val);
+    int  readRegister(int regAddress);
+
+/*----------------------------------------------------------------------------- 
+ * pinmode
+ * Set units to sequential, bank0 mode
+ */  
+    void pinMode(int pin, int mode); 
+    void digitalWrite(int pin, int val);
+    int  digitalRead(int pin);
+
+// These provide a more advanced mapping of the chip functionality
+// See the data sheet for more information on what they do
+
+//Returns a word with the current pin states (ie contents of the GPIO register)
+    unsigned short digitalWordRead();
+// Allows you to write a word to the GPIO register
+    void digitalWordWrite(unsigned short w);
+// Sets up the polarity mask that the MCP23016 supports
+// if set to 1, it will flip the actual pin value.
+    void inputPolarityMask(unsigned short mask);
+//Sets which pins are inputs or outputs (1 = input, 0 = output) NB Opposite to arduino's
+//definition for these
+    void inputOutputMask(unsigned short mask);
+    int read(void);
+    void write(int data);
+
+protected:
+    I2C     _i2c;
+    int     MCP23016_i2cAddress;                        // physical I2C address
+    unsigned short   shadow_GPIO, shadow_IODIR, shadow_IPOL;     // Cached copies of the register values
+    
+};
+
+#endif
\ No newline at end of file