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

16 bit SPI advice needed

Discussion in 'Microcontrollers' started by BobW, Dec 3, 2017.

  1. BobW

    BobW Active Member

    Joined:
    Apr 28, 2010
    Messages:
    525
    Likes:
    54
    Location:
    Canada
    My project of the week (if I'm lucky) involves interfacing a PIC16F1703 to an Analog Devices ADIS16203 digital inclinometer. Both are SPI capable. However, the ADIS16203 works strictly in 16 bit words, and the PIC16F1703 SPI documentation only discusses 8 bit byte transfer. I assume that I just need to read two successive bytes over SPI to get the full 16 bit word from the inclinometer, but I can also see where things could easily go awry (given my past experience with odd serial protocols). In past projects, when things were a bit non-standard, I would just bit bang the data, rather than try to figure out how to set up all of the config registers and config bits. That's what I'd do here (and probably will bit bang it for initial testing), but eventually I want to get this working in an interrupt routine, so I'll have to use the actual SPI port.

    Does anyone here have experience with 16 bit SPI, and tips or example code to share?

    Edit: I should mention that this will be programmed in assembly language.
     
  2. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,173
    Likes:
    529
    Location:
    Cleveland, OH, USA
    ONLINE
    Hi Bob,

    I have done it only a few times. Just like you suggest, you exchange 8 bits at a time. One chip I used was the AK8963 e-compass with a 16F1783. That did a sequential read of several 8-bit registers. Probably closest to what you are doing was reading the AS5048A rotary encoder from AMS. I used a 16F1519 for that. Here's a snippet of the read code. If more will help, let me know, and I will clean up the rest. I typically write a lot of comments to myself, which maybe shouldn't be put in public. Note, bits 15 and 14 were for parity and error, respectively, and had to be stripped off before calculating the encoder result. Here's a link to the datasheet: http://ams.com/eng/Products/Magnetic-Position-Sensors/Angle-Position-On-Axis/AS5048A (Can't link directly to the DS. Just click on the link there.)

    Code (MPASM):

    ;setup serial port
         MOVLB     4              ;SPI controls in Bank4                       |B4
         CLRF      SSPSTAT        ;CKE=0, SMP=0 (sample at middle)                                       |B4
         MOVLW     b'00100000'    ;
         MOVWF     SSPCON1        ;CKP=0,master clk =Fosc/x (see below),
    ;SPEN <5> enabled
    ;04.25.15 tried all 3 settings for <3,0>, Fosc/64 did not work, others did,
    ;hung up on waiting for the BF flag bit. 0001=Fosc/16 should work wtih
    ;all Fosc up to 32 MHz.  0000=Fosc/4. AS5048 internal clock is ca. 5 MHz. ˜˜
     
    GetSPI    
         MOVLB     2              ;                                            |B2
         BCF       CSn            ;!CS                                         |B2
         MOVLB     4              ;                                            |B4
         MOVLW     0xFF           ;alternative to zeros                        |B4                    |B4
         MOVWF     SSPBUF         ;                                            |B4
    ;    CLRF      SSPBUF         ;initiates duplex communication              |B4
                             
    GetBUFF
    ;NB:Polling SSPSTAT,BF seems to work as well as polling PIR1,SSPIF and
    ;doesn't require bank switching.  
         btfss     SSPSTAT,BF
         goto      $-1
         movf      SSPBUF,w
         movwf     SPI_H
         CLRF      SSPBUF
         btfss     SSPSTAT,BF
         goto      $-1
         movf      SSPBUF,w
         movwf     SPI_L    
         movlb     2              ;                                           |B2
         bsf       CSn            ;set !SS(CSn)high                           |B2
    ;    movlb    4                                                           |B4
    ;    BCF       SSPCON1,SSPEN  ;disable SPI port leave running             |B4

    ErrTest
         BTFSC     SPI_H,6        ;checks error bit and returns if set
         GOTO      Test0
         BCF       SPI_H,7        ;clears parity bit so print not effected 08.01.15
         BSF       SPI_H,7    
    ;SET BIT<7> TO FLAG HIGH (MSB) BYTE WHEN SENDING EUSART TO STEPPER
    ;insert save data steps here
         nop
    ;     DelayCy   (150*msecs)
    ;     DelayCy   (150*msecs)
         call      RegPrnt
         goto      GetSPI

     
    John

    EDIT: Just noticed the last 2 steps in the error test section. Ignore one or both. I was using that particular draft of the whole code to drive a stepper motor synchronously to the movement of the encoder input.
     
    Last edited: Dec 4, 2017
  3. BobW

    BobW Active Member

    Joined:
    Apr 28, 2010
    Messages:
    525
    Likes:
    54
    Location:
    Canada
    Thanks John. Much appreciated. I'm completely brain dead tonight, so I'll give your code a good looking over tomorrow.
    BTW, there's no such thing as too many comments.
     
  4. dave

    Dave New Member

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


     
  5. fourtytwo

    fourtytwo Member

    Joined:
    Jul 8, 2016
    Messages:
    30
    Likes:
    1
    Location:
    Boudica's county, UK

    Not much help but to drive a 16bit DAC fast I had to resort to a PIC24F with a 16 bit SPI controller, beware not all 16 bit mcu's have 16 bit SPI only those with fifo buffers!
     
  6. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,378
    Likes:
    920
    Location:
    Rochdale UK
    I use MCP's 12bit DAC... Same protocol as the 16bit.. I use two 8bit SPI transfers with no issue at all using pic16 and pic18...

    SPI has 4 modes.... You just need to make sure the correct mode is selected or you can loose a bit in the middle..
     
  7. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,380
    Likes:
    665
    Location:
    Derbyshire, UK
    ONLINE
    Yes, it's perfectly fine to send two 8 bit bytes, it's the way it's most often done - there seems little advantage in using 16 bit mode on the 24F series, so I don't bother.

    Even if you do, it leaves the identical 'problem' of how do you do 32 bit transfers :D
     
  8. fourtytwo

    fourtytwo Member

    Joined:
    Jul 8, 2016
    Messages:
    30
    Likes:
    1
    Location:
    Boudica's county, UK
    Well I did use the word FAST!!
     
  9. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,378
    Likes:
    920
    Location:
    Rochdale UK
    True... The speed will come from the abilities of the pic24 over the pic16 and pic18.

    To run at 8MHz on a small pic, you have to run at top speed, but the pic32 and pic24 can have different peripheral speeds.. I am testing a small SPI screen on a pic18... I can't achieve max speed ( 10MHz) only 8 or 16MHz..

    Between 8 and 10 there is little difference I know, but it doesn't work at 16!!
     
  10. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,380
    Likes:
    665
    Location:
    Derbyshire, UK
    ONLINE
    Tell me about it!! :D

    On my PIC18F18877, running at 32MHz, I have to run the SPI at div16 (2MHz), it doesn't work at all at div4 (8MHz) - dropping the clock speed to 16MHz allows the use of div4 (4MHz), but at the lower clock speed it runs slightly slower anyway.
     

Share This Page