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
MCP23017.cpp
00001 /* MCP23017 library for Arduino 00002 Copyright (C) 2009 David Pye <davidmpye@gmail.com 00003 Modified for use on the MBED ARM platform 00004 00005 This program is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include "MCP23017.h" 00020 #include "mbed.h" 00021 00022 union { 00023 uint8_t value8[2]; 00024 uint16_t value16; 00025 } tmp_data; 00026 00027 /*----------------------------------------------------------------------------- 00028 * 00029 */ 00030 MCP23017::MCP23017(PinName sda, PinName scl, int i2cAddress) : _i2c(sda, scl) { 00031 MCP23017_i2cAddress = i2cAddress; 00032 reset(); // initialise chip to power-on condition 00033 } 00034 00035 /*----------------------------------------------------------------------------- 00036 * reset 00037 * Set configuration (IOCON) and direction(IODIR) registers to initial state 00038 */ 00039 void MCP23017::reset() { 00040 // 00041 // First make sure that the device is in BANK=0 mode 00042 // 00043 writeRegister(0x05, (unsigned char)0x00); 00044 // 00045 // set direction registers to inputs 00046 // 00047 writeRegister(IODIR, (unsigned short)0xFFFF); 00048 // 00049 // set all other registers to zero (last of 10 registers is OLAT) 00050 // 00051 for (int reg_addr = 2 ; reg_addr <= OLAT ; reg_addr+=2) { 00052 writeRegister(reg_addr, (unsigned short)0x0000); 00053 } 00054 // 00055 // Set the shadow registers to power-on state 00056 // 00057 shadow_IODIR = 0xFFFF; 00058 shadow_GPIO = 0; 00059 shadow_GPPU = 0; 00060 shadow_IPOL = 0; 00061 } 00062 00063 /*----------------------------------------------------------------------------- 00064 * write_bit 00065 * Write a 1/0 to a single bit of the 16-bit port 00066 */ 00067 void MCP23017::write_bit(int value, int bit_number) { 00068 if (value == 0) { 00069 shadow_GPIO &= ~(1 << bit_number); 00070 } else { 00071 shadow_GPIO |= 1 << bit_number; 00072 } 00073 writeRegister(GPIO, (unsigned short)shadow_GPIO); 00074 } 00075 00076 /*----------------------------------------------------------------------------- 00077 * Write a combination of bits to the 16-bit port 00078 */ 00079 void MCP23017::write_mask(unsigned short data, unsigned short mask) { 00080 shadow_GPIO = (shadow_GPIO & ~mask) | data; 00081 writeRegister(GPIO, (unsigned short)shadow_GPIO); 00082 } 00083 00084 /*----------------------------------------------------------------------------- 00085 * read_bit 00086 * Read a single bit from the 16-bit port 00087 */ 00088 int MCP23017::read_bit(int bit_number) { 00089 shadow_GPIO = readRegister(GPIO); 00090 return ((shadow_GPIO >> bit_number) & 0x0001); 00091 } 00092 00093 /*----------------------------------------------------------------------------- 00094 * read_mask 00095 */ 00096 int MCP23017::read_mask(unsigned short mask) { 00097 shadow_GPIO = readRegister(GPIO); 00098 return (shadow_GPIO & mask); 00099 } 00100 00101 /*----------------------------------------------------------------------------- 00102 * Config 00103 * set direction and pull-up registers 00104 */ 00105 void MCP23017::config(unsigned short dir_config, unsigned short pullup_config, unsigned short polarity_config) { 00106 shadow_IODIR = dir_config; 00107 writeRegister(IODIR, (unsigned short)shadow_IODIR); 00108 shadow_GPPU = pullup_config; 00109 writeRegister(GPPU, (unsigned short)shadow_GPPU); 00110 shadow_IPOL = polarity_config; 00111 writeRegister(IPOL, (unsigned short)shadow_IPOL); 00112 } 00113 00114 /*----------------------------------------------------------------------------- 00115 * writeRegister 00116 * write a byte 00117 */ 00118 void MCP23017::writeRegister(int regAddress, unsigned char data) { 00119 char buffer[2]; 00120 00121 buffer[0] = regAddress; 00122 buffer[1] = data; 00123 _i2c.write(MCP23017_i2cAddress, buffer, 2); 00124 } 00125 00126 /*---------------------------------------------------------------------------- 00127 * write Register 00128 * write two bytes 00129 */ 00130 void MCP23017::writeRegister(int regAddress, unsigned short data) { 00131 char buffer[3]; 00132 00133 buffer[0] = regAddress; 00134 tmp_data.value16 = data; 00135 buffer[1] = tmp_data.value8[0]; 00136 buffer[2] = tmp_data.value8[1]; 00137 00138 _i2c.write(MCP23017_i2cAddress, buffer, 3); 00139 } 00140 00141 /*----------------------------------------------------------------------------- 00142 * readRegister 00143 */ 00144 int MCP23017::readRegister(int regAddress) { 00145 char buffer[2]; 00146 00147 buffer[0] = regAddress; 00148 _i2c.write(MCP23017_i2cAddress, buffer, 1); 00149 _i2c.read(MCP23017_i2cAddress, buffer, 2); 00150 00151 return ((int)(buffer[0] + (buffer[1]<<8))); 00152 } 00153 00154 /*----------------------------------------------------------------------------- 00155 * pinMode 00156 */ 00157 void MCP23017::pinMode(int pin, int mode) { 00158 if (DIR_INPUT) { 00159 shadow_IODIR |= 1 << pin; 00160 } else { 00161 shadow_IODIR &= ~(1 << pin); 00162 } 00163 writeRegister(IODIR, (unsigned short)shadow_IODIR); 00164 } 00165 00166 /*----------------------------------------------------------------------------- 00167 * digitalRead 00168 */ 00169 int MCP23017::digitalRead(int pin) { 00170 shadow_GPIO = readRegister(GPIO); 00171 if ( shadow_GPIO & (1 << pin)) { 00172 return 1; 00173 } else { 00174 return 0; 00175 } 00176 } 00177 00178 /*----------------------------------------------------------------------------- 00179 * digitalWrite 00180 */ 00181 void MCP23017::digitalWrite(int pin, int val) { 00182 //If this pin is an INPUT pin, a write here will 00183 //enable the internal pullup 00184 //otherwise, it will set the OUTPUT voltage 00185 //as appropriate. 00186 bool isOutput = !(shadow_IODIR & 1<<pin); 00187 00188 if (isOutput) { 00189 //This is an output pin so just write the value 00190 if (val) shadow_GPIO |= 1 << pin; 00191 else shadow_GPIO &= ~(1 << pin); 00192 writeRegister(GPIO, (unsigned short)shadow_GPIO); 00193 } else { 00194 //This is an input pin, so we need to enable the pullup 00195 if (val) { 00196 shadow_GPPU |= 1 << pin; 00197 } else { 00198 shadow_GPPU &= ~(1 << pin); 00199 } 00200 writeRegister(GPPU, (unsigned short)shadow_GPPU); 00201 } 00202 } 00203 00204 /*----------------------------------------------------------------------------- 00205 * digitalWordRead 00206 */ 00207 unsigned short MCP23017::digitalWordRead() { 00208 shadow_GPIO = readRegister(GPIO); 00209 return shadow_GPIO; 00210 } 00211 00212 /*----------------------------------------------------------------------------- 00213 * digitalWordWrite 00214 */ 00215 void MCP23017::digitalWordWrite(unsigned short w) { 00216 shadow_GPIO = w; 00217 writeRegister(GPIO, (unsigned short)shadow_GPIO); 00218 } 00219 00220 /*----------------------------------------------------------------------------- 00221 * inputPolarityMask 00222 */ 00223 void MCP23017::inputPolarityMask(unsigned short mask) { 00224 writeRegister(IPOL, mask); 00225 } 00226 00227 /*----------------------------------------------------------------------------- 00228 * inputoutputMask 00229 */ 00230 void MCP23017::inputOutputMask(unsigned short mask) { 00231 shadow_IODIR = mask; 00232 writeRegister(IODIR, (unsigned short)shadow_IODIR); 00233 } 00234 00235 /*----------------------------------------------------------------------------- 00236 * internalPullupMask 00237 */ 00238 void MCP23017::internalPullupMask(unsigned short mask) { 00239 shadow_GPPU = mask; 00240 writeRegister(GPPU, (unsigned short)shadow_GPPU); 00241 } 00242
Generated on Mon Jul 18 2022 21:09:52 by 1.7.2