SPI Module

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Tom Estes
Registered User
Registered User
Posts: 37
Joined: Thu Dec 14, 2006 4:19 pm
Location: Monkey Island, Oklahoma USA

SPI Module

Post by Tom Estes » Fri Mar 23, 2007 8:35 pm

I'm writing driver software for the SCP1000 mems barometric pressure sensor. I'm attaching the first part of that to demonstrate my problem which is: The sensor works fine so long as I pass constants to the spi.writebyte routine. If I pass a variable byte, garbage is written instead causing the sensor routine to fail.

Code: Select all

Device = 18F2620
Clock = 4


Include "spi.bas"
Include "usart.bas"
Include "convert.bas"
Include "math.bas"

//SCP1000 register addresses
Const   REVIDA = $00,
        DATAWRA = $01,
        ADDPTRA = $02,
        OPERATIONA = $03,
        OPSTATUSA = $04,
        RSTRA = $06,
        STATUSA = 07,
        DATARD8A = $1F,
        DATARD16A = $20,
        TEMPOUTA = $21,
        CFGIA = $00,
        TWIADDIA = $05,
        CFG2IA = $09,
        MODTEST2IA = $2D,
        USERDATA1A = $29,
        USERDATA2A = $2A,
        USERDATA3A = $2B,
        USERDATA4A = $2C,
        scpHiRes = $0A,
        scpHiSpeed = $09,
        scpULoPower = $0B,
        scpLoPower = $0C
        

Dim DRDY As PORTC.1
Dim CSB As PORTC.2

Dim TempF As Float
Dim TempC As Float
Dim PresRaw As LongWord
Dim TempRaw As Word
Dim InHg As Float
Dim StationFt As Float
Dim TempReg As Byte

Function Initialize(pSCPMode As Byte) As Boolean
    Dim DATA8RD As Byte
    Dim TestVar As Byte
    TestVar = $0A
    High(CSB)
    Input(DRDY)
    DelayMS(150)                    //per specs
    //check to see if checksum is OK
    Low(CSB)
    SPI.WriteByte(DATARD8A<<2)      //read DATARD8
    DATA8RD = SPI.ReadByte
    High(CSB)
    If (DATA8RD.0 = 1) Then         //if bit zero set, checksum is OK
        Result = True
    Else
        Result = False
    End If
    //enter low noise configuration
    Low(CSB)
    SPI.WriteByte((ADDPTRA<<2)+2)   //write to ADDPTR
    SPI.WriteByte(MODTEST2IA)       //MODTEST2($2D) address
    High(CSB)
    Low(CSB)
    SPI.WriteByte((DATAWRA<<2)+2)   //write to DATAWR
    SPI.WriteByte($03)              //command $03 - reduce noise level
    High(CSB)
    Low(CSB)
    SPI.WriteByte((OPERATIONA<<2)+2)    //write to OPERATION
    SPI.WriteByte($02)              //command $02 - write DATAWR contents to
                                    //register pointed to by ADDPTR
    High(CSB)           //low noise configuration, SCP1000 is in standby mode
    DelayMS(100)        //delay per specs
    Low(CSB)
    SPI.WriteByte((OPERATIONA<<2)+2)    //write mode to OPERATION
    SPI.WriteByte($0A)
    High(CSB)
End Function
This initialization routine works fine. If however I replace the SPI.WriteByte($0A) - 2 lines up from the end function, with SPI.WriteByte(TestVar) it fails. TestVar is defined as a local variable and assigned the value $0A. What I really want to do is pass pSCPMode to SPI.WriteByte(pSCPMode) so I can initialize to the mode I need. This fails as well. It seems SPI.WriteByte doesn't like variables......or what am I missing?

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Sat Mar 24, 2007 10:17 am

The only difference in passing a constant and variable to the WriteByte() routine is that the constant will move a literal into WREG, then WREG to SSPBuffer. A variable will use a moveff.

There are quite a few errata sheets for the 18F2620 device releating to the MSSP module in SPI mode. It's hard to tell what might apply without knowing the silicon version you have. I think it may be a timing issue, the two writes in succession may cause a write collision on the bus. You could try something like...

Code: Select all

    SPI.WriteByte(TestVar)
    if SPI.WriteCollision then
       high(PORTD.0)
    endif 
Basically just set an LED high if a write collision has occurred. Given that your silicon is happy with the constant 'movlw', you could also try making the following changes to the SPI module 'WriteByte()' routine. Just open the SPI.bas module in the IDE (use the explorer window to click on the SPI include). Unlock the file for editing by double clicking on the padlock icon (just above the code window) and comment out the WriteByte() routine. Try the following.

Code: Select all

public sub WriteByte(pData as WREG)
   SSPBuffer = pData
   repeat
      ClrWDT
   until FBufferIsFull
end sub
With the above, the variable will be moved into WREG before being transferred to SSPBuffer. If that does not work, try this

Code: Select all

public sub WriteByte(pData as byte)
   SSPBuffer = pData
   repeat
      ClrWDT
   until FBufferIsFull
end sub
Let me know if any of the above works for you...

Tom Estes
Registered User
Registered User
Posts: 37
Joined: Thu Dec 14, 2006 4:19 pm
Location: Monkey Island, Oklahoma USA

Post by Tom Estes » Sat Mar 24, 2007 3:54 pm

Spot on David. For your info my silicon version is A3.

The routine works when pData is typed as WREG but doesn't work when typed as byte or SSPBuffer.

It seems I'm uncovering silicon issues that others seem to be able to solve. Sorry about that, maybe as I get a better grip on Swordfish I too can solve them without bothering you.

In any case, thanks for your GREAT support. Where else can one get timely, concise (and so far 100% correct) advice straight from the developer? You amaze me....

If I can provide you with any additional info regarding this issue let me know. Otherwise I'm in good shape....

Tom

User avatar
SteveB
Posts: 23
Joined: Fri Oct 06, 2006 1:40 am
Location: Del Rio, TX

Post by SteveB » Sun Apr 08, 2007 8:35 pm

I was having some trouble with the SPI module as well. I am using an 18F2620, Silicon A4, and was getting some inconsistent reads/writes, especially when doing a lot of TX/RX one after another. After looking at the errata, I changed the ReadByte and WriteByte routines as follows...

Code: Select all

Public Function ReadByte() As SSPBuffer
   SSPIF = 0
   SSPBuffer = 0
   Repeat
      ClrWDT
   Until SSPIF = 1
End Function

Code: Select all

Public Sub WriteByte(pData As WREG) 
   SSPIF = 0
   SSPBuffer = pData 
   Repeat 
      ClrWDT 
   Until SSPIF = 1 
End Sub
Now they use the SSP Interrupt flag instead of the Buffer Full flag (SSPSTAT.0). You will need to add:

Code: Select all

Public Dim SSPIF As PIR1.3
to the Public aliases section.

It also includes the change previously mentioned by Dave to the WriteByte sub, using WREG.

I also added a subroutine to enable the SPI module:

Code: Select all

{
****************************************************************************
* Name    : EnableSPI                                                      *
* Purpose : Enables SPI and reads buffer once, clearing any flags          *
****************************************************************************
}                      
Public Sub EnableSPI()
   Dim pDummy As Byte
   Enabled = true
   pDummy = SSPBuffer
   SSPIF = 0
End Sub

Hopes this helps others you are having trouble with the PIC SPI module.


Steve B

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Tue Apr 10, 2007 11:17 am

Steve

Thanks for that information - very useful indeed. With your permission, I would like to paste the information contained in this post into the SPI.bas modules...

User avatar
SteveB
Posts: 23
Joined: Fri Oct 06, 2006 1:40 am
Location: Del Rio, TX

Post by SteveB » Tue Apr 10, 2007 3:02 pm

No problem with me, I am just happy when I can contribute something useful.

SteveB

Edit: Made a silly comment, realized it afterward.

User avatar
SteveB
Posts: 23
Joined: Fri Oct 06, 2006 1:40 am
Location: Del Rio, TX

Also...

Post by SteveB » Tue Apr 10, 2007 3:35 pm

I also have added the following, but this is just convience:

Code: Select all

Public Compound Sub SPIWrite(WriteByte)
I eventually intend to Overload some of the routines to allow for Words, etc. to be used with the SPIWrite. But it may be a while, so nobody hold there breath waiting. I'll post it eventually when it's done and it works the way it should.

SteveB

Post Reply