How to adress pins at the MCP23S17

Hello!

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)
{
  Serial.begin(9600);
  
  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
  PORTD = (1<<SLAVESELECT);
  SPI.begin();
  SPI_CLOCK_DIV64;   //Takt 64
  SPI.attachInterrupt();

  while(1){
    
  }
}

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.

a7

You could try a basic framework like this:

#include <SPI.h>

//pins
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

    private:
        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);                                    
        
        }//write16

        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;
            
        }//read16

    public:
        myPortExpander( uint8_t pinRST, uint8_t pinSS )
        {
            _pinRST = pinRST;
            _pinSS = pinSS;        
                
        }//myPortExpander
    
        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 );                        
    
        }//begin
        
        void setGPIODir( uint16_t dir )
        {
            write16( IODIR, dir );           
            
        }//setGPIODir

        void setGPIO( uint16_t val )
        {
            write16( GPIO, val );           
            
        }//setGPIO        
    
};//myPortExpander

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

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

void setup()
{        
    uint8_t
        count = 0;
    uint16_t
        u16Tmp;

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

    //start our class thingy and set the GPIOs to outputs
    myPortX.begin();
    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
        delay(1000);
        
    }//while
    
}//setup

void loop()
{
}//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.