I have a MCP23S17 device and i need help making a very short code for setting up the IC. I only need 2 things from it. Set the port A and B into an Input, and read the state of port A and B
Please check if my code is correct:
#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 IODIRA 0x00 //direction register for PORTA
#define IODIRB 0x01 //direction register for PORTB
#define GPIOA 0x12 //status register for PORTA
#define GPIOB 0x13 //status register for PORTB
void setup() {
//initialize the SPI
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
//setup registers port A and B into intput
digitalWrite(9, LOW);
SPI.transfer(WR_CMD); //is this the correct sequence for PORTA?
SPI.transfer(IODIRA);
SPI.transfer(0xff);
SPI.transfer(WR_CMD); // do you have to do it one register at a time?
SPI.transfer(IODIRB);
SPI.transfer(0xff);
digitalWrite(_pinSS, HIGH);
//read PORTA
read16(GPIOA);
//read PORTB
read16(GPIOB);
}
uint16_t read16(uint8_t addr) {
uint16_t retval = 0;
digitalWrite(9, LOW);
SPI.transfer(RD_CMD);
SPI.transfer(addr);
retval |= SPI.transfer(0);
retval |= (uint16_t)(SPI.transfer(0) << 8);
digitalWrite(_pinSS, HIGH);
return retval;
}
Can you read portA and B in one spi transaction? or you really have to send the read command again
I should have just said "what happens when you try it?", thinking that I would just try it if I wa in my lab, not under the umbrella. And I happened to have an MCP23S17 lying around.
See section
3.2.1 BYTE MODE AND SEQUENTIAL MODE
it seems to indicate that put in the correct mode, you can read read read.
On the other hand, so what if you could not? If the several lines of code it takes is offensive in some way, just make your own function that hides that low level stuff.
Unless you are pressed for time, a good reason to want to boost efficiency wherever you c an.
Having briefly looked at the 23S17 datasheet, I think you can do this by:
Set IOCON.BANK=0 (interleaves the 2 sets of port registers)
Set IOCON.SEQOP=0 (enables auto address pointer incrementing)
Then I think you can do your SPI transaction by sending out the 23S17 device address (inc R/W bit), then the register address of GPIOA (=12), and then 2 additional SPI transfers that should return the values in GPIOA followed by GPIOB with the 23S17 auto incrementing the address pointer from 12 to 13.