Hi all,
I am trying interface MCP23S17 with RPI using SPI, i want to lit the LEDs connected to port A of MCP23S17.
I am using the following C Code.
C Code for SPI interface with MCP23S17:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
/* change CMD_WRITE and CMD_READ addrs to match MCP23S17 address */
#define CMD_WRITE 0x40
#define CMD_READ 0x41
static char *spiDevice = "/dev/spidev0.0" ;
static uint8_t spiMode = 0 ;
static uint8_t spiBPW = 8 ;
static uint32_t spiSpeed = 5000000 ;
static uint16_t spiDelay = 0;
/* all of the MCP23S17 Registers */
#define IOCON 0x0A
#define IODIRA 0x00
#define IPOLA 0x02
#define GPINTENA 0x04
#define DEFVALA 0x06
#define INTCONA 0x08
#define GPPUA 0x0C
#define INTFA 0x0E
#define INTCAPA 0x10
#define GPIOA 0x12
#define OLATA 0x14
#define IODIRB 0x01
#define IPOLB 0x03
#define GPINTENB 0x05
#define DEFVALB 0x07
#define INTCONB 0x09
#define GPPUB 0x0D
#define INTFB 0x0F
#define INTCAPB 0x11
#define GPIOB 0x13
#define OLATB 0x15
int spi_fd;
static void writeByte (uint8_t reg, uint8_t data)
{
uint8_t spiBufTx [3] ;
uint8_t spiBufRx [3] ;
struct spi_ioc_transfer spi ;
spiBufTx [0] = CMD_WRITE ;
spiBufTx [1] = reg ;
spiBufTx [2] = data ;
spi.tx_buf = (unsigned long)spiBufTx ;
spi.rx_buf = (unsigned long)spiBufRx ;
spi.len = 3 ;
spi.delay_usecs = spiDelay ;
spi.speed_hz = spiSpeed ;
spi.bits_per_word = spiBPW ;
ioctl (spi_fd, SPI_IOC_MESSAGE(1), &spi) ;
}
/*spi_open
* - Open the given SPI channel and configures it.
* - there are normally two SPI devices on your PI:
* /dev/spidev0.0: activates the CS0 pin during transfer
* /dev/spidev0.1: activates the CS1 pin during transfer
*
*/
int spi_open(char* dev)
{
if((spi_fd = open(dev, O_RDWR)) < 0){
printf("error opening %s\n",dev);
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
unsigned char data = 0xAF;
if(argc <= 1){
argv[1]=spiDevice;
}
// open and configure SPI channel. (/dev/spidev0.0 for example)
if(spi_open(argv[1]) < 0){
printf("spi_open failed\n");
return -1;
}
else
{
printf("device: %s\n", spiDevice);
}
writeByte (0X0A, 0x80) ; // enable MCP23S17 addresses
writeByte (0X00, 0x00) ; // Set Port A -> Outputs
writeByte (0X14, 0xFF) ; // turn PORT A outputs "on"
close(spi_fd);
return 0;
}
After running this code no LED connected to port A is turn on.
I am not understanding, where i am going wrong ?
Any help will be appreciated.
Re: SPI communication with MCP23S17 not working
Hello,
for readability, you should use the defines made early in the code:
writeByte (0X0A, 0x80) ; // enable MCP23S17 addresses
writeByte (0X00, 0x00) ; // Set Port A -> Outputs
writeByte (0X14, 0xFF) ; // turn PORT A outputs "on"
goes to
writeByte (IOCON , 0x80) ; // enable MCP23S17 addresses
writeByte (IODIRA, 0x00) ; // Set Port A -> Outputs
writeByte (OLATA, 0xFF) ; // turn PORT A outputs "on"
The problem is the IOCON write where you set the bank flag to 1, but your addresses are for bank flag 0. Try writing a bank flag 0, so the commands go for
writeByte (IOCON , 0x00) ; // Bank 0
Hope this helps,
Gerhard
for readability, you should use the defines made early in the code:
writeByte (0X0A, 0x80) ; // enable MCP23S17 addresses
writeByte (0X00, 0x00) ; // Set Port A -> Outputs
writeByte (0X14, 0xFF) ; // turn PORT A outputs "on"
goes to
writeByte (IOCON , 0x80) ; // enable MCP23S17 addresses
writeByte (IODIRA, 0x00) ; // Set Port A -> Outputs
writeByte (OLATA, 0xFF) ; // turn PORT A outputs "on"
The problem is the IOCON write where you set the bank flag to 1, but your addresses are for bank flag 0. Try writing a bank flag 0, so the commands go for
writeByte (IOCON , 0x00) ; // Bank 0
Hope this helps,
Gerhard
Re: SPI communication with MCP23S17 not working
Thanks for the reply.
I have done the following modification in the code
writeByte (IOCON , 0x00) ; // Bank 0
After still, i am not able to get the LEDs turn on.
I am using Raspberry Pi 2 and the spi module is spi_bcm2835.
Is there any other way to get it working?
I have done the following modification in the code
writeByte (IOCON , 0x00) ; // Bank 0
After still, i am not able to get the LEDs turn on.
I am using Raspberry Pi 2 and the spi module is spi_bcm2835.
Is there any other way to get it working?
- DougieLawson
- Posts: 42481
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
Re: SPI communication with MCP23S17 not working
Changeto
Code: Select all
struct spi_ioc_transfer spi;
Code: Select all
struct spi_ioc_transfer spi;
memset (&spi, 0, sizeof(spi));
Languages using left-hand whitespace for syntax are ridiculous
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
Re: SPI communication with MCP23S17 not working
Hello,
difficult to do remote debugging
- check wiring. Reset to high, address lines to low, gnd connected. SI to MOSI, SO to MISO; chip not hot or smoking.
- do you use GPIO10, 9, 11, 8 for the SPI ?
- doublecheck it is a MCP23S17 and not a MCP23017
- LED with series resistor to GND ?
Perhaps it helps to see some other code. It is in python, and was my first example to get this device running
As I said, not a perfect sample code. I do not set IOCON here, as 0x00 is default for this register.
Hope it helps
Datasheet is http://ww1.microchip.com/downloads/en/D ... 21952b.pdf
Gerhard
difficult to do remote debugging
- check wiring. Reset to high, address lines to low, gnd connected. SI to MOSI, SO to MISO; chip not hot or smoking.
- do you use GPIO10, 9, 11, 8 for the SPI ?
- doublecheck it is a MCP23S17 and not a MCP23017
- LED with series resistor to GND ?
Perhaps it helps to see some other code. It is in python, and was my first example to get this device running
Code: Select all
import spidev
import time
class MCP23S17:
READ = 1
WRITE = 0
# Bank 0 Addresses
IODIRA = 0x00
IODIRB = 0x01
IODIR_BIT_READ = 1
IODIR_BIT_WRITE = 0
GPIOA = 0x12
GPIOB = 0x13
max_speed_hz = None
portA_value = None
portB_value = None
def __init__(self, bus=0, device=1, addr=0):
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.max_speed_hz = 10000000
self.addr = addr
self.portA_value = 0
self.portB_value = 0
def clearPortA(self):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.GPIOA
self.portA_value = 0
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, self.portA_value]))
def clearPortB(self):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.GPIOB
self.portB_value = 0
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, self.portB_value]))
def setPortA(self, port, value):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.GPIOA
if value:
self.portA_value |= (1 << port)
else:
self.portA_value &= ~(1 << port)
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, self.portA_value]))
def setPortA_dir(self, value):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.IODIRA
cmdValue = value;
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, cmdValue]))
def setPortB_dir(self, value):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.IODIRB
cmdValue = value;
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, cmdValue]))
def setPortB(self, port, value):
addr1 = 0x40 | self.addr << 1 | self.WRITE
addr2 = self.GPIOB
if value:
self.portB_value |= (1 << port)
else:
self.portB_value &= ~(1 << port)
self.spi.max_speed_hz = self.max_speed_hz
self.spi.xfer2 (list([addr1, addr2, self.portB_value]))
def getPortB(self, port):
addr1 = 0x40 | self.addr << 1 | self.READ
addr2 = self.GPIOB
self.spi.max_speed_hz = self.max_speed_hz
r = self.spi.xfer2 (list([addr1, addr2, 0]))
if r[2] & (1 << port) != 0:
return True
return False
mcp23s17 = MCP23S17(0,0,0)
mcp23s17.setPortA_dir( 0b00000000 )
mcp23s17.setPortB_dir( 0b00000000 )
t = 0.2
while True:
mcp23s17.clearPortB()
for i in range(8):
mcp23s17.clearPortA()
mcp23s17.setPortA(i, 1)
time.sleep(t)
mcp23s17.clearPortA()
for i in range(8):
mcp23s17.clearPortB()
mcp23s17.setPortB(i, 1)
time.sleep(t)
t -= 0.01
if t < 0.04:
t = 0.2
Hope it helps
Datasheet is http://ww1.microchip.com/downloads/en/D ... 21952b.pdf
Gerhard
- gordon@drogon.net
- Posts: 2024
- Joined: Tue Feb 07, 2012 2:14 pm
- Location: Devon, UK
Re: SPI communication with MCP23S17 not working
I appreciate that you may ultimately not want to use wiringPi, but the gpio utility can be helpful here as it can poke stuff like this from the command line:
That makes the first pin of port A on the mcp23s17 appear to be pin 200 to wiringPi, sets the mode to output and sets it to 1.
Then check the source code (wiringPi/mcp23s17.c) to see how its doing it and compare with your code.
-Gordon
Code: Select all
gpio -x mcp23s17:200:0 mode 200 out
gpio -x mcp23s17:200:0 write 200 1
Then check the source code (wiringPi/mcp23s17.c) to see how its doing it and compare with your code.
-Gordon
--
Gordons projects: https://projects.drogon.net/
Gordons projects: https://projects.drogon.net/
Re: SPI communication with MCP23S17 not working
Thanks all for reply.
I rewired the MCP23S17 on breadboard and double checked the wiring.
I used Gordon's code to check the wiring and mcp chip status.
>> gpio -x mcp23s17:200:0 mode 200 out
>> gpio -x mcp23s17:200:0 write 200 1
After this, the LED connected to GPA0 turned ON. This made me conclude that the wiring is proper and mcp chip is OK.
I went through wiringPi library. I modified my earlier C code and used wiringPi in it.
I executed it and the spi interface with MCP23S17 is working. The working C code is as follows.
I use Raspberry Pi B+ and the spi module is spi_bcm2708.
I rewired the MCP23S17 on breadboard and double checked the wiring.
I used Gordon's code to check the wiring and mcp chip status.
>> gpio -x mcp23s17:200:0 mode 200 out
>> gpio -x mcp23s17:200:0 write 200 1
After this, the LED connected to GPA0 turned ON. This made me conclude that the wiring is proper and mcp chip is OK.
I went through wiringPi library. I modified my earlier C code and used wiringPi in it.
I executed it and the spi interface with MCP23S17 is working. The working C code is as follows.
Code: Select all
#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <mcp23s17.h>
// Register Addresses of MCP23S17
#define CMD_WRITE 0x40
#define IOCON 0x0A
#define IODIRA 0x00
#define OLATA 0x14
int main (void)
{
uint8_t data[3];
int i, speed, csPin;
speed = 500000; //CLK setting, set to 500KHz
csPin = 5;
// Init
wiringPiSetup();
wiringPiSetupGpio();
pinMode(csPin, OUTPUT);
wiringPiSPISetupMode(0, speed, 0);
digitalWrite(csPin, HIGH); // CS pin high
printf("Raspberry Pi - MCP23S17\n");
data[0] = CMD_WRITE;
data[1] = IOCON;
data[2] = 0x00;
digitalWrite(csPin, LOW); // CS pin low
wiringPiSPIDataRW(0, data, 3); //Sending SPI data
delay(1);
digitalWrite(csPin, HIGH); // CS pin high
delay(1);
data[0] = CMD_WRITE;
data[1] = IODIRA;
data[2] = 0x00; //Setting all PortA pins as outputs
digitalWrite(csPin, LOW); // CS pin low
wiringPiSPIDataRW(0, data, 3); //Sending SPI data
delay(1);
digitalWrite(csPin, HIGH); // CS pin high
delay(1);
data[0] = CMD_WRITE;
data[1] = OLATA;
data[2] = 0x80; //Setting GPA7 High
digitalWrite(csPin, LOW); // CS pin low
wiringPiSPIDataRW(0, data, 3); //Sending SPI data
delay(1);
digitalWrite(csPin, HIGH); // CS pin high
delay(1);
printf("done\n");
}
Re: SPI communication with MCP23S17 not working
Hi Gordon
I used interface MCP23S17 to Raspberry Pi 2 it has spi module spi_bcm2835.
I used the following code to test the setup, but no output.
>> gpio -x mcp23s17:200:0 mode 200 out
>> gpio -x mcp23s17:200:0 write 200 1
But when i used the same code on Raspberry Pi B+ which has spi module spi_bcm2708, there it gives proper output.
Also my earlier C code which worked successfully on Raspberry Pi B+, is not giving any output on Raspberry Pi 2.
Do i have to update/install any library on Raspberry Pi 2 ?
Is spi module spi_bcm2835 not working ?
I used interface MCP23S17 to Raspberry Pi 2 it has spi module spi_bcm2835.
I used the following code to test the setup, but no output.
>> gpio -x mcp23s17:200:0 mode 200 out
>> gpio -x mcp23s17:200:0 write 200 1
But when i used the same code on Raspberry Pi B+ which has spi module spi_bcm2708, there it gives proper output.
Also my earlier C code which worked successfully on Raspberry Pi B+, is not giving any output on Raspberry Pi 2.
Do i have to update/install any library on Raspberry Pi 2 ?
Is spi module spi_bcm2835 not working ?