Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

18F4520 MCP23S18 SPI Interface

Status
Not open for further replies.

Mity Eltu

Member
I'm having some difficulty understanding how to make this interface operate. Rather than try to explain what I don't understand, let me just post my code. All I'm trying to do is get the port expander to turn on the leds on portb. So far I'm getting nothing. Can someone look at the code and tell me where I've hosed it up?

Please?


Code:
Define CONFIG1L = 0x00
 
Define CLOCK_FREQUENCY = 8
 
Dim loop As Bit
 
main:
    OSCCON = 0x72  'internal 8MHz
    Gosub setup
   
    Call sspsend(0x0a, 0x28)  'sequential address, sequ op dis
    Call sspsend(0x0b, 0x28)
    Call sspsend(0x01, 0x00)  'all pins output
    Call sspsend(0x0d, 0x00)  'pull ups disabled
    Call sspsend(0x13, 0xff)  'on
   
    While loop 'heart beat
        PORTD.0 = 1
        WaitMs 1000
        PORTD.0 = 0
        WaitMs 1000
    Wend
End                                              
 
 
setup:
    INTCON = 0x00
    INTCON2 = 0x80  'pull ups disabled
    INTCON3 = 0x00
   
    CCP1CON = 0x00  'cap / comp off
    CCP2CON = 0x00
   
    SSPCON1 = 0x20  'spi on
    SSPSTAT = 0x40  'sample at end, cke=0
   
    ADCON0 = 0x00  'A/D off
    ADCON1 = 0x0f  'all digital
   
    CMCON = 0x07  'comp off, digital io
    CVRCON = 0x00
       
    HLVDCON = 0x00  'Low volt detect off
   
    TRISA = 0x00
    TRISB = 0x00
    TRISC = 0x00
    TRISC.4 = 1  'sdi input
    TRISD = 0x00
    LATD.0 = 1
    TRISE = 0x00
   
    PORTA = 0x00
    PORTB = 0x00
    PORTC = 0x00
    PORTE = 0x00
   
    WaitUs 100
   
    loop = 1
Return                                           
 
Proc sspsend(adr As Byte, dat As Byte)
    PORTD.1 = 0  'chip select
   
    SSPBUF = 0x40  'send chip id
    While SSPSTAT.0 = 0
    Wend
   
    'send address
    SSPBUF = adr
    While SSPSTAT.0 = 0
    Wend
   
    'send data
    SSPBUF = dat
    While SSPSTAT.0 = 0
    Wend
   
    PORTD.1 = 1
End Proc
 
I have a single led on pin 10 (expander port b 7). I just reversed the polarity, but that didn't fix it.
I have picSDI to expander SO, picSDO to expander SI, and picPORTD1 to expander CS.
I have tried taking the expander reset pin to vcc and gnd as well as controlled by the uc without any change.
I did put an led on the pic SDO pin to see if it was at least TRYING to send data. It blinks dimly indicating it is sending something (I can't tell what - no scope here at the moment).
The heartbeat is working.

Wait, only open collector? Should I make the pins inputs and then sink through the led?

edit: Just tried all 4 possible combination of io direction and port on/off. No changes. Still nothing on the led. This is really frustrating. I managed to get 2 pics talking spi in about an hour. I've been banging on this for more than 3 and still don't have anything to show.
 
Wait, only open collector? Should I make the pins inputs and then sink through the led?
No!

You need to make them outputs and apply 0x00 to the port, then they will sink current... Resistor from +V through the LED to the pin will light it up!
 
My father-in-law always said you have to be smarter than the piece of equipment you're working with.

That's always been a big problem for me.....

There were 2 big mistakes I was making. ONE - open drain output. Thank you Ian for getting me on the right track there. Read the datasheet but apparently just glossed right over that part. TWO - I didn't clear SSPSTAT BF bit after the data was transferred. I guess if I had some error chekcing routines I would have noticed the bus collision. It is now blinking as it should and I have managed to turn on and off the expanded outputs corectly.

Anyway. Live and learn..... I wish I could just live and know without having to learn.

Thanks for the help.
 
I have another problem with this interface. I am able to send bytes to the expander chip without any trouble now - thanks for the help.
Now, however, I am trying to receive data and I just can't seem to get it to do anything. I'm even now confused about how to make the spi clock the data.

code snippet:
Code:
Function sspread(adr As Byte, adr2 As Byte) As Byte
    PORTA.5 = 0  'chip select
  
    SSPBUF = 0x41  'send chip id, RW bit = 1 (read)
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
  
    SSPBUF = adr  'send address
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
  
    While SSPSTAT.0 = 0 'clock data to receive?
    Wend
    SSPSTAT.0 = 0
  
    sspread = SSPBUF
 
    PORTA.5 = 1
End Function

So, this doesn't seem to actually receive anything. When this function is called, I am always requesting the same byte from the expander chip. I want to receive the LATA register at address 0x15. When I WRITE to this register, it works every time. I always write either 0xfe or 0xfa to the register to make distinctions between code sections. I have tried writing the received data into EEPROM to check and it's always either 0x00 or 0xff.

For the sake of completeness, the following code is executed to set the expander chip functionality:
Code:
    Call sspsend(0x0a, 0x22)  '0x28)  'sequential address, sequ op dis
    Call sspsend(0x0b, 0x22)  '0x28)
  
    Call sspsend(0x0c, 0x00)  'pull ups disabled
    Call sspsend(0x00, 0xff)  'all porta pins input
    Call sspsend(0x04, 0x00)  'porta0 interrupt on change
  
    Call sspsend(0x01, 0x00)  'all portb pins output
    Call sspsend(0x0d, 0x00)  'pull ups disabled
    Call sspsend(0x15, 0xff)  'all off

The sspsend procdure works and is as follows:
Code:
Proc sspsend(adr As Byte, dat As Byte)
    PORTA.5 = 0  'chip select
  
    SSPBUF = 0x40  'send chip id, RW bit = 0 (write)
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
  
    SSPBUF = adr  'send address
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
  
    SSPBUF = dat  'send data
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
  
    PORTA.5 = 1
End Proc

Is there anything that jumps out at you as being an error? I really just don't understand why it's not working.
 
SPI is a continual loop... To receive a byte you have to send a byte..SSPBUF holds the value returned after you sent one..

Assume you need to access register 2 on the device..


Code:
Function sspsend(adr As Byte) As Byte
    PORTA.5 = 0  'chip select
 
    SSPBUF = 0x41  'send chip id, RW bit = 1 (read)
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
 
    SSPBUF = adr  'send address
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
 
    SSPBUF =0xff  'send data
    While SSPSTAT.0 = 0
    Wend
    SSPSTAT.0 = 0
    sspsend = SSPBUF

    PORTA.5 = 1
End Function
 
Ok, so it's full duplex. Sending and receiving at the same time. I guess that's why the data sheet says:
17.3 SPI Mode
The SPI mode allows 8 bits of data to be synchronously
transmitted and received simultaneously.

Thanks, I'll let you know how it goes Monday. Taking the weekend OFF from work this time.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top