Basic library of routines to interface to a Microchip MCP23017 16-bit I/O expander using an I2C interface.

Dependents:   Assignment_2_herpe Final_V1 ass2 ass2 ... more

Committer:
jimherd
Date:
Sun Nov 28 21:10:15 2010 +0000
Revision:
2:2a17f52c550a
Parent:
0:a6a5d942b58f
Child:
4:32fd6ee97dff

        

Who changed what in which revision?

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