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
    }
}
Committer:
davidr99
Date:
Tue Jan 19 23:50:23 2016 +0000
Revision:
0:133b7e09bbe7
MCP23016 Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:133b7e09bbe7 1 /* MCP23016 library
davidr99 0:133b7e09bbe7 2 Based on MCP23017 library for arduino by David Pye <davidmpye@gmail.com>
davidr99 0:133b7e09bbe7 3
davidr99 0:133b7e09bbe7 4 This program is free software: you can redistribute it and/or modify
davidr99 0:133b7e09bbe7 5 it under the terms of the GNU General Public License as published by
davidr99 0:133b7e09bbe7 6 the Free Software Foundation, either version 3 of the License, or
davidr99 0:133b7e09bbe7 7 (at your option) any later version.
davidr99 0:133b7e09bbe7 8
davidr99 0:133b7e09bbe7 9 This program is distributed in the hope that it will be useful,
davidr99 0:133b7e09bbe7 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
davidr99 0:133b7e09bbe7 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
davidr99 0:133b7e09bbe7 12 GNU General Public License for more details.
davidr99 0:133b7e09bbe7 13
davidr99 0:133b7e09bbe7 14 You should have received a copy of the GNU General Public License
davidr99 0:133b7e09bbe7 15 along with this program. If not, see <http://www.gnu.org/licenses/>.
davidr99 0:133b7e09bbe7 16 */
davidr99 0:133b7e09bbe7 17
davidr99 0:133b7e09bbe7 18 #include "MCP23016.h"
davidr99 0:133b7e09bbe7 19 #include "mbed.h"
davidr99 0:133b7e09bbe7 20
davidr99 0:133b7e09bbe7 21 union {
davidr99 0:133b7e09bbe7 22 uint8_t value8[2];
davidr99 0:133b7e09bbe7 23 uint16_t value16;
davidr99 0:133b7e09bbe7 24 } tmp_data;
davidr99 0:133b7e09bbe7 25
davidr99 0:133b7e09bbe7 26 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 27 *
davidr99 0:133b7e09bbe7 28 */
davidr99 0:133b7e09bbe7 29 MCP23016::MCP23016(PinName sda, PinName scl, int i2cAddress) : _i2c(sda, scl) {
davidr99 0:133b7e09bbe7 30 MCP23016_i2cAddress = I2C_BASE_ADDRESS + i2cAddress;
davidr99 0:133b7e09bbe7 31 reset(); // initialise chip to power-on condition
davidr99 0:133b7e09bbe7 32 }
davidr99 0:133b7e09bbe7 33
davidr99 0:133b7e09bbe7 34 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 35 * reset
davidr99 0:133b7e09bbe7 36 * Set configuration (IOCON) and direction(IODIR) registers to initial state
davidr99 0:133b7e09bbe7 37 */
davidr99 0:133b7e09bbe7 38 void MCP23016::reset() {
davidr99 0:133b7e09bbe7 39 //
davidr99 0:133b7e09bbe7 40 // set direction registers to inputs
davidr99 0:133b7e09bbe7 41 //
davidr99 0:133b7e09bbe7 42 writeRegister(IODIR0, (unsigned short)0xFFFF);
davidr99 0:133b7e09bbe7 43 //
davidr99 0:133b7e09bbe7 44 // set all other registers to zero (last of 10 registers is OLAT)
davidr99 0:133b7e09bbe7 45 //
davidr99 0:133b7e09bbe7 46 for (int reg_addr = OLAT0 ; reg_addr <= IPOL1 ; reg_addr+=2) {
davidr99 0:133b7e09bbe7 47 writeRegister(reg_addr, (unsigned short)0x0000);
davidr99 0:133b7e09bbe7 48 }
davidr99 0:133b7e09bbe7 49 //
davidr99 0:133b7e09bbe7 50 // Set the shadow registers to power-on state
davidr99 0:133b7e09bbe7 51 //
davidr99 0:133b7e09bbe7 52 shadow_IODIR = 0xFFFF;
davidr99 0:133b7e09bbe7 53 shadow_GPIO = 0;
davidr99 0:133b7e09bbe7 54 shadow_IPOL = 0;
davidr99 0:133b7e09bbe7 55 }
davidr99 0:133b7e09bbe7 56
davidr99 0:133b7e09bbe7 57 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 58 * write_bit
davidr99 0:133b7e09bbe7 59 * Write a 1/0 to a single bit of the 16-bit port
davidr99 0:133b7e09bbe7 60 */
davidr99 0:133b7e09bbe7 61 void MCP23016::write_bit(int value, int bit_number) {
davidr99 0:133b7e09bbe7 62 if (value == 0) {
davidr99 0:133b7e09bbe7 63 shadow_GPIO &= ~(1 << bit_number);
davidr99 0:133b7e09bbe7 64 } else {
davidr99 0:133b7e09bbe7 65 shadow_GPIO |= 1 << bit_number;
davidr99 0:133b7e09bbe7 66 }
davidr99 0:133b7e09bbe7 67 writeRegister(OLAT0, (unsigned short)shadow_GPIO);
davidr99 0:133b7e09bbe7 68 }
davidr99 0:133b7e09bbe7 69
davidr99 0:133b7e09bbe7 70 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 71 * Write a combination of bits to the 16-bit port
davidr99 0:133b7e09bbe7 72 */
davidr99 0:133b7e09bbe7 73 void MCP23016::write_mask(unsigned short data, unsigned short mask) {
davidr99 0:133b7e09bbe7 74 shadow_GPIO = (shadow_GPIO & ~mask) | data;
davidr99 0:133b7e09bbe7 75 writeRegister(OLAT0, (unsigned short)shadow_GPIO);
davidr99 0:133b7e09bbe7 76 }
davidr99 0:133b7e09bbe7 77
davidr99 0:133b7e09bbe7 78 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 79 * read_bit
davidr99 0:133b7e09bbe7 80 * Read a single bit from the 16-bit port
davidr99 0:133b7e09bbe7 81 */
davidr99 0:133b7e09bbe7 82 int MCP23016::read_bit(int bit_number) {
davidr99 0:133b7e09bbe7 83 shadow_GPIO = readRegister(GP0);
davidr99 0:133b7e09bbe7 84 return ((shadow_GPIO >> bit_number) & 0x0001);
davidr99 0:133b7e09bbe7 85 }
davidr99 0:133b7e09bbe7 86
davidr99 0:133b7e09bbe7 87 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 88 * read_mask
davidr99 0:133b7e09bbe7 89 */
davidr99 0:133b7e09bbe7 90 int MCP23016::read_mask(unsigned short mask) {
davidr99 0:133b7e09bbe7 91 shadow_GPIO = readRegister(GP0);
davidr99 0:133b7e09bbe7 92 return (shadow_GPIO & mask);
davidr99 0:133b7e09bbe7 93 }
davidr99 0:133b7e09bbe7 94
davidr99 0:133b7e09bbe7 95 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 96 * Config
davidr99 0:133b7e09bbe7 97 * set direction and pull-up registers
davidr99 0:133b7e09bbe7 98 */
davidr99 0:133b7e09bbe7 99 void MCP23016::config(unsigned short dir_config, unsigned short polarity_config) {
davidr99 0:133b7e09bbe7 100 shadow_IODIR = dir_config;
davidr99 0:133b7e09bbe7 101 writeRegister(IODIR0, (unsigned short)shadow_IODIR);
davidr99 0:133b7e09bbe7 102 shadow_IPOL = polarity_config;
davidr99 0:133b7e09bbe7 103 writeRegister(IPOL0, (unsigned short)shadow_IPOL);
davidr99 0:133b7e09bbe7 104 }
davidr99 0:133b7e09bbe7 105
davidr99 0:133b7e09bbe7 106 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 107 * writeRegister
davidr99 0:133b7e09bbe7 108 * write a byte
davidr99 0:133b7e09bbe7 109 */
davidr99 0:133b7e09bbe7 110 void MCP23016::writeRegister(int regAddress, unsigned char data) {
davidr99 0:133b7e09bbe7 111 char buffer[2];
davidr99 0:133b7e09bbe7 112
davidr99 0:133b7e09bbe7 113 buffer[0] = regAddress;
davidr99 0:133b7e09bbe7 114 buffer[1] = data;
davidr99 0:133b7e09bbe7 115 _i2c.write(MCP23016_i2cAddress, buffer, 2);
davidr99 0:133b7e09bbe7 116 }
davidr99 0:133b7e09bbe7 117
davidr99 0:133b7e09bbe7 118 /*----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 119 * write Register
davidr99 0:133b7e09bbe7 120 * write two bytes
davidr99 0:133b7e09bbe7 121 */
davidr99 0:133b7e09bbe7 122 void MCP23016::writeRegister(int regAddress, unsigned short data) {
davidr99 0:133b7e09bbe7 123 char buffer[3];
davidr99 0:133b7e09bbe7 124
davidr99 0:133b7e09bbe7 125 buffer[0] = regAddress;
davidr99 0:133b7e09bbe7 126 tmp_data.value16 = data;
davidr99 0:133b7e09bbe7 127 buffer[1] = tmp_data.value8[0];
davidr99 0:133b7e09bbe7 128 buffer[2] = tmp_data.value8[1];
davidr99 0:133b7e09bbe7 129
davidr99 0:133b7e09bbe7 130 _i2c.write(MCP23016_i2cAddress, buffer, 3);
davidr99 0:133b7e09bbe7 131 }
davidr99 0:133b7e09bbe7 132
davidr99 0:133b7e09bbe7 133 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 134 * readRegister
davidr99 0:133b7e09bbe7 135 */
davidr99 0:133b7e09bbe7 136 int MCP23016::readRegister(int regAddress) {
davidr99 0:133b7e09bbe7 137 char buffer[2];
davidr99 0:133b7e09bbe7 138
davidr99 0:133b7e09bbe7 139 buffer[0] = regAddress;
davidr99 0:133b7e09bbe7 140 _i2c.write(MCP23016_i2cAddress, buffer, 1);
davidr99 0:133b7e09bbe7 141 _i2c.read(MCP23016_i2cAddress, buffer, 2);
davidr99 0:133b7e09bbe7 142
davidr99 0:133b7e09bbe7 143 return ((int)(buffer[0] + (buffer[1]<<8)));
davidr99 0:133b7e09bbe7 144 }
davidr99 0:133b7e09bbe7 145
davidr99 0:133b7e09bbe7 146 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 147 * pinMode
davidr99 0:133b7e09bbe7 148 */
davidr99 0:133b7e09bbe7 149 void MCP23016::pinMode(int pin, int mode) {
davidr99 0:133b7e09bbe7 150 if (mode == DIR_INPUT) {
davidr99 0:133b7e09bbe7 151 shadow_IODIR |= 1 << pin;
davidr99 0:133b7e09bbe7 152 } else {
davidr99 0:133b7e09bbe7 153 shadow_IODIR &= ~(1 << pin);
davidr99 0:133b7e09bbe7 154 }
davidr99 0:133b7e09bbe7 155 writeRegister(IODIR0, (unsigned short)shadow_IODIR);
davidr99 0:133b7e09bbe7 156 }
davidr99 0:133b7e09bbe7 157
davidr99 0:133b7e09bbe7 158 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 159 * digitalRead
davidr99 0:133b7e09bbe7 160 */
davidr99 0:133b7e09bbe7 161 int MCP23016::digitalRead(int pin) {
davidr99 0:133b7e09bbe7 162 shadow_GPIO = readRegister(GP0);
davidr99 0:133b7e09bbe7 163 if ( shadow_GPIO & (1 << pin)) {
davidr99 0:133b7e09bbe7 164 return 1;
davidr99 0:133b7e09bbe7 165 } else {
davidr99 0:133b7e09bbe7 166 return 0;
davidr99 0:133b7e09bbe7 167 }
davidr99 0:133b7e09bbe7 168 }
davidr99 0:133b7e09bbe7 169
davidr99 0:133b7e09bbe7 170 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 171 * digitalWrite
davidr99 0:133b7e09bbe7 172 */
davidr99 0:133b7e09bbe7 173 void MCP23016::digitalWrite(int pin, int val) {
davidr99 0:133b7e09bbe7 174 // This will set the OUTPUT voltage
davidr99 0:133b7e09bbe7 175 //as appropriate.
davidr99 0:133b7e09bbe7 176 bool isOutput = !(shadow_IODIR & 1<<pin);
davidr99 0:133b7e09bbe7 177
davidr99 0:133b7e09bbe7 178 if (isOutput) {
davidr99 0:133b7e09bbe7 179 //This is an output pin so just write the value
davidr99 0:133b7e09bbe7 180 if (val) shadow_GPIO |= 1 << pin;
davidr99 0:133b7e09bbe7 181 else shadow_GPIO &= ~(1 << pin);
davidr99 0:133b7e09bbe7 182 writeRegister(OLAT0, (unsigned short)shadow_GPIO);
davidr99 0:133b7e09bbe7 183 }
davidr99 0:133b7e09bbe7 184 }
davidr99 0:133b7e09bbe7 185
davidr99 0:133b7e09bbe7 186 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 187 * digitalWordRead
davidr99 0:133b7e09bbe7 188 */
davidr99 0:133b7e09bbe7 189 unsigned short MCP23016::digitalWordRead() {
davidr99 0:133b7e09bbe7 190 shadow_GPIO = readRegister(GP0);
davidr99 0:133b7e09bbe7 191 return shadow_GPIO;
davidr99 0:133b7e09bbe7 192 }
davidr99 0:133b7e09bbe7 193
davidr99 0:133b7e09bbe7 194 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 195 * digitalWordWrite
davidr99 0:133b7e09bbe7 196 */
davidr99 0:133b7e09bbe7 197 void MCP23016::digitalWordWrite(unsigned short w) {
davidr99 0:133b7e09bbe7 198 shadow_GPIO = w;
davidr99 0:133b7e09bbe7 199 writeRegister(OLAT0, (unsigned short)shadow_GPIO);
davidr99 0:133b7e09bbe7 200 }
davidr99 0:133b7e09bbe7 201
davidr99 0:133b7e09bbe7 202 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 203 * inputPolarityMask
davidr99 0:133b7e09bbe7 204 */
davidr99 0:133b7e09bbe7 205 void MCP23016::inputPolarityMask(unsigned short mask) {
davidr99 0:133b7e09bbe7 206 writeRegister(IPOL0, mask);
davidr99 0:133b7e09bbe7 207 }
davidr99 0:133b7e09bbe7 208
davidr99 0:133b7e09bbe7 209 /*-----------------------------------------------------------------------------
davidr99 0:133b7e09bbe7 210 * inputoutputMask
davidr99 0:133b7e09bbe7 211 */
davidr99 0:133b7e09bbe7 212 void MCP23016::inputOutputMask(unsigned short mask) {
davidr99 0:133b7e09bbe7 213 shadow_IODIR = mask;
davidr99 0:133b7e09bbe7 214 writeRegister(IODIR0, (unsigned short)shadow_IODIR);
davidr99 0:133b7e09bbe7 215 }
davidr99 0:133b7e09bbe7 216