Menu

First time using SPI, need a little advice

Help
2013-01-25
2013-05-30
  • Tom Poulton

    Tom Poulton - 2013-01-25

    Hi guys,

    I'm trying to use a 16F877 to control an MCP4131 digital pot and have run into difficulties (having no access to a scope doesnt help much either). I'm still a bit confused by everything to do with SPI despite doing a fair bit of googling and reading up.

    Datasheet for digital pot http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf

    OK, so just to confirm firstly have I connected this up correctly, I have connected:

    Pin 1 CS to RA5(CS),    Pin 2 SCK to RC3(SCK),   Pin3 SDI/SDO to RC5(SDO)

    So from what I think I understand so far I have to hold RA5 LOW while using SPItransfer to send data then change it back to High?

    Also as far as I can tell I have to send a channel number then the value, so can i accomplish this using 2 consecutive SPItransfer commands, something like:

    ;Chip Settings
    #chip 16F877,20
    #config OSC=XT
    ;Variables
    Dim DigiPot As byte
    SPIMode MasterFast
    Dir PORTA.5 Out
    Start:
    DigiPot = 0
    Wait 5 s
    DigiPot = 64
    Wait 5 s
    DigiPot = 128
    Wait 5 s
    Goto Start
    '''Send data to Digipot
    Sub SPIsend
        Set PORTA.5 Off
        SPITransfer 2, 
        SPITransfer DigiPot, 
        Set PORTA.5 Off
        Exit Sub
    End Sub
    

    I found this code for a Picaxe, which is what I tried to base my code above from

    SYMBOL CS = C.5 ; chip select pin is tied high
    SYMBOL channel = b0 ; range 0 to 3
    SYMBOL setting = b1 ; range 0 to 255
    SYMBOL index = b2
    channel = %00000010 ; need to get the channel into top 2 bits of byte for MSB_First
    setting = %00000000
    hspisetup spimode00, spifast
    Send_data:
    low CS ; enable chip select
    hspiout (channel, setting) ;
    high CS ; disable chip select
    return
    

    I've trimmed the stuff out where they are setting the value of setting variable, but does it look like my program will produce the same result on the SPI side of things?

    Thanks

     
  • Tom Poulton

    Tom Poulton - 2013-01-25

    Resolved now.

    still experimenting to see what I changed to sort it but this worked ok:

    ;Chip Settings
    #chip 16F877,20
    ;Variables
    Dim DigiPot As byte
    Dir PORTB.5 Out
    Dir PORTC.5 Out
    Dir PORTC.3 Out
    Dir PORTA.5 Out
    SPIMode Master
    Set PORTA.5 On
    DigiPot = 0
    start:
    Set PORTB.5 On
    Do Until DigiPot = 255
        SPIsetpot
        DigiPot = DigiPot+1
        Wait 100 ms
    Loop
    Wait 5 s
    Set PORTB.5 Off
    Do Until DigiPot = 0
        SPIsetpot
        DigiPot = DigiPot-1
        Wait 100 ms
    Loop
    Wait 5 s
    Goto start
    Sub SPIsetpot
        Set PORTA.5 Off
        Wait 10 ms
        SPITransfer 00000010,
        SPITransfer DigiPot,
        Wait 10 ms
        Set PORTA.5 On
        Exit Sub
    End Sub
    
     
  • Tom Poulton

    Tom Poulton - 2013-01-25

    Hmm spoke too soon I think, I tried directly setting values of 0 and 255 and it doesnt seem to work unless I actually ramp the value up/down. Any ideas?

     
  • Tom Poulton

    Tom Poulton - 2013-01-27

    Also spoke too soon about it working, it was working when I tested it out, tried powering the circuit back up and no matter what I seem to do it now doesnt seem to do anything, i've tried adding a delay in the main program loop and one before and after RA5 getting pulled high/low so I can see it with a test meter, I've finally bit the bullet and ordered a secondhand 30mhz scope from fleabay as a) I really could use one and b) this problem is driving me nuts

     
  • kent_twt4

    kent_twt4 - 2013-01-27

    the code for SPITransfer uses some improper syntax:

    SPITransfer 00000010,
    

    For binary numbers, it should be

    SPITransfer b'00000010', 0
    

    Is it necessary to write a '1' to the error code register?  No delays should be required.  If the code still refuses to work, you can try a simple software routine say with the increment, decrement commands?  MOSI, and SCK needs to be initialized to '0':

    sub SPI_Xfer(xfer)
    For clocks = 1 to 8
        If xfer.7 = 1 Then
            MOSI = 1
        Else
            MOSI = 0
        End if
        Rotate xfer Left Simple
        SCK = 1
        If MISO = 1 Then
            xfer.0 = 1
        Else
            xfer.0 = 0
        End If
        SCK = 0
    Next
    end sub
    

    A scope is a really nice tool to have :-).

     
  • Tom Poulton

    Tom Poulton - 2013-01-29

    Thanks for the reply Kent, Can I just double check with you my understanding of the commands required to control the pot, If i understand the datasheet corectly (page 46 - memory map and supported commands) I have to send a 16-bit command to volatile wiper 1 as 2 8 bit commands consisting of '000000nn' and 'nnnnnnnn' where 'n' is the data to be written to the pot wiper, and as i understand it the last two bits of the first byte will always be 0 anyway and the last byte ill hold my value in binary from 0-255. I find getting my head around this kind of thing really difficult so all advice it greatly appreciated.

     
  • kent_twt4

    kent_twt4 - 2013-01-29

    Basically correct; That would be write to wiper0 b'000000nn", or wiper1 b'000100nn' as the first byte.  the MCP4131 is a 7 bit device so per data sheet 0-128 decimal for the said 129 steps of the second byte.  Make sure Master SDO goes to  slave (MCP4131) SDI.

     
  • Tom Poulton

    Tom Poulton - 2013-01-29

    Thanks Kent :)

    I have only tried writing 0's to it so far, I had hooked up the pot across 5v-0V to measure the voltage output, it was happily sitting a 0v so that proves thats working, tomorrow I will try and get it to write a few more values to determine if that works. On the 4131 shares a single pin for SDI/SDO however I dont intend to read values back from it so should it  be ok just to repeatedly send the 1st byte as 0's and the second with the required value and not worry about recieving anything back or checking the error bit as in the circuit I'm using this for (variable PSU) I'll be masuring the controlled voltage on RA0 via a potential divider and if I've got the gist of it, if an error occurs it waits for slave select to go back to high then low and will resume correct operation?

    Cheers

     
  • kent_twt4

    kent_twt4 - 2013-01-29

    Cool that you got it working, as the POR value is 0x40.  I think it was the SPIWrite binary number syntax that was the problem, just that the compiler/assembler didn't complain.  Good luck.

     
  • Tom Poulton

    Tom Poulton - 2013-01-31

    Really appreciated the help, thanks Kent your advice was spot-on :)

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.