MSSP Port Settings for SPI

Discussion in 'Embedded Systems and Microcontrollers' started by jpanhalt, Apr 25, 2015.

  1. jpanhalt

    Thread Starter Expert

    Jan 18, 2008
    Device: 16F1519 (enhanced mid-range) @ 4MHz for testing
    Sensor: AS5048 rotary magnetic encoder
    Language: MPASM
    Simulation: MPLAB ICD3 SIM
    SPI: 3-wire configuration (MOSI) tied high at sensor; TRIS=1 at MCU Master

    I have SPI working with the following code:
    Code (ASM):
    2. ;TABS=5,GUTTER=4,WINDOW=80
    4.      #define   SCK   PORTC,3 ;slave clock, pin18
    5.      #define   SDI   PORTC,4 ;MISO, pin23
    6.      #define   SDO   PORTC,5 ;MOSI, pin24
    7.      #define   CSn   PORTA,5 ;!SS or chip select, pin7
    8.      #define   LED   LATD,0 ;output
    10. ;******************************************************************************    
    11. ;SPI Testing
    12. ;******************************************************************************
    13. ;Seven registers in Bank 4 control the MSSP Modeule used with
    14. ;SPI and I2C communicaton.  In addition TRIS(B2), LAT(B1), and PIR1,SSPIF(B0)
    15. ;are or may by used.  The following applies only to SPI with the MCU as master:
    16. ;SSPSTAT: SMP<7>clear=sample at middle of output time
    17. ;         CKE<6>set=transmit occurs on CLK active to idle,clear=idle to active
    18. ;         <5,1> I2C read only
    19. ;         BF<0>buffer full read only, set=receive complete
    20. ;SETTING: SSPSTAT=clear
    21. ;SSPCON1: WCOL<7>I2C only
    22. ;         SSPOV<6>SSPBUF overflow error, not used in Master Mode
    23. ;         SSPEN<5>enables serial port SCK,SDO, SDI and !SS(CSn)
    24. ;         CKP<4>clock polarity,1=idle high, 0=idle low,see CKE above
    25. ;         for AS5048 clock idle=low, send data on rising edge
    26. ;         SSPM<3,0> 0010=M.clock=Fosc/64,0001=clock=Fosc/16,0000=clock=Fosc/4
    27. ;SETTING: SSPCON1=00?00010, <5>=SSPEN
    28. ;SSPCON2: <7,1> not used (SPI only)
    29. ;         SEN<0>1=start condition on SDA and SCL pins,0=start condition idle
    30. ;SETTING: &&&&&&&&&&&&&&&&NOT SURE&&&&&&&&&&&&&&&
    31. ;SSPCON3: NOT USED (I2C)
    32. ;SSPMSK : NOT USED (I2C)
    33. ;SSPADD : NOT USED (Baud rate I2C)
    34. ;SSPBUF : Write ti initiate send, read on receipt
    35. ;
    36. ;PIR1,SSPIF:Flag for receipt...should SSPSTAT,BF be used instead?  
    37. ;******************************************************************************
    39. Test0                      ;just a point to return to that shows an error
    41. ;setup serial port
    43.      MOVLB     4           ;SPI controls in Bank4                          |B4
    44.      MOVLW     b'00000001' ;
    45.      MOVWF     SSPCON1     ;master clk=Fosc/16  
    47. ;SSPCON1 <7,6> are read only, setting SSPEN<5> used to toggle SPI port on/off
    48. ;clearing<4> sets idle state for clock low, setting<3-0> low = master clk
    49. ;= Fosc/4, setting 0001 = master clk Fosc/16, <5> enables or resets SSP
    50. ;04.25.15 tried all 3 settings for <3,0>, Fosc/64 did not work, others did,
    51. ;hung up on waiting for the BF flag bit.
    53.      CLRF      SSPCON2     ;                                               |B4
    54.      BSF       SSPCON2,SEN ;1=start condition on SDA aand SCL, 0=idle at start
    55.      CLRF      SSPSTAT     ;                                               |B4
    57. GetSPI
    58.      MOVLB     0              ;                                            |B0
    59.      BCF       CSn            ;                                            |B0
    60.      MOVLB     4              ;                                            |B4
    61.      BSF       SSPCON1,SSPEN  ;enables serial port                         |B4    
    62.      MOVLW     0xFF           ;
    63.      MOVWF     SSPBUF         ;                                            |B4
    64.  ;   CLRF      SSPBUF         ;also works to start
    66. GetBUFF  
    67. ;NB:Polling SSPSTAT,BF seems to work as well as polling PIR1,SSPIF and
    68. ;doesn't require bank switching.    
    69.      btfss     SSPSTAT,BF
    70.      goto      $-1
    71.      movf      SSPBUF,w
    72.      movwf     SPI_H
    73.      CLRF      SSPBUF
    74.      btfss     SSPSTAT,BF
    75.      goto      $-1            
    76.      movf      SSPBUF,w
    77.      movwf     SPI_L        
    78.      BCF       SSPCON1,SSPEN  ;disable SPI port
    79.      movlb     2              ;                                            |B2
    80.      bsf       LATA,5         ;set !SS(CSn)high
    81. ErrTest
    82.      BTFSS     SPI_H,7
    83.      GOTO      Test0
    84.      BTFSC     SPI_H,6
    85.      GOTO      Test0
    86.      BCF       SPI_H,7
    87. ;     DelayCy   (300*msecs)
    88. ;     DelayCy   (300*msecs)
    89.      goto      Test0
    I have gone a bit overboard with comments hoping that will help some readers avoid digging out the datasheet.

    1) I had been polling PIR1,SSPIF as my flag for SSPBUF full, but have switched to polling SSPSTAT,BF instead. Both seem to work. The latter avoids switching banks. So long as I am not using interrupts, is there any reason not to ignore SSPIF and just monitor BF?
    2) SSPCON1,SSPM (ratio of SPI clock to Fosc): Fosc/4 and Fosc/16 work fine. Fosc/64 doesn't work in simulation . It hangs during polling. Any reason not to stay with Fosc/16?
    3) Sequence of clearing CSn vs. setting SPEN? Doing either first works. Setting SPEN first seemed to make more sense, but clearing CSn first requires fewer bank changes. Nothing really seems to happen until SSPBUF is written.
    4) SSPCON2,SEN : I am perplexed by what this does. I understand the description, but setting or clearing it doesn't seem to make a difference.This is the one question for which I am most clueless and worried. If it is not supposed to make a difference, why is it there for SPI? (I understand its use in slave mode.)

    Sorry for the long question, most of it is code.


  2. Papabravo


    Feb 24, 2006
    1) You should review what causes each bit to be set and reset. IIRC the interrupt flag needs to be RESET manually in software. The BF may not require that step. As long as SPI interrupts are disabled it should not be a problem to ignore the interrupt flag.
    2) As long as Fosc/16 allows you to choose an appropriate clock there is no reason to slow things down that I can think of. Only if you were dealing with an SPI peripheral that could not keep up with the required data transfers.
    3) Normally you would have CSn inactive (high(?)) and enable SPEN once at the end of initialization. For there on you would use CSn to enable the peripheral device conduct your transaction and return it to the inactive state. If you had multiple SPI peripheral devices you would service each one in turn. The purpose of CSn is select which peripheral you wan to put the return data onto the common bus (MISO).
    4) I'm guessing here, but operating the device in slave mode is different than operating in master mode. The direction of SCLK is reversed and the direction of the data lines is reversed, and lastly if there is a pin called SS_bar, that is the slave select line which you would use to enable transactions with the PIC as a slave device.
    jpanhalt likes this.
  3. jpanhalt

    Thread Starter Expert

    Jan 18, 2008
    Thanks. I am clear on everything except#4.
    #1 As for the IF, reading it clears both. In SPI (caution: simulation), BF is detected, but never seen. The value stays the same in the watch window, but the color changes to red. #2 The sensor's native clock is 5 MHz. I certainly have no need for such high speed readings. This will be for the front-end loader of a tractor.
    #3 That is how I saw it. The real control, though, is writing to SPPBUF.
    #4 My MCU will be master with, probably, two slaves. My assumption is that functionally it doesn't matter. Missing a couple of readings at 0.5 or 1 MHz (i.e., Fosc= 8 or 16 MHz) for a mechanical device won't make a difference. It is just something that gnaws on me.

  4. jpanhalt

    Thread Starter Expert

    Jan 18, 2008
    Problem solved:

    Unlike its usual practice to comment in the MSSP section when some items apply to I2C only, in this case MC did not do that. For another example with the SSPCON2 register, MC shows:

    SDA and SCL are the data pins and clock pins for I2C respectively. So, that setting has no effect on SPI.

    Last edited: Apr 25, 2015