How to adress pins at the MCP23S17


I am trying to to controll a one-digit-display with the MCP23S17.
However, do I not really know how I can adress/ use the pins of the MCP23S17.

I am trying to build this:

And this is my Code so far to set up the SPI( not sure tho if it is correct)

#define F_CPU 16000000UL
#include <avr/io.h>
#include <SPI.h> 

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

int main(void)
  PORTB = (1<<2); // Pull-Up-Widerstand
  DDRB = (1<<2);
  DDRD |= (0<< DATAIN); //schalte Pin 12 auf Eingang
  DDRD |= (1<<SLAVESELECT) | (1<< SPICLOCK) | (1<<DATAOUT); //Pin 10,13, 11 werden auf Ausgang gesetzt
  SPI_CLOCK_DIV64;   //Takt 64


Let's say I want to use the pin GPA0 and have it as an Output. How would I do this?

Thanks so much!

It looks like you are not using any SPI library to the full extent possible, which proper use might mean you would be doing neither direct port manipulation nor worrying about some (obscure?) register.

OK, so SPDR isn’t obscure after all, but goes to show you - I’ve been using SPI and hadn’t needed to even know about the SPDR…

If you just want to transfer data between the Arduino and some SPI device, use the SPI library. See some simple SPI examples.

Also I just googled for you

mcp23s17 arduino

and there should be some things there to move you along. In particular there seems to be at least one library dedicated to handling the part you are using.

Also, look at the schematic and compare it to your code - the wiring doesn’t match the pin assignments.


You could try a basic framework like this:

#include <SPI.h>

const uint8_t
    pinRST = 9,     //reset
    pinSS = 10,     //slave select
    pinMOSI = 11,   //master out
    pinMISO = 12,   //master in
    pinCLK = 13;    //serial clock

//quick and dirty class for basic GPIO writing
class myPortExpander
    #define WR_CMD      0x40    //control byte, slave address 0, R/nW=0 (write)
    #define RD_CMD      0x41    //control byte, slave address 0, R/nW=1 (read)
    #define IODIR       0x00    //address of I/O direction register pair
    #define GPIO        0x12    //address of port data register pair

        uint8_t _pinSS;
        uint8_t _pinRST;
        void write16( uint8_t addr, uint16_t data )
            digitalWrite( _pinSS, LOW );
            SPI.transfer( WR_CMD );
            SPI.transfer( addr );
            SPI.transfer( (uint16_t)( data & 0xff ) );
            SPI.transfer( (uint16_t)( (data >> 8) & 0xff) );
            digitalWrite( _pinSS, HIGH);                                    

        uint16_t read16( uint8_t addr )
            uint16_t retval = 0;
            digitalWrite( _pinSS, LOW );
            SPI.transfer( RD_CMD );
            SPI.transfer( addr );            
            retval |= SPI.transfer(0);
            retval |= (uint16_t)(SPI.transfer(0) << 8);
            digitalWrite( _pinSS, HIGH );
            return retval;

        myPortExpander( uint8_t pinRST, uint8_t pinSS )
            _pinRST = pinRST;
            _pinSS = pinSS;        
        void begin( void )
            pinMode( _pinRST, OUTPUT );
            digitalWrite( _pinRST, LOW );
            pinMode( _pinSS, OUTPUT );          //out SS
            digitalWrite( _pinSS, HIGH );
            digitalWrite( 11, OUTPUT );         //MOSI
            digitalWrite( 12, INPUT_PULLUP );   //MISO
            digitalWrite( 13, OUTPUT );         //CLK

            delayMicroseconds( 100ul );
            digitalWrite( _pinRST, HIGH );                        
        void setGPIODir( uint16_t dir )
            write16( IODIR, dir );           

        void setGPIO( uint16_t val )
            write16( GPIO, val );           

//instance of class object myPortX(pander)
myPortExpander myPortX( pinRST, pinSS );

//patterns for the 7-seg display
    grSegments[] = 
        0b00111111, //0
        0b00000110, //1
        0b01011011, //2
        0b01001111, //3
        0b01100110, //4
        0b01101101, //5
        0b01111101, //6
        0b00000111, //7
        0b01111111, //8
        0b01101111  //9 

void setup()
        count = 0;

    //initialize the SPI with a slow ~1MHz clock
    SPI.beginTransaction( SPISettings( 1000000, MSBFIRST, SPI_MODE0 ) );

    //start our class thingy and set the GPIOs to outputs
    myPortX.setGPIODir(0xffff);     //all ports outputs    

    //once a second, send a new pattern to port A
    //should count from 0-9
    while( 1 )
        myPortX.setGPIO( (uint16_t)(grSegments[count++]) );         //if this doesn't light segs comment this line out...
        //myPortX.setGPIO( (uint16_t)(grSegments[count++] << 8) );  //...and try this one instead

        //bump count
        if( count == 10 )
            count = 0;

        //simple 1-sec delay between counts

void loop()

This compiles and generates promising signals on the SPI but I don't have your setup nor the port expander to test with so it may be worthless...

Also, you should really have 330R resistors on each segment pin, not on the CC side.

There is a library for using the MCP23S17 that may make things easier.

Documentation for the library.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.