Hi all,

I am trying to write a PBP program to interface a PIC18F2520 to the MCP23S17 port expander (on the EasyPIC6 dev board).

If you don't know the Port Expander is an SPI device that adds two 8 bit ports. To configure it you send a command byte ($40) followed by the register address you wish to write to and the value you wish to write (e.g. to set portA as an output you write $00 to the IODIRA register). Then to write a value to the port you send the command byte followed by the register GPIOA address and the value you wish to write, e.g. $FF to turn the port all ON.

If you didn't understand the above don't worry - its not particularly important in understanding my problem.

My program simply sets up the port expander by sending the appropriate bytes (see above) using the shiftout command and then runs a loop that increments a variable each cycle and writes it to the two ports on the port expander (which will just light some LEDs to give a visual indication that the port expander is working). The loop runs every 100ms and toggles PORTB.0 (an LED) on each cycle so I know that the program is running.

I compiled the code and simulated it in ISIS and it works fine. However when I load it onto the PIC it does not work - the PORTB.0 LED flashes so the program is running, however the Port Expander LEDs do nothing. I put an oscilloscope on the nCS, SCLK and SDO lines to check that the data is being sent by the pic as it is in the simulation. I can see the nCS pin toggling as it should, however there is nothing on the SCLK and SDO lines. This means that despite the simulation running correctly the PIC is just not shifting the data out therefore the port expander is not anything.

As an experiment I toggles the SCLK line manually inside the loop (just once up and once down) and put the scope on it. I can see this behaviour on the scope so I know that the pin is setup correctly as an output, it just isnt being driven by the shiftout command.

I also tried shiftout on two other pins but got nothing on them either so perhaps its a setup problem?

It seems odd that it simulates fine but does not function in reality, although I do not truly trust the ISIS simulation as I have seen it do very odd things in the past.

If anyone has any thoughts on this please let me know as its beginning to drive me insane.

Code:
Include "modedefs.bas"
 asm
   
    __CONFIG    _CONFIG1H, _OSC_XT_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
    __CONFIG    _CONFIG2L, _PWRT_ON_2L & _BOREN_OFF_2L  & _BORV_2_2L
    __CONFIG    _CONFIG2H, _WDT_OFF_2H
    __CONFIG    _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
    __CONFIG    _CONFIG4L, _STVREN_ON_4L
    
    endasm

 
' ==============================================================================
' DEFINES
' ==============================================================================

DEFINE OSC 4

TRISA = 0
TRISC = 0
TRISB = 0

PORTA = 0
PORTC = 0
PORTB = 0



' ==============================================================================
' ADC Config
' ==============================================================================
    ADCON0.0 = 0          'Disable ADC Module
    ADCON1 = %00001111	  'Set PORTA to digital


' ==============================================================================
' Constants
' ==============================================================================
 
                
CONTROL_BYTE con $40    ' write operation to device address $00
IOCON con $0A
IODIRA CON $00
IODIRB CON $01
GPIOA CON $14
GPIOB con $15



' ==============================================================================
' Pin Definitions
' ==============================================================================

SCLK var PORTC.3
SDI var PORTC.4
SDO var PORTC.5

nCS var PORTA.2
nRST var PORTA.3



' ==============================================================================
' Variables
' ==============================================================================

Data_Byte var byte
Register var byte
LCD_Cmd var bit     ' denotes whether the data sent to the LCD is a command or
                    ' a character. i.e. determines the state of the RS pin
LCD_Byte var byte   ' the byte to send to the LCD (character or command)



gosub PE_INIT

pause 250

REGISTER = GPIOA
DATA_BYTE = $00



loop:

    pause 100
    REGISTER = GPIOA
    'DATA_BYTE = $00
    gosub SEND_PE_BYTE
    REGISTER = GPIOB
   ' DATA_BYTE = $00
    gosub SEND_PE_BYTE       
    toggle PORTB.0
    DATA_BYTE = DATA_BYTE + 1

goto loop:



PE_INIT:

        nRST = 0 ' reset the port expander
        pause 10
        nRST = 1

        REGISTER = IOCON         
        DATA_BYTE = %00100000
        gosub SEND_PE_BYTE       ' setup IOCON for Bank 0 non-sequetial operation
        
        REGISTER = IODIRA
        DATA_BYTE = $00
        gosub SEND_PE_BYTE 
        
        REGISTER = IODIRB
        DATA_BYTE = $00
        gosub SEND_PE_BYTE       ' set PORTB as output
       

return

SEND_PE_BYTE:
        
        nCS = 0 ' enable PE
        Shiftout SDO, SCLK, MSBFIRST, [CONTROL_BYTE,REGISTER,DATA_BYTE]        
        nCS = 1 '      
        pause 10

return