1. 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.
    Dismiss Notice

18F4520 MCP23S18 SPI Interface

Discussion in 'Oshonsoft' started by Mity Eltu, Oct 28, 2015.

  1. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    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 (text):
    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                                        
     
     
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    Whats connected to the port..... MCP23s18 has open collector outputs.. ie only reads or sinks... The MCP23s17 has proper ports.. it can source as well as sink....
     
  3. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    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.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK

    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!
     
  6. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    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.
     
  7. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    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 (text):

    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 (text):
        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 (text):

    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.
     
  8. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,170
    Likes:
    910
    Location:
    Rochdale UK
    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 (basic):


    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
     
     
  9. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    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.
     
  10. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    EXCELLENT! That solved it. Thank you!
     

Share This Page