Swordfish Module - MCP23S17 (SPI Shift Register)

After a recent discussion on the forum regarding shift registers, I thought I would share what I have done with the feedback from others.

MCP23S17

Whats a MCP23S17?

Its a 16-Bit I/O Expander with Serial Interface. In other words, it extends the number of logic I/O's available to a micro controller (handy for driving a large number of LEDs for example!).

A quick overview of features from the MCP23S17 Datasheet:

  • 16-bit remote bidirectional I/O port
    • I/O pins default to input
  • High-speed SPI interface (MCP23S17)
    • 10 MHz (max.)
  • Three hardware address pins to allow up to eight devices on the bus
  • Configurable interrupt output pins
    • Configurable as active-high, active-low or open-drain
    • Maximum output current sourced or sunk by any output pin ... 25mA
    • Maximum current out of VSS pin ... 150mA
    • Maximum current into VDD pin ... 125mA
  • Configurable interrupt source
    • Interrupt-on-change from configured register defaults or pin changes
  • Low standby current: 1 μA (max.)
  • Operating voltage:
    • 1.8V to 5.5V @ -40°C to +85°C

 

Limitations

Although the device is capable of driving +/-25mA on each pin, it is restricted to the maximum collective current as shown in the list above (~150mA). In terms of comparison with other devices I have found on the net, this "limitation" is of minor concern and trumps 95% of other shift registers.

The user module (linked further down) allows a combined update speed of ~17uS for all 16 outputs (~60Khz). Is this a limitation? In terms of functionality its a consideration, not a show stopper. Most persistence of vision projects with LOTS of LEDs need a refresh rate of ~25Hz (which is 2400% less then what these devices can deliver).

There can only be 8 different device addresses. This limits the total number of I/Os to 128 (8 * 16).

 

Pinout

MCP23S17_PINOUT_copy

 

Schematic (Multiple Devices)

MCP23S17_Schematic

(I was interested to see how much time it took to update all 32 outputs, hence the frequency meter. As it turns out, this happens
at ~30Khz with a PIC configured to run at 40Mhz)

 

Swordfish User Module

Can be downloaded here - User Module Pack (MCP23S17_MULT.bas)

 

Example Program

Before compiling the example programs - you will need to update SPI.bas as explained by Graham in this post (if you are using a PIC with SPI errata).

Here's a program that will increment a LongWord type variable and display each of the 4 bytes on a separate port - in an infinite loop.

Device = 18F2620
Clock = 40
Config OSC = HSPLL, MCLRE = Off
 
Include "mcp23s17_mult.bas"
 
Dim tmpLongWord As LongWord
 
Const mcp1 = %111, // First chip address
 mcp2 = %000 // Second chip address
 
MCP23S17_MULT.SetTrisPortA(mcp1,$00)
MCP23S17_MULT.SetTrisPortB(mcp1,$00)
 
MCP23S17_MULT.SetTrisPortA(mcp2,$00)
MCP23S17_MULT.SetTrisPortB(mcp2,$00)
 
Low(PORTB.0)
tmpLongWord = 0
 
While True
 tmpLongWord = tmpLongWord + 1
 MCP23S17_MULT.WritePortA(mcp1,tmpLongWord.byte0)
 MCP23S17_MULT.WritePortB(mcp1,tmpLongWord.byte1) 
 MCP23S17_MULT.WritePortA(mcp2,tmpLongWord.byte2)
 MCP23S17_MULT.WritePortB(mcp2,tmpLongWord.byte3)
 PORTB.0 = 1
 PORTB.0 = 0
Wend

 

Here's another example program that configures one port as all inputs (also enables internal pullup resistors), and the other port as all outputs. The output port will then mirror the input port.

Device = 18F2620
Clock = 40
Config OSC = HSPLL, MCLRE = Off
 
Include "mcp23s17_mult.bas"
 
 
Dim i1, i2 As Word
 
Const mcp1 = %000, // First chip address
 mcp2 = %111 // Second chip address
 
MCP23S17_MULT.SetTrisPortA(mcp1,0)
MCP23S17_MULT.SetTrisPortB(mcp1,$FF)
MCP23S17_MULT.SetPullUpsPortB(mcp1,$FF)
 
MCP23S17_MULT.SetTrisPortA(mcp2,0)
MCP23S17_MULT.SetTrisPortB(mcp2,$FF)
MCP23S17_MULT.SetPullUpsPortB(mcp2,$FF)
 
While true
 i1 = MCP23S17_MULT.ReadPortB(mcp1)
 MCP23S17_MULT.WritePortA(mcp1,i1)
 
 i2 = MCP23S17_MULT.ReadPortB(mcp2)
 MCP23S17_MULT.WritePortA(mcp2,i2)
Wend

 

Forum Activity

Member Access