PDA

View Full Version : MCP23S17 - Three different approaches - ShiftIn/ShiftOut / MSSP+PBP / MSSP+ASM



gadelhas
- 1st February 2012, 19:42
Hi everyone;

In a project that came up was necessary to use the MCP23S17. After searching the forum, i did not find any example that would satisfy my needs.

For this reason, I decided to write my own code to communicate with the MCP23S17. There were written three different approaches to communicate with the IC.

The first uses only PBP and the commands and shiftin ShiftOut, the second approach, uses the MSSP module of the PIC IC with PBP, and the third, also uses the MSSP module, but the "send" and "receive" routines were written in ASM.

The following three examples below, one per post. In each post you can see the size of the code, and the time that takes to execute the "Send" and "receive" routine.

All codes are commented well enough to understand its operation. Also the schematic is founded attached, and the Proteus simulation. ( You must take off the ".txt" from each file )

The code was written in Microcode Studio 3.0.0.5 and PBP2.60C.
The IC that was used is PIC16F887.
To test the codes, was used the development board Mikroelektronika EASYPICv6 and software PROTEUS 7.7 SP2.

I hope it will be useful to someone.

gadelhas
- 1st February 2012, 19:46
'************************************************* ***************
'* Name : MCP23S17 + PBP + ShiftIN & ShiftOut *
'* Author : [GADELHAS] *
'* Notice : Copyright (c) 2012 *
'* : All Rights Reserved *
'* Date : 31-01-2012 *
'* Version : 1.0 *
'* Notes : *
'* : EASYPICV6 + PIC16F887 + MCP23S17 *
'************************************************* ***************
' CONFIGS
' ================================================== ==============
@ __CONFIG _CONFIG1, _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOR_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_ON & _IESO_OFF
@ __CONFIG _CONFIG2, _WRT_OFF & _BOR40V' DEFINES & INCLUDES
' ================================================== ==============
DEFINE OSC 8
include "modedefs.bas"
' REGISTERS AND PINOUT ( 1 = IN; 0 = OUT )
' ================================================== ==============
'76543210 '76543210
TRISA = %00000000: PORTA = %00000000
TRISB = %00000000: PORTB = %00000000
TRISC = %00000000: PORTC = %00000000
TRISD = %00000000: PORTD = %00000000
TRISE = %00000000: PORTE = %00000000
ADCON0 = %00000000
ADCON1 = %00000000
ANSEL = %00000000
ANSELH = %00000000
CM1CON0 = %00000000
CM2CON0 = %00000000

' ALIAS & MODIFIERS
' ================================================== ==============
nCS VAR PORTA.2
nRST VAR PORTA.3
SCLK VAR PORTC.3
SDI VAR PORTC.4
SDO VAR PORTC.5

' VARIABLES & COSTANTS
' ================================================== ==============
MCPWRT CON $40 'Command o write in MCP23S17 Address $00
MCPRED CON $41 'Command o read from MCP23S17 Address $00
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)

DataOut VAR BYTE 'Variable for Data Byte to Send to the MCP23S17
DataIn VAR BYTE 'Variable for Data Byte to Receive from the MCP23S17
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17

' PROGRAM INIT
' ================================================== ==============
GOSUB INIT_MCP23S17 'Init the MCP23S17
' MAIN LOOP
' ================================================== ==============
MAIN:
MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17

MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

PAUSE 200
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
INIT_MCP23S17:
nRST = 0 'Reset the port expander
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $20
GOSUB SEND_MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
GOSUB SEND_MCP23S17

MCPReg = IODIRB 'Configures PortB(2) All Input
DataOut = $FF
GOSUB SEND_MCP23S17
RETURN
SEND_MCP23S17:
nCS = 0 'Enable the MCP23S17
SHIFTOUT SDO, SCLK, MSBFIRST, [MCPWRT,MCPReg,DataOut]
nCS = 1 'Disable the MCP23S17
RETURN
RECEIVE_MCP23S17:
nCS = 0 'Enable the MCP23S17
SHIFTOUT SDO, SCLK, MSBFIRST, [MCPRED,MCPReg]
SHIFTIN SDI, SCLK, MSBPRE, [DataIn]
nCS = 1 'Disable the MCP23S17
RETURN
END



Size: 285 Words

Time to execute the following Routine ( Send) - 990 ticks -> 495.0uS


MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17



Time to execute the following Routine ( Receive) - 927 ticks -> 463.1uS


MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

gadelhas
- 1st February 2012, 19:50
'************************************************* ***************
'* Name : MCP23S17 + MSPP + PBP *
'* Author : [GADELHAS] *
'* Notice : Copyright (c) 2012 *
'* : All Rights Reserved *
'* Date : 31-01-2012 *
'* Version : 1.0 *
'* Notes : *
'* : EASYPICV6 + PIC16F887 + MCP23S17 *
'************************************************* ***************
' CONFIGS
' ================================================== ==============
@ __CONFIG _CONFIG1, _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOR_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_ON & _IESO_OFF
@ __CONFIG _CONFIG2, _WRT_OFF & _BOR40V' DEFINES & INCLUDES
' ================================================== ==============
DEFINE OSC 8
' REGISTERS AND PINOUT ( 1 = IN; 0 = OUT )
' ================================================== ==============
'76543210 '76543210
TRISA = %00000000: PORTA = %00000000
TRISB = %00000000: PORTB = %00000000
TRISC = %00010000: PORTC = %00000000
TRISD = %00000000: PORTD = %00000000
TRISE = %00000000: PORTE = %00000000
ADCON0 = %00000000
ADCON1 = %00000000
ANSEL = %00000000
ANSELH = %00000000
CM1CON0 = %00000000
CM2CON0 = %00000000
SSPSTAT = %00000000 'Configures the SPI Module ( Read DataSheet )
SSPCON = %00110000 'Configures the SPI Module ( Read DataSheet )

' ALIAS & MODIFIERS
' ================================================== ==============
nCS VAR PORTA.2
nRST VAR PORTA.3
SCLK VAR PORTC.3
SDI VAR PORTC.4
SDO VAR PORTC.5

' VARIABLES & COSTANTS
' ================================================== ==============
MCPWRT CON $40 'Command o write in MCP23S17 Address $00
MCPRED CON $41 'Command o read from MCP23S17 Address $00
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)

DataOut VAR BYTE 'Variable for Data Byte to Send to the MCP23S17
DataIn VAR BYTE 'Variable for Data Byte to Receive from the MCP23S17
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17

' PROGRAM INIT
' ================================================== ==============
GOSUB INIT_MCP23S17 'Init the MCP23S17
' MAIN LOOP
' ================================================== ==============
MAIN:
MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17

MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

PAUSE 200
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
INIT_MCP23S17:
nRST = 0 'Reset the port expander
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $20
GOSUB SEND_MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
GOSUB SEND_MCP23S17

MCPReg = IODIRB 'Configures PortB(2) All Input
DataOut = $FF
GOSUB SEND_MCP23S17
RETURN
SEND_MCP23S17:
nCS = 0 'Enable the MCP23S17
SSPBUF = MCPWRT 'Command to Write to the MCP23S17
PAUSEUS 1
SSPBUF = MCPReg 'Register to Write the Data
PAUSEUS 1
SSPBUF = DataOut 'Data to be sent
PAUSEUS 1
nCS = 1 'Disable the MCP23S17
RETURN
RECEIVE_MCP23S17:
nCS = 0 'Enable the MCP23S17
SSPBUF = MCPRED 'Command to Read from the MCP23S17
PAUSEUS 1
SSPBUF = MCPReg 'Register to Read from
PAUSEUS 1
SSPBUF = 0 'Send something
PAUSEUS 1
DataIn = SSPBUF 'Data received from te MCP23S17
PAUSEUS 1
nCS = 1 'Disable the MCP23S17
RETURN
END



Size: 166 Words

Time to execute the following Routine ( Send) - 92 ticks -> 46.0uS


MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17



Time to execute the following Routine ( Receive) - 119 ticks -> 59.1uS


MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

gadelhas
- 1st February 2012, 19:53
'************************************************* ***************
'* Name : MCP23S17 + MSPP + ASM *
'* Author : [GADELHAS] *
'* Notice : Copyright (c) 2012 *
'* : All Rights Reserved *
'* Date : 31-01-2012 *
'* Version : 1.0 *
'* Notes : *
'* : EASYPICV6 + PIC16F887 + MCP23S17 *
'************************************************* ***************
' CONFIGS
' ================================================== ==============
@ __CONFIG _CONFIG1, _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOR_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_ON & _IESO_OFF
@ __CONFIG _CONFIG2, _WRT_OFF & _BOR40V
' DEFINES & INCLUDES
' ================================================== ==============
DEFINE OSC 8
' REGISTERS AND PINOUT ( 1 = IN; 0 = OUT )
' ================================================== ==============
'76543210 '76543210
TRISA = %00000000: PORTA = %00000100
TRISB = %00000000: PORTB = %00000000
TRISC = %00010000: PORTC = %00000000
TRISD = %00000000: PORTD = %00000000
TRISE = %00000000: PORTE = %00000000
ADCON0 = %00000000
ADCON1 = %00000000
ANSEL = %00000000
ANSELH = %00000000
CM1CON0 = %00000000
CM2CON0 = %00000000
SSPSTAT = %00000000 'Configures the SPI Module ( Read DataSheet )
SSPCON = %00110000 'Configures the SPI Module ( Read DataSheet )

' ALIAS & MODIFIERS
' ================================================== ==============
nCS VAR PORTA.2
nRST VAR PORTA.3
SCLK VAR PORTC.3
SDI VAR PORTC.4
SDO VAR PORTC.5

' VARIABLES & COSTANTS
' ================================================== ==============
MCPWRT CON $40 'Command o write in MCP23S17 Address $00
MCPRED CON $41 'Command o read from MCP23S17 Address $00
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)

DataOut VAR BYTE 'Variable for Data Byte to Send to the MCP23S17
DataIn VAR BYTE 'Variable for Data Byte to Receive from the MCP23S17
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17

' PROGRAM INIT
' ================================================== ==============
GOSUB INIT_MCP23S17 'Init the MCP23S17
' MAIN LOOP
' ================================================== ==============
MAIN:
MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17

MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

PAUSE 200
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
INIT_MCP23S17:
nRST = 0 'Reset the port expander
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $20
GOSUB SEND_MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
GOSUB SEND_MCP23S17

MCPReg = IODIRB 'Configures PortB(2) All Input
DataOut = $FF
GOSUB SEND_MCP23S17
RETURN
SEND_MCP23S17:
ASM
bcf PORTA, 2 ;Enable the MCP23S17
MOVE?CB _MCPWRT, SSPBUF ;Command to Write to the MCP23S17
call _delay
MOVE?BB _MCPReg, SSPBUF ;Register to Write the Data
call _delay
MOVE?BB _DataOut, SSPBUF ;Data to be sent
call _delay
bsf PORTA, 2 ;Disable the MCP23S17
ENDASM
RETURN
RECEIVE_MCP23S17:
ASM
bcf PORTA, 2 ;Enable the MCP23S17
MOVE?CB _MCPRED, SSPBUF ;Command to Read from the MCP23S17
call _delay
MOVE?BB _MCPReg, SSPBUF ;Register to Read from
call _delay
MOVE?BB _DataOut, SSPBUF ;Send something
call _delay
MOVE?BB SSPBUF, _DataIn ;Data received from te MCP23S17
bsf PORTA, 2 ;Disable the MCP23S17
ENDASM
RETURN
delay: 'Delay Routine 3uS - You may have to change if running OSC faster
asm ;8Mhz/4 = 2Mhz = 0.5uS X 6cycles(2 p/goto) = 3uS
goto $+1
goto $+1
goto $+1
endasm
return
END



Size: 157 Words

Time to execute the following Routine ( Send) - 47 ticks -> 23.1uS


MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
GOSUB SEND_MCP23S17



Time to execute the following Routine ( Receive) - 50 ticks -> 25.0uS


MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
PORTB = DataIn 'PIC

Demon
- 2nd February 2012, 02:31
This is great stuff. I use the MCP23016, but this new IC is much faster.

Can you explain how you came up with the 3us delay in the 3rd approach? I look at your comment and the SPI characteristics in the datasheet and don't know what to use exactly.

Robert

gadelhas
- 2nd February 2012, 13:48
This is great stuff. I use the MCP23016, but this new IC is much faster.

Can you explain how you came up with the 3us delay in the 3rd approach? I look at your comment and the SPI characteristics in the datasheet and don't know what to use exactly.

Robert

Hi Robert, Thanks for your comment.

Hi came up with 3 uS by trial and error. I tried 2 uS, but it wasn´t enough. The problem is not the MCP23S17, but the SSPUBUF register of the PIC. I think if you run the PIC faster, for instance @20Mhz, you can even reduce that time.

Demon
- 2nd February 2012, 23:30
Wouldn't it be the other way around? If you run a PIC faster, it would cycle quicker so you'd need more delay instructions no?

I checked the datasheet again and page 35 table 2-4 has 500ns for Serial Data to Output Valid. Does that mean it takes 500ns for the IC to process a complete output operation?

I would assume reading is quicker...?

Robert

gadelhas
- 3rd February 2012, 00:28
Wouldn't it be the other way around? If you run a PIC faster, it would cycle quicker so you'd need more delay instructions no?

I checked the datasheet again and page 35 table 2-4 has 500ns for Serial Data to Output Valid. Does that mean it takes 500ns for the IC to process a complete output operation?

I would assume reading is quicker...?

Robert

The problem is that when you put a byte in the SSPUF of the PIC, it takes some time for the PIC to output that byte( @8Mhz ~3uS ). If you run the PIC faster, the time that it takes to output the byte gets reduced.
At this speed ( 8Mhz ), you put the byte into the SSPUF and you must wait 3us to put another byte in the SSPUF, if you put a byte before the 3us, for instance at 2us, the byte before will be corrupted and the pic will output the new byte and miss the byte before. You can try this in the simulation that is attached.

You are looking at the wrong table ( 2-4 GP and INT TIMMING). You should look table 2-3 (SPI Characteristics ). The MCP23S17 can RUN at a max of 10Mhz ( SPI ).

HenrikOlsson
- 3rd February 2012, 07:54
Hi,
Instead of relying on software timing you can check the MSSP interrupt flag:

myByte VAR BYTE
SSPIF VAR PIR1.3

myByte = 123

SSPBUF = myByte ' Load byte to shiftregister buffer
SSPIF = 0 ' Clear interrupt flag
WHILE SSPIF=0 : WEND ' Wait for transmission to finish

This way you don't have to change any timing if you change the oscillator or if you change the MSSP module clock divisor etc.

Check the datasheet and make sure the SSPIF is at PIR1.3 for your device. (I think they try to keep it consistent but you never know)

/Henrik.

gadelhas
- 3rd February 2012, 20:25
Hi,
Instead of relying on software timing you can check the MSSP interrupt flag:

myByte VAR BYTE
SSPIF VAR PIR1.3

myByte = 123

SSPBUF = myByte ' Load byte to shiftregister buffer
SSPIF = 0 ' Clear interrupt flag
WHILE SSPIF=0 : WEND ' Wait for transmission to finish

This way you don't have to change any timing if you change the oscillator or if you change the MSSP module clock divisor etc.

Check the datasheet and make sure the SSPIF is at PIR1.3 for your device. (I think they try to keep it consistent but you never know)

/Henrik.

Hi Henrik,

You are correct. I did try the PIR1.3 flag, however i forgot to clear it before test it, and because of that it was not working like should be.
One problem with this approach is that it takes more memory.

One more thing, to test if the SSPBUF has received a byte, we should test the SSPSTAT.BF bit, like:



DataIn = SSPBUF 'Data received from te MCP23S17
SSPSTAT.0 = 0
WHILE SSPSTAT.0 : WEND


Now i need to change the code that i posted before this little improvement, but i can modify my posts!!!!

Thanks!!!

HenrikOlsson
- 3rd February 2012, 21:55
Hi,
I initially used the the SSPSTAT.0 bit for both sending and receiving but eventually got into trouble. Darrel then made me aware in this thread (http://support.melabs.com/threads/96-MSSP-module-query.) of that the purpose of SSPSTAT.0 flag really is when the PIC is operating in slave mode and data is shifted into to PIC by an external clock source, ie when something else is providing the SPI clock. (Thanks Darrel!)

When the PIC is acting as the master, as is the case in all your examples, it works fine with the interrupt flag. For shifting in a byte you simply write a "dummy" value to SPPBUF, the module will then shift that dummy byte out with 8 clockpulses and then you'll have your input byte in SSPBUF.

IF you're going to use the SSPSTAT.0 bit I suspect you want to poll it before reading SSPBUF to see if there's a byte available to be read. The way you have in your latest post you grab whatever is in SSPBUF and then sit there waiting for another byte before continuing. Is that the intentended operation?

/Henrik.

gadelhas
- 3rd February 2012, 22:13
Hi,
IF you're going to use the SSPSTAT.0 bit I suspect you want to poll it before reading SSPBUF to see if there's a byte available to be read. The way you have in your latest post you grab whatever is in SSPBUF and then sit there waiting for another byte before continuing. Is that the intentended operation?

/Henrik.

No, i actully take it of in my last version. Since the last thing that the MCP sends is the byte that i want, i just grab it and put it on the PORTB.

gadelhas
- 4th February 2012, 22:33
You can find the last code on the WIKI (http://www.picbasic.co.uk/forum/content.php?r=471-MCP23S17-Three-different-approaches-ShiftIn-ShiftOut-MSSP-PBP-MSSP-ASM).

Yvesmazzon
- 6th February 2012, 09:31
Hi Gaelas,
I realized when you mailed the above was quite a while ago. Did you ever extendedyour code to drive a 8 or 4 bits LCD? I am using PicDem board and also the ISISversion but both are written in PASM and trying to get the PBP or Proton basicto do the same thing. Any advises or basic code will be welcome.
Regards,
Yves

gadelhas
- 6th February 2012, 15:11
Hi Gaelas,
I realized when you mailed the above was quite a while ago. Did you ever extendedyour code to drive a 8 or 4 bits LCD? I am using PicDem board and also the ISISversion but both are written in PASM and trying to get the PBP or Proton basicto do the same thing. Any advises or basic code will be welcome.
Regards,
Yves


Hi;

No i don't have any example how to interface the MCP with a LCD. It never was necessary. Maybe one day i develop such example, but for now i'm working on other examples.

Ryan7777
- 28th July 2012, 22:34
Im having trouble getting this to work. my circuit is the same as Gadelhas has in his schematic, except im not grabbing any inputs with my circuit and i'm using a different PIC . The way I have it coded is so that I can use it with a 16F648A w/ 4Mhz internal OSC and I think it should light each led on the MCP23S17s PORTA one at a time before reseting at the end of the string and repeating, but its not working in that the leds never light. I have an LED on PORTB.4 as kind of a watch dog blinky and its behaving as I would expect. Any ideas on whats wrong with my version of Gadelhas' code or something else I'm missing?



' CONFIGS
' ================================================== ==============
@ DEVICE PIC16F648A, INTRC_OSC_NOCLKOUT, WDT_OFF, PWRT_OFF, MCLR_OFF, PROTECT_OFF, BOD_OFF, LVP_OFF

' DEFINES & INCLUDES
' ================================================== ==============
DEFINE OSC 4
include "modedefs.bas"
' REGISTERS AND PINOUT ( 1 = IN; 0 = OUT )
' ================================================== ==============
'76543210
CMCON = 7 ' Turn off un-needed PIC hardware
VRCON = 0 ' '' ''
CCP1CON = 0 ' '' ''
INTCON = %00000000 ' '' ''


' ALIAS & MODIFIERS
' ================================================== ==============
nCS VAR PORTA.0
nRST VAR PORTB.5
SCLK VAR PORTB.0
SDO VAR PORTB.3

' VARIABLES & COSTANTS
' ================================================== ==============
MCPWRT CON $40 'Command o write in MCP23S17 Address $00
MCPRED CON $41 'Command o read from MCP23S17 Address $00
IOCON CON $0A 'Register address to MCP23S17 Config
IODIRA CON $00 'Register address to MCP23S17 PortA(1)
IODIRB CON $01 'Register address to MCP23S17 PortB(2)
GPIOA CON $12 'Register address to MCP23S17 GPIOA(1)
GPIOB CON $13 'Register address to MCP23S17 GPIOB(2)
OLATA CON $14 'Register address to MCP23S17 LATA(1)
OLATB CON $15 'Register address to MCP23S17 LATB(2)

DataOut VAR BYTE 'Variable for Data Byte to Send to the MCP23S17
DataIn VAR BYTE 'Variable for Data Byte to Receive from the MCP23S17
MCPReg VAR BYTE 'Variable for the Register to Send to the MCP23S17

' PROGRAM INIT
' ================================================== ==============
clear
pause 100
nrst = 1
ncs = 1
sclk = 0
sdo = 0
pause 100
GOSUB INIT_MCP23S17 'Init the MCP23S17
' MAIN LOOP
' ================================================== ==============
MAIN:
MCPReg=OLATA 'This light up the leds, connected in
DataOut=DataOut+1 'PortA(1) of the MCP23S17
if dataout >=8 then
dataout=0
GOSUB SEND_MCP23S17
gosub INIT_MCP23S17:
endif
GOSUB SEND_MCP23S17

' MCPReg = GPIOB 'This read the PortB(1) of the MCP23S17
' GOSUB RECEIVE_MCP23S17 'and show the result on the PORTB of the
' PORTB = DataIn 'PIC

PAUSE 500
if dataout = 0 then
high PORTB.4
pause 250
low PORTB.4
pause 250
endif
high PORTB.4
pause 500
low PORTB.4
GOTO MAIN
' SUB - ROTINES
' ================================================== ==============
INIT_MCP23S17:
nRST = 0 'Reset the port expander
PAUSE 1
nRST = 1
MCPReg = IOCON 'Configures the MCP23S17
DataOut = $20
GOSUB SEND_MCP23S17
MCPReg = IODIRA 'Configures PortA(1) All Output
DataOut = $00
GOSUB SEND_MCP23S17

MCPReg = IODIRB 'Configures PortB(2) All Input
DataOut = $FF
GOSUB SEND_MCP23S17
RETURN
SEND_MCP23S17:
nCS = 0 'Enable the MCP23S17
SHIFTOUT SDO, SCLK, MSBFIRST, [MCPWRT,MCPReg,DataOut]
nCS = 1 'Disable the MCP23S17
RETURN
'RECEIVE_MCP23S17:
' nCS = 0 'Enable the MCP23S17
' SHIFTOUT SDO, SCLK, MSBFIRST, [MCPRED,MCPReg]
' SHIFTIN SDI, SCLK, MSBPRE, [DataIn]
' nCS = 1 'Disable the MCP23S17
'RETURN
END

gadelhas
- 29th July 2012, 01:49
Hi Ryan7777;

Try to add this 2 lines after the INTCON configuration and see if it works.

TRISA = %00000000
TRISB = %00000000

gadelhas
- 29th July 2012, 23:47
Hi Ryan7777;

Have you allready tried my sugestion?

I've tried and it worked, so you must add those to lines that i mention.
Also remember that you are working with binary numbers, so this;



DataOut=DataOut+1
if dataout >=8 then


will not light up all the leds.

Ryan7777
- 30th July 2012, 11:00
Oh hey, Thanks! You're exactly right the set up of my ports was the snag. I was also confused with the dataOut= and the pins on the port expander being addressed as a binary number (1,2,4,8,16,32,64,128). My first go after after setting up TRIS, the port expander was counting up in binary and of course stopping because of the if dataOut >=8 then bit of code. I fixed all of that and tossed together some quick, sloppy code using a couple of FOR NEXT loops and SELECT CASE structure to get it to count up and down in proper fashion to scan the LEDs one at a time up PORTA and back down. So if I wanted to play "night rider", now I all I'd need is a black firebird :rolleyes: Now I feel like a have a good grasp on how to talk to the MCP23S17 for the project I had originally intended it for. Thank you for the fast replies and for posting your tutorial on this part! I'll post my "blinky" code when I get back to my real PC.

Thanks again!

Ryan