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