1

I'm trying to read from a handful of switches connected to a MCP23S17 port expander using pigpio, however I'm not getting any useful results. Whatever my switch values, I have 0 returned.

I've checked all voltages and triple-checked connections, and everything seems fine. A0, A1 and A2 are grounded, which I believe gives me an address of 0x20. I currently just have switches hooked up to GPB0-7.

The two commands below were obtained from looking at the data sheet (not exhaustively), and this answer for Arduino, so I'm not entirely confident I'm doing things right here.

#include <stdio.h>
#include <pigpio.h>

#define GPIOA   0x12
#define GPIOB   0x13
#define ADDRESS 0x20    // A0, A1 and A2 are low

#define CS    24
#define MISO  17
#define MOSI  27
#define SCLK  22
#define BAUD  10000
#define FLAGS 0

int main()
{
    unsigned char buffer[1];
    unsigned char command[3];

    gpioInitialise();
    bbSPIOpen(CS, MISO, MOSI, SCLK, BAUD, FLAGS);

    command[0] = (ADDRESS << 1 | 0x01);  // Read command
    command[1] = GPIOB;                  // Bank B  

    // I presume we need a final empty value so bbSPIXfer knows how much to send?
    command[2] = 0; 

    bbSPIXfer(CS, command, (char *)buffer, 1);

    printf("%d \n", buffer[0]);

    bbSPIClose(CS);
    gpioTerminate();
}
1
  • 1
    Have a look with piscope and check the signals are as expected. Personally I'd start the daemon (sudo pigpiod) and do initial tests with pigs.
    – joan
    Sep 27, 2021 at 9:04

1 Answer 1

0

After some fiddling with pigs and piscope (thanks @joan!), I found that the third byte in the response contained the value returned from the device, not the first.

Not sure if this is how the chip is supposed to behave or whether something else is configured wrong, but increasing the size of the buffer and using buffer[2] has worked for now.

For others wishing to read the MCP23S17 or MCP23007 using pigpio, here is my code which enables pull-up resistors on all GPIO pins and writes out the inverted binary values of both banks.

#include <stdio.h>
#include <pigpio.h>

// Default BANK = 0 sequential addressing

#define GPPUA   0x0C   // Pull up resistors, bank A
#define GPPUB   0x0D   // Pull up resistors, bank B
#define GPIOA   0x12   // GPIO bank A
#define GPIOB   0x13   // GPIO bank B
#define ADDRESS 0x00   // A0, A1 and A2 are low 

// Commands are of the form 0 1 0 0 A2 A1 A0 R/W
#define WRITE_COMMAND 0x40 | (ADDRESS << 1); 
#define READ_COMMAND  0x40 | (ADDRESS << 1) | 0x01;  

#define CS   24
#define MISO 16
#define MOSI 20
#define SCLK 21
#define BAUD 250000
#define FLAGS 0

void initialise();
void enablePullUp();

int main()
{
    unsigned char buffer[4];
    char command[4];

    initialise();
    enablePullUp();

    // Read from both banks
    command[0] = READ_COMMAND;
    command[1] = GPIOA;
    command[2] = GPIOB;
    command[3] = 0;

    bbSPIXfer(CS, command, (char *)buffer, sizeof(command)); 

    printf("GPIOA: %d\n", buffer[2]);
    printf("GPIOB: %d\n", buffer[3]);

    // Pin values are present in buffer[2] and buffer[3]. 
    // Store both banks in a single combined value.
    int combinedValue = (buffer[2] << 8) | buffer[3];

    // Convert to bits
    unsigned char values[16];
    for (int i = 0; i < 16; i++)
    {
        // Invert bit value for display so 1 is on
        values[i] = (combinedValue & (1 << i)) != 0 ? 0 : 1;
    }

    printf("Bits:  ");

    for (int i = 0; i < 16; i++)
    {
        printf("%d", values[i]);
    }
    printf("\n");

    bbSPIClose(CS);
    gpioTerminate();
}

void initialise() 
{
     // Use PWM for timing DMA transfers, as PCM is used for audio
    gpioCfgClock(5, 0, 0);

    gpioInitialise();
    bbSPIOpen(CS, MISO, MOSI, SCLK, BAUD, FLAGS);
}

/*
 * Enables pull-up resistors on all pins.
 */
void enablePullUp() 
{
    unsigned char buffer[4];
    char command[4]; 

    command[0] = WRITE_COMMAND;
    command[1] = GPPUA;
    command[2] = 0xFF;   // Enable on all GPIO pins
    command[3] = 0xFF;   // Sequential mode, write GPUUB

    bbSPIXfer(CS, command, (char *)buffer, sizeof(command)); 
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.