Arduino: MCP23008 Library

Introduction

 

MCP23008 Image

Ever needed a few extra I/O points or need to dedicate some I/O to a peripheral like an LCD or 7 segment LED?  Try the MCP23008.  The MCP23008 is an 8-bit general purpose I/O expansion chip controlled via a I2C interface.  Each of the 8 I/O point can be configured as inputs or outputs.  Inputs can be configured to use weak pull-up resistors or trigger an interrupt on change of state based on how the MCP23008 registers are setup.  The following details an Arduino driver for the MCP23008.  A simple test circuit and example program demonstrate the use of the driver.

 

Pinout

MCP23008 Pinout

 
Pins 1 &2   I2C interface
Pins 3-5   Device address
Pin 6   Device reset (Active low)
Pin 7   Not Used
Pin 8   Interrupt Pin (Indicates interrupt)
Pin 9   Vss (Ground)
Pins 10-17   I/O Pins GP0 – SP7
Pin 18   Vdd (Power)

 

 

 

 

 

 

 

 

 

Test Circuit Schematic Diagram

 

Below is the test circuit that was used to test the MCP23008 driver.  GP0 – GP3 are configured as outputs to drive the LEDs.  GP4 – GP7 are configured as inputs and the MCP23008 internal pull-up resisters are enabled.  The INT pin is has been left disconnected in this circuit.  Address pins have all been tied to ground.  The SDA and SCL pins must have pull-up resistors.  4.7k ohms resisters are typical.

 Test Schematic

 

Program

 

The test program below reads the inputs on GPo – GP3 and then writes the status to the output on GP4 – GP7 every 100 milliseconds.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include 
#include 
 
#define MCP23008_ADDR 0x40
 
MCP23008 MyMCP(MCP23008_ADDR);
 
uint8_t  MyVal = 0;
 
void setup()
{
  Wire.begin();
 
  MyMCP.writeIODIR(0x0F);       // 0-3 Inputs; 4-7 Outputs
  MyMCP.writeGPPU(0x0F);        // Enable pullups on 0-3
  MyMCP.writeGPIO(0xF0);        // Write 0 to GPIO
}
 
void loop()
{
 
  MyVal = MyMCP.readGPIO();     // Read inputs
  MyMCP.writeGPIO(MyVal << 4);  // Write inputs to outputs
  delay(100);                   // Wait 1/10th second and repeat
 
}

 

MCP23008 Driver

 

A description of the driver functions are shown below along with the header and class file for the driver.  The driver is available for download at the bottom of the page.  I would recommend downloading the file instead of copying the below as WordPress sometimes corrupts some of the code.

 

Functions

MCP23008(uint8_t addr) Class constructor
void writeIODIR(uint8_t cIODIR) Write IODIR register
void writeIPOL(uint8_t cIPOL) Write IPOL register
void writeGPINTEN(uint8_t cGPINTEN) Write GPINTEN register
void writeDEFVAL(uint8_t cDEFVAL) Write DEFVAL register
void writeGPPU(uint8_t cGPPU) Write GPPU register
void writeGPIO(uint8_t cGPIO) Write GPIO register
void writeOLAT(uint8_t cOLAT) Write OLAT register
uint8_t readIODIR() Read IODIR register
uint8_t readIPOL() Read IPOL register
uint8_t readGPINTEN() Read GPINTEN register
uint8_t readDEFVAL() Read DEFVAL register
uint8_t readGPPU() Read GPPU register
uint8_t readINTF() Read INTF register
uint8_t readINTCAP() Read INTCAP register
uint8_t readGPIO() Read GPIO register
uint8_t readOLAT() Read OLAT register

 

Header File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// MCP23008.h
//------------------------------------------------------------------------------
// Library for communicating with MCP23008 8-bit port expander.
// Created by Garrett Blanton January, 24, 2014.
// Released into the public domain.
 
#ifndef MCP23008_h
#define MCP23008_h
 
#include "Arduino.h"
 
#define regIODIR      0x00         // IO Direction Register
#define regIPOL       0x01         // Input Polarity Register
#define regGPINTEN    0x02         // Interrupt-On-Change Register
#define regDEFVAL     0x03         // Default Value Register
#define regINTCON     0x04         // Interrupt Control Register
#define regIOCON      0x05         // Configuration Register
#define regGPPU       0x06         // Pull-up Register
#define regINTF       0x07         // Interrupt Flag Register
#define regINTCAP     0x08         // Interrupt Captured Value Register
#define regGPIO       0x09         // General Purpose IO Register
#define regOLAT       0x0A         // Output Latch Register
 
class MCP23008
{
  public:
 
	MCP23008(uint8_t addr);			// Class constructor
 
	void writeIODIR(uint8_t cIODIR);	// Write IODIR register
	void writeIPOL(uint8_t cIPOL);		// Write IPOL register
	void writeGPINTEN(uint8_t cOLINTEN);	// Write GPINTEN register
	void writeDEFVAL(uint8_t cDEFVAL);	// Write DEFVAL register
	void writeINTCON(uint8_t cINTCON);	// Write INTCON register
	void writeIOCON(uint8_t cIOCON);	// Write IOCON register
	void writeGPPU(uint8_t cOLPU);		// Write GPPU register
	void writeGPIO(uint8_t cOLIO);		// Write GPIO register
	void writeOLAT(uint8_t cOLAT);		// Write OLAT register
 
	uint8_t readIODIR();			// Read IODIR register
	uint8_t readIPOL();			// Read IPOL register
	uint8_t readGPINTEN();			// Read GPINTEN register
	uint8_t readDEFVAL();			// Read DEFVAL register
	uint8_t readGPPU();			// Read GPPU register
	uint8_t readINTCON();			// Read INTCON register
	uint8_t readIOCON();			// Read IOCON register
	uint8_t readINTF();			// Read INTF register
	uint8_t readINTCAP();			// Read INTCAP register
	uint8_t readGPIO();			// Read GPIO register
	uint8_t readOLAT();			// Read OLAT register
 
  private:
 
	void writebyte(uint8_t Address, uint8_t Register, uint8_t Value);	// Writes byte to MCP23008
	uint8_t readbyte(uint8_t Address, uint8_t Register);			// Reads byte from MCP23008
 
	uint8_t _ADDR;				// MCP23008 Address : 0b0100xxx0
};
 
#endif

 

Class File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
// MCP23008.cpp
//------------------------------------------------------------------------------
// Library for communicating with MCP23008  8-bit port expander.
// Created by Garrett Blanton January, 24, 2013.
// Released into the public domain.
//
// Functions
//------------------------------------------------------------------------------
//	MCP23008(uint8_t addr);			// Class constructor
//	void writeIODIR(uint8_t cIODIR);	// Write IODIR register
//	void writeIPOL(uint8_t cIPOL);		// Write IPOL register
//	void writeGPINTEN(uint8_t cGPINTEN);	// Write GPINTEN register
//	void writeDEFVAL(uint8_t cDEFVAL);	// Write DEFVAL register
//	void writeGPPU(uint8_t cGPPU);		// Write GPPU register
//	void writeGPIO(uint8_t cGPIO);		// Write GPIO register
//	void writeOLAT(uint8_t cOLAT);		// Write OLAT register
//	uint8_t readIODIR();			// Read IODIR register
//	uint8_t readIPOL();			// Read IPOL register
//	uint8_t readGPINTEN();			// Read GPINTEN register
//	uint8_t readDEFVAL();			// Read DEFVAL register
//	uint8_t readGPPU();			// Read GPPU register
//	uint8_t readINTF();			// Read INTF register
//	uint8_t readINTCAP();			// Read INTCAP register
//	uint8_t readGPIO();			// Read GPIO register
//	uint8_t readOLAT();			// Read OLAT register
//
//	void writebyte(uint8_t Address, uint8_t Register, uint8_t Value);
//	uint8_t readbyte(uint8_t Address, uint8_t Register);
 
#include "Arduino.h"
#include "Wire.h"
#include "MCP23008.h"
 
MCP23008::MCP23008(byte addr)
{
  _ADDR = addr >> 1;
}
 
// writebyte
//------------------------------------------------------------------------------
// Writes a single byte of data to the specified MCP23008 register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// Address	MCP23008 Address
// Register	MCP23008 Register to write
// Value	Value to write to register
//
// Registers
//------------------------------------------------------------------------------
// regIODIR      0x00	IO Direction Register
// regIPOL       0x01   Input Polarity Register
// regGPINTEN    0x02   Interrupt-On-Change Register
// regDEFVAL     0x03   Default Value Register
// regINTCON     0x04   Interrupt Control Register
// regIOCON      0x05   Configuration Register
// regGPPU       0x06   Pull-up Register
// regINTF       0x07   Interrupt Flag Register
// regINTCAP     0x08   Interrupt Captured Value Register
// regGPIO       0x09   General Purpose IO Register
// regOLAT       0x0A   Output Latch Register
 
void MCP23008::writebyte(uint8_t Address, uint8_t Register, uint8_t Value)
{
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.write(Value);
  Wire.endTransmission();
}
 
// readbyte
//------------------------------------------------------------------------------
// Reads a single byte of data from the specified MCP23008 register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// Address	MCP23008 Address
// Register	MCP23008 Register to write
// return	Value read from register
//
// Registers
//------------------------------------------------------------------------------
// regIODIR      0x00	IO Direction Register
// regIPOL       0x01   Input Polarity Register
// regGPINTEN    0x02   Interrupt-On-Change Register
// regDEFVAL     0x03   Default Value Register
// regINTCON     0x04   Interrupt Control Register
// regIOCON      0x05   Configuration Register
// regGPPU       0x06   Pull-up Register
// regINTF       0x07   Interrupt Flag Register
// regINTCAP     0x08   Interrupt Captured Value Register
// regGPIO       0x09   General Purpose IO Register
// regOLAT       0x0A   Output Latch Register
 
uint8_t MCP23008::readbyte(uint8_t Address, uint8_t Register)
{
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.endTransmission();
  Wire.requestFrom((char)Address,1);
  Wire.available();
  return Wire.read();
}
 
// writeIODIR
//------------------------------------------------------------------------------
// Writes to the MCP23008 IODIR register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cIODIR	Data direction value (0=output; 1=input)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		IO7 |IO6 |IO5 |IO4 |IO3 |IO2 |IO1 |IO0
 
void MCP23008::writeIODIR(uint8_t cIODIR)
{
  writebyte(_ADDR, regIODIR, cIODIR);
}
 
// writeIPOL
//------------------------------------------------------------------------------
// Writes to the MCP23008 IPOL register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cIPOL	Input Polarity Register (0=Direct; 1=Opposite)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		IP7 |IP6 |IP5 |IP4 |IP3 |IP2 |IP1 |IP0
 
void MCP23008::writeIPOL(uint8_t cIPOL)
{
  writebyte(_ADDR, regIPOL, cIPOL);
}
 
// writeGPINTEN
//------------------------------------------------------------------------------
// Writes to the MCP23008 GPINTEN register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPINTEN	Interrupt-On-Change Control Register (0=Disable; 1=Enable)
//
//		BIT7  |BIT6  |BIT5  |BIT4  |BIT3  |BIT2  |BIT1  |BIT0
//		GPINT7|GPINT6|GPINT5|GPINT4|GPINT3|GPINT2|GPINT1|GPINT0
 
void MCP23008::writeGPINTEN(uint8_t cGPINTEN)
{
  writebyte(_ADDR, regGPINTEN, cGPINTEN);
}
 
// writeDEFVAL
//------------------------------------------------------------------------------
// Writes to the MCP23008 DEFVAL register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cDEFVAL	Default Compare Register For Interrupt-On-Change (GPINT!=DEF)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		DEF7|DEF6|DEF5|DEF4|DEF3|DEF2|DEF1|DEF0
 
void MCP23008::writeDEFVAL(uint8_t cDEFVAL)
{
  writebyte(_ADDR, regDEFVAL, cDEFVAL);
}
 
// writeINTCON
//------------------------------------------------------------------------------
// Writes to the MCP23008 INTCON register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cINTCON	Interrupt Control Register (0=Compare Previous Pin; 1=DEFVAL)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		IOC7|IOC6|IOC5|IOC4|IOC3|IOC2|IOC1|IOC0
 
void MCP23008::writeINTCON(uint8_t cINTCON)
{
  writebyte(_ADDR, regINTCON, cINTCON);
}
 
// writeIOCON
//------------------------------------------------------------------------------
// Writes to the MCP23008 IOCON register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cIOCON	Configuration Register
//
//		Bit5	0=Sequential Operation Enabled;
//			1=Sequential Operation Disabled
//		Bit4	0=Slew rate enabled
//			1=Slew rate disabled
//		Bit2	0=Open-drain output
//			1=Active driver output
//		Bit1	0=INT output active low
//			1=INT output active high
 
void MCP23008::writeIOCON(uint8_t cIOCON)
{
  writebyte(_ADDR, regIOCON, cIOCON);
}
 
// writeGPPU
//------------------------------------------------------------------------------
// Writes to the MCP23008 GPPU register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPPU	Pull-up resister configuration (0=Disabled; 1=Enabled)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		PU7 |PU6 |PU5 |PU4 |PU3 |PU2 |PU1 |PU0  
 
void MCP23008::writeGPPU(uint8_t cGPPU)
{
  writebyte(_ADDR, regGPPU, cGPPU);
}
 
// writeGPIO
//------------------------------------------------------------------------------
// Writes to the MCP23008 GPIO register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPIO	Port Register (0=Logic Low; 1=Logic High)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0  
 
void MCP23008::writeGPIO(uint8_t cGPIO)
{
  writebyte(_ADDR, regGPIO, cGPIO);
}
 
// writeOLAT
//------------------------------------------------------------------------------
// Writes to the MCP23008 OLAT register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPIO	Output Latch Register (0=Logic Low; 1=Logic High)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		OL7 |OL6 |OL5 |OL4 |OL3 |OL2 |OL1 |OL0  
 
void MCP23008::writeOLAT(uint8_t cOLAT)
{
  writebyte(_ADDR, regOLAT, cOLAT);
}
 
// readIODIR
//------------------------------------------------------------------------------
// Reads from the MCP23008 IODIR register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Data direction value (0=output; 1=input)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0  
 
uint8_t MCP23008::readIODIR()
{
  return readbyte(_ADDR, regIODIR);
}
 
// readIPOL
//------------------------------------------------------------------------------
// Reads from the MCP23008 IPOL register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Input Polarity Register (0=Direct; 1=Opposite)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		IP7 |IP6 |IP5 |IP4 |IP3 |IP2 |IP1 |IP0
 
uint8_t MCP23008::readIPOL()
{
  return readbyte(_ADDR, regIPOL);
}
 
// readGPINTEN
//------------------------------------------------------------------------------
// Reads from the MCP23008 GPINTEN register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Interrupt-On-Change Control Register (0=Disable; 1=Enable)
//
//		BIT7  |BIT6  |BIT5  |BIT4  |BIT3  |BIT2  |BIT1  |BIT0
//		GPINT7|GPINT6|GPINT5|GPINT4|GPINT3|GPINT2|GPINT1|GPINT0
 
uint8_t MCP23008::readGPINTEN()
{
  return readbyte(_ADDR, regGPINTEN);
}
 
// readDEFVAL
//------------------------------------------------------------------------------
// Reads from the MCP23008 DEFVAL register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Default Compare Register For Interrupt-On-Change (GPINT!=DEF)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		DEF7|DEF6|DEF5|DEF4|DEF3|DEF2|DEF1|DEF0
 
uint8_t MCP23008::readDEFVAL()
{
  return readbyte(_ADDR, regDEFVAL);
}
 
// readINTCON
//------------------------------------------------------------------------------
// Reads from the MCP23008 INTCON register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Interrupt Control Register (0=Compare Previous Pin; 1=DEFVAL)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		IOC7|IOC6|IOC5|IOC4|IOC3|IOC2|IOC1|IOC0
 
uint8_t MCP23008::readINTCON()
{
  return readbyte(_ADDR, regINTCON);
}
 
// readIOCON
//------------------------------------------------------------------------------
// Reads from the MCP23008 IOCON register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Configuration Register
//
//		Bit5	0=Sequential Operation Enabled;
//			1=Sequential Operation Disabled
//		Bit4	0=Slew rate enabled
//			1=Slew rate disabled
//		Bit2	0=Open-drain output
//			1=Active driver output
//		Bit1	0=INT output active low
//			1=INT output active high
 
uint8_t MCP23008::readIOCON()
{
  return readbyte(_ADDR, regIOCON);
}
 
// readGPPU
//------------------------------------------------------------------------------
// Reads from the MCP23008 GPPU register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Pull-up resister configuration (0=Disabled; 1=Enabled)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		PU7 |PU6 |PU5 |PU4 |PU3 |PU2 |PU1 |PU0  
 
uint8_t MCP23008::readGPPU()
{
  return readbyte(_ADDR, regGPPU);
}
 
// readINTF
//------------------------------------------------------------------------------
// Reads from the MCP23008 INTF register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Interrupt Flag Register (0=No Interrupt; 1=Caused Interrupt)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		INT7|INT6|INT5|INT4|INT3|INT2|INT1|INT0  
 
uint8_t MCP23008::readINTF()
{
  return readbyte(_ADDR, regINTF);
}
 
// readINTCAP
//------------------------------------------------------------------------------
// Reads from the MCP23008 INTCAP register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// return	Interrupt Capture Register (0=Logic Low; 1=Logic High)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		INT7|INT6|INT5|INT4|INT3|INT2|INT1|INT0  
 
uint8_t MCP23008::readINTCAP()
{
  return readbyte(_ADDR, regINTCAP);
}
 
// readGPIO
//------------------------------------------------------------------------------
// Reads from the MCP23008 GPIO register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPIO	Port Register (0=Logic Low; 1=Logic High)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		GP7 |GP6 |GP5 |GP4 |GP3 |GP2 |GP1 |GP0
 
uint8_t MCP23008::readGPIO()
{
  return readbyte(_ADDR, regGPIO);
}
 
// readOLAT
//------------------------------------------------------------------------------
// Reads from the MCP23008 OLAT register.
//
// Parameter	Description
//------------------------------------------------------------------------------
// cGPIO	Output Latch Register (0=Logic Low; 1=Logic High)
//
//		BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0
//		OL7 |OL6 |OL5 |OL4 |OL3 |OL2 |OL1 |OL0  
 
uint8_t MCP23008::readOLAT()
{
  return readbyte(_ADDR, regOLAT);
}

 

Driver Download

 

Arduino MCP23008 Driver

 

 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>