MCP23S17 does not work with Mega2560

Hi all,

for my step sequencer project I will use 8 MCP23S17 SPI Port Expander to interface all the switches an LEDs. It operates with the Arduino UNO as exected and shown here: Hart gelötet!: Musik - Schritt für Schritt (Teil 2)

In my sketches I use the MCP23S17 Class von Cort Buffington: Arduino Playground - MCP23S17 Class for Arduino

Than I tried to do the same job with an Arduino Mega2560. Due to the other SPI-pins of the Mega (50...53) I build a new cable from my SPI-Board to the Arduino Mega. The cable is tested and it is ok. The Mega and the SPI-Board are powered up and the power levels are also ok.

But after uploading this test code:

#include <SPI.h>              
#include <MCP23S17.h>         

MCP inputchip(5);             
MCP outputchip(0);            

void setup() {
  for (int i = 1; i <= 16; i++) {    
    inputchip.pinMode(i, HIGH);      
    inputchip.pullupMode(i, HIGH);   
    inputchip.inputInvert(i, HIGH);  
    outputchip.pinMode(i, LOW);      
  }
}

void loop() {
  for (int i = 1; i <=16; i++) {       
    int value;                         
    value = inputchip.digitalRead(i);  
    outputchip.digitalWrite(i, value); 
    }
}

If I push a switch, the appropriate LED lights up, when I use the UNO. But with the Mega, no reaction.

After that I thought it was something wrong with the hardware an I double-checked the board an made some test with a single MCP23S17 on a breadboard. The result was the same: UNO works, Mega don't work. The SPI pins are working correctly, because a test with a MicroSD card breakout board was successful.

Any idea what 's going on there? Is there maybe a problem with the library?
A web research was unsuccessful. A lot of people used the MCP with the UNO but it seems no one used one with the Mega.

Any help appreciated. Thanks in advance.
Chris

Did you change this?

#define    SS            (10)          // SPI bus slave select output to pin 10 - READ ARDUINO SPI DOCS BEFORE CHANGING!!!

Or this:

// GENERIC BYTE WRITE - will write a byte to a register, arguments are register address and the value to write

void MCP::byteWrite(uint8_t reg, uint8_t value) {      // Accept the register and byte
  PORTB &= 0b11111011;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action
  SPI.transfer(OPCODEW | (_address << 1));             // Send the MCP23S17 opcode, chip address, and write bit
  SPI.transfer(reg);                                   // Send the register we want to write
  SPI.transfer(value);                                 // Send the byte
  PORTB |= 0b00000100;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
}

Port manipulation is always fraught when changing processors. That is almost certainly the problem.

I did some stuff with this port expander a while back (using I2C). Someone did an SPI version:

The code there may help.

Hi Nick,

thanks for the hint at:

PORTB &= 0b11111011; 
...
PORTB |= 0b00000100;

I didn't realize the impact of this code. Now I learned how to use it and I changed it to

PORTB &= 0b11111110; 
...
PORTB |= 0b00000001;

for Pin 53 which is Pin B0 at the ATmega2560.
The first entry you adives to I changed to

#define    SS            (53)

before, which didn't work without the other changes.
Now it is done and it works well.

Thanks a lot!
Chris