MSSP Port Settings for SPI

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
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:
;TABS=5,GUTTER=4,WINDOW=80 

     #define   SCK   PORTC,3 ;slave clock, pin18 
     #define   SDI   PORTC,4 ;MISO, pin23
     #define   SDO   PORTC,5 ;MOSI, pin24
     #define   CSn   PORTA,5 ;!SS or chip select, pin7
     #define   LED   LATD,0 ;output
     
;******************************************************************************    
;SPI Testing
;******************************************************************************
;Seven registers in Bank 4 control the MSSP Modeule used with 
;SPI and I2C communicaton.  In addition TRIS(B2), LAT(B1), and PIR1,SSPIF(B0) 
;are or may by used.  The following applies only to SPI with the MCU as master:
;SSPSTAT: SMP<7>clear=sample at middle of output time
;         CKE<6>set=transmit occurs on CLK active to idle,clear=idle to active
;         <5,1> I2C read only
;         BF<0>buffer full read only, set=receive complete
;SETTING: SSPSTAT=clear
;SSPCON1: WCOL<7>I2C only
;         SSPOV<6>SSPBUF overflow error, not used in Master Mode 
;         SSPEN<5>enables serial port SCK,SDO, SDI and !SS(CSn)
;         CKP<4>clock polarity,1=idle high, 0=idle low,see CKE above
;         for AS5048 clock idle=low, send data on rising edge
;         SSPM<3,0> 0010=M.clock=Fosc/64,0001=clock=Fosc/16,0000=clock=Fosc/4
;SETTING: SSPCON1=00?00010, <5>=SSPEN
;SSPCON2: <7,1> not used (SPI only)
;         SEN<0>1=start condition on SDA and SCL pins,0=start condition idle
;SETTING: &&&&&&&&&&&&&&&&NOT SURE&&&&&&&&&&&&&&&
;SSPCON3: NOT USED (I2C)
;SSPMSK : NOT USED (I2C)
;SSPADD : NOT USED (Baud rate I2C)
;SSPBUF : Write ti initiate send, read on receipt
;
;PIR1,SSPIF:Flag for receipt...should SSPSTAT,BF be used instead?  
;******************************************************************************

Test0                      ;just a point to return to that shows an error

;setup serial port

     MOVLB     4           ;SPI controls in Bank4                          |B4
     MOVLW     b'00000001' ;
     MOVWF     SSPCON1     ;master clk=Fosc/16  

;SSPCON1 <7,6> are read only, setting SSPEN<5> used to toggle SPI port on/off 
;clearing<4> sets idle state for clock low, setting<3-0> low = master clk
;= Fosc/4, setting 0001 = master clk Fosc/16, <5> enables or resets SSP
;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.

     CLRF      SSPCON2     ;                                               |B4
     BSF       SSPCON2,SEN ;1=start condition on SDA aand SCL, 0=idle at start 
     CLRF      SSPSTAT     ;                                               |B4
   
GetSPI
     MOVLB     0              ;                                            |B0
     BCF       CSn            ;                                            |B0
     MOVLB     4              ;                                            |B4
     BSF       SSPCON1,SSPEN  ;enables serial port                         |B4    
     MOVLW     0xFF           ;
     MOVWF     SSPBUF         ;                                            |B4
 ;   CLRF      SSPBUF         ;also works to start
     
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        
     BCF       SSPCON1,SSPEN  ;disable SPI port
     movlb     2              ;                                            |B2
     bsf       LATA,5         ;set !SS(CSn)high
ErrTest
     BTFSS     SPI_H,7
     GOTO      Test0
     BTFSC     SPI_H,6
     GOTO      Test0
     BCF       SPI_H,7
;     DelayCy   (300*msecs)
;     DelayCy   (300*msecs)
     goto      Test0
I have gone a bit overboard with comments hoping that will help some readers avoid digging out the datasheet.

QUESTIONS:
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.

Thanks.

John
 

Papabravo

Joined Feb 24, 2006
21,159
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.
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
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.

John
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
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:
upload_2015-4-25_19-29-4.png

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

John
 
Last edited:
Top