MS5540C

MS5540C Schematic
Easypic4 Dev Board
MS5540C - Product Page

MS5540C Datasheet

AN502 - C Code

This module is setup to use the software shift commands to communicate via the SPI interface of the MS5540C pressure and temperature sensor (Barometer). Overall, the sensor works great and I plan on integrating this with a SHT11 humidity and temperature sensor for some upcoming weather station work.

This sensor compares favorably with the SCP1000 pressure sensor, but has a much friendlier SMT package. I would recommend running an external 32.768 KHz oscillator as referenced in the schematic above, however, some forums have reported that the hardware pwm port of the pic could be configured to proved the necessary MCLK signal when running at a 50% duty cycle.

Code

// DEVICE AND CLOCK
Device = 18F2620
Clock =  40

// DEVICE FUSE CONFIG
Config
    OSC 	= HSPLL,    // HS Oscillator
    FCMEN	= OFF,		// Failsafe Clock Monitor Disabled
    IESO	= OFF,		// Int/Ext Oscillator Switch Over Disabled
    PWRT	= OFF,		// Power Up Timer Disabled
    BOREN	= OFF,		// Brownout Reset Disabled
    WDT     = OFF,		// Watchdog Timer Disabled
    MCLRE	= ON,		// MCLR Enabled
    WDTPS   = 256,       // 15000 x 4mS  = 60 seconds
    LVP     = OFF,      // Low_Voltage Programming
    PBADEN  = OFF       // PORTB Digital 


    Include "UTILS.BAS"
    Include "CONVERT.bas"
    Include "SUART.bas"
    Include "SHIFT.bas"
    Include "MS5540C.bas"

    Dim PRESSURE As Float
    Dim TEMPERATURE As Float

Sub SETUP()
    SetAllDigital()
    SetTX(PORTB.7)
    SetRX(PORTB.6)
    SetBaudrate(sbr9600)
    SetMode(umTrue)
End Sub

SETUP()

While TRUE
    MS5540C.Init()
    MS5540C.CalcPT(PRESSURE,TEMPERATURE)
    UART.Write("Temperature = ",FloatToStr(TEMPERATURE),13,10)                    
    UART.Write("Pressure = ",FloatToStr(PRESSURE),13,10)                    
    UART.Write(13,10) 
    DelayMS(1000)
Wend    

End

Module

Module MS5540C 

    Include "UTILS.BAS"
    Include "SHIFT.bas"    

// DEFAULT MODULE OPTIONS - USER OPTIONS CAN OVERRIDE THESE VALUES...                        
    #option MS_CLK  = PORTC.3                     
    #option MS_SDI  = PORTC.4                    
    #option MS_SDO  = PORTC.5                 

        // Validate CLK pin...
    #if IsOption(MS_CLK) And Not IsValidPortPin(MS_CLK) 
       #error MS_CLK, "Invalid option. CLK must be a valid port pin."
    #endif

        // Validate SDI pin...
    #if IsOption(MS_SDI) And Not IsValidPortPin(MS_SDI) 
       #error MS_SDI, "Invalid option. DI must be a valid port pin."
    #endif

        // Validate SDO pin...
    #if IsOption(MS_SDO) And Not IsValidPortPin(MS_SDO) 
       #error MS_SDO, "Invalid option. DO must be a valid port pin."
    #endif     

// Bring port and pin options into the module...   
    Dim CLK As [email protected]   
    Dim SDI As [email protected]
    Dim SDO As [email protected]

// PRIVATE VARIABLES 
    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim D1 As Word
    Dim D2 As Word

    Dim C1 As Word
    Dim C2 As Word
    Dim C3 As Word
    Dim C4 As Word
    Dim C5 As Word
    Dim C6 As Word
{
****************************************************************************
* Name    : WaitOnDoutFall(PRIVATE)                                              
* Purpose : Wait for SDO line of MS5540C to go low
****************************************************************************
}
Function WaitOnDoutFall() As Boolean
    Dim IDX As Word
    IDX = 0
    While TRUE    
        If SDI = 1 Then
            DelayMS(20)
            Inc(IDX)
                If IDX > 1024 Then
                    result = FALSE
                    Break
                EndIf
        ElseIf SDI = 0 Then
            result = TRUE
            Break
        EndIf    
    Wend

End Function    
{
****************************************************************************
* Name    : Reset_MS(PRIVATE)                                              
* Purpose : Reset the MS5540C
****************************************************************************
}    
Sub Reset_MS()
    Shift.Out(LSB_FIRST,$55,8)
    Shift.Out(LSB_FIRST,$05,8)
    Shift.Out(LSB_FIRST,$00,5)
End Sub 
{
****************************************************************************
* Name    : getW(PRIVATE)                                              
* Purpose : get W1,W2,W3,W4 calibration data
****************************************************************************
}
Sub getW()
    Shift.Out(LSB_FIRST,$57,8)
    Shift.Out(LSB_FIRST,$01,5)
    W1 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$D7,8)
    Shift.Out(LSB_FIRST,$00,5)
    W2 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$37,8)
    Shift.Out(LSB_FIRST,$01,5)
    W3 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$B7,8)
    Shift.Out(LSB_FIRST,$00,5)
    W4 = Shift.In(MSB_POST,16)            

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet
End Sub
{
****************************************************************************
* Name    : getD(PRIVATE)                                              
* Purpose : get D1,D2 - digital pressure and temperature data
****************************************************************************
}
Sub getD()
    // get D1
    Shift.Out(LSB_FIRST,$2F,8)
    Shift.Out(LSB_FIRST,$00,2)    

    Shift.Out(LSB_FIRST,$00,2)
    If WaitOnDoutFall() Then
        D1 = Shift.In(MSB_POST,16)
    EndIf

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet

    //get D2   
    Shift.Out(LSB_FIRST,$4F,8)
    Shift.Out(LSB_FIRST,$00,3)

    Shift.Out(LSB_FIRST,$00,1)
    If WaitOnDoutFall() Then
        D2 = Shift.In(MSB_POST,16)
    EndIf

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet         
End Sub
{
****************************************************************************
* Name    : ConvertWtoC(PRIVATE)                                              
* Purpose : Convert calibration data to coefficients
****************************************************************************
}
Sub ConvertWtoC()
    Dim x As Word
    Dim y As Word

    C1 = (W1 >> 1) And $7FFF

    x = (W3 << 6) And $0FC0
    y = W4 And $003F
    C2 = x Or y

    C3 = (W4 >> 6) And $03FF

    C4 = (W3 >> 6) And $03FF

    x = (W1 << 10) And $0400
    y = (W2 >> 6 ) And $03FF
    C5 = x Or y

    C6 = W2 And $003F
End Sub
{
****************************************************************************
* Name    : CalcPT(PUBLIC)                                              
* Purpose : Calculate pressure and temperature
****************************************************************************
}
Public Sub CalcPT(ByRef PRES As Float, ByRef TEMP As Float)
    Dim UT1 As Float
    Dim dT As Float       

    Dim OFF As Float
    Dim SENS As Float
    Dim X As Float

    getW() //Get the calibration data
    getD() //Get pressure and temperature data
    ConvertWtoC() //Get calibration coefficients

    UT1 = 8 * C5 + 20224           //Calculate Calibration Temperature
    dT  = D2 - UT1                 //Calculate actual temperature
    TEMP = DT * (C6 + 50)
    TEMP = (200 + (TEMP / 1024)) / 10.0 //Temperature in C
    TEMP = (TEMP * 9 /5) + 32   //Temperature in F

    OFF = ((C4 - 512.0) * dT)
    OFF = C2 * 4 + OFF / 4096 

    SENS = (C3 * dT) / 1024
    SENS = C1 + SENS + 24576

    X = SENS * (D1 - 7168.0)
    X = X / 16384 - OFF

    PRES = (((X * 10) / 32) + 2500) / 10.0 //millibars
    PRES = PRES * 0.0295333727 //inches of mercury
End Sub
{
****************************************************************************
* Name    : Init(PUBLIC)                                              
* Purpose : Initialize the pins and MS5540C
****************************************************************************
} 
Public Sub Init()    
    Shift.SetClock(CLK,TRUE) //initialise shiftOUT clock pin, IDLE HIGH
    Shift.SetInput(SDI)
    Shift.SetOutput(SDO) //initialise shiftOUT pin 
    Reset_MS() 
End Sub 

End 

=======

Module

Module MS5540C 

    Include "UTILS.BAS"
    Include "SHIFT.bas"    

// DEFAULT MODULE OPTIONS - USER OPTIONS CAN OVERRIDE THESE VALUES...                        
    #option MS_CLK  = PORTC.3                     
    #option MS_SDI  = PORTC.4                    
    #option MS_SDO  = PORTC.5                 

        // Validate CLK pin...
    #if IsOption(MS_CLK) And Not IsValidPortPin(MS_CLK) 
       #error MS_CLK, "Invalid option. CLK must be a valid port pin."
    #endif

        // Validate SDI pin...
    #if IsOption(MS_SDI) And Not IsValidPortPin(MS_SDI) 
       #error MS_SDI, "Invalid option. DI must be a valid port pin."
    #endif

        // Validate SDO pin...
    #if IsOption(MS_SDO) And Not IsValidPortPin(MS_SDO) 
       #error MS_SDO, "Invalid option. DO must be a valid port pin."
    #endif     

// Bring port and pin options into the module...   
    Dim CLK As [email protected]   
    Dim SDI As [email protected]
    Dim SDO As [email protected]

// PRIVATE VARIABLES 
    Dim W1 As Word
    Dim W2 As Word
    Dim W3 As Word
    Dim W4 As Word

    Dim D1 As Word
    Dim D2 As Word

    Dim C1 As Word
    Dim C2 As Word
    Dim C3 As Word
    Dim C4 As Word
    Dim C5 As Word
    Dim C6 As Word
{
****************************************************************************
* Name    : WaitOnDoutFall(PRIVATE)                                              
* Purpose : Wait for SDO line of MS5540C to go low
****************************************************************************
}
Function WaitOnDoutFall() As Boolean
    Dim IDX As Word
    IDX = 0
    While TRUE    
        If SDI = 1 Then
            DelayMS(20)
            Inc(IDX)
                If IDX > 1024 Then
                    result = FALSE
                    Break
                EndIf
        ElseIf SDI = 0 Then
            result = TRUE
            Break
        EndIf    
    Wend

End Function    
{
****************************************************************************
* Name    : Reset_MS(PRIVATE)                                              
* Purpose : Reset the MS5540C
****************************************************************************
}    
Sub Reset_MS()
    Shift.Out(LSB_FIRST,$55,8)
    Shift.Out(LSB_FIRST,$05,8)
    Shift.Out(LSB_FIRST,$00,5)
End Sub 
{
****************************************************************************
* Name    : getW(PRIVATE)                                              
* Purpose : get W1,W2,W3,W4 calibration data
****************************************************************************
}
Sub getW()
    Shift.Out(LSB_FIRST,$57,8)
    Shift.Out(LSB_FIRST,$01,5)
    W1 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$D7,8)
    Shift.Out(LSB_FIRST,$00,5)
    W2 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$37,8)
    Shift.Out(LSB_FIRST,$01,5)
    W3 = Shift.In(MSB_POST,16)

    Shift.Out(LSB_FIRST,$B7,8)
    Shift.Out(LSB_FIRST,$00,5)
    W4 = Shift.In(MSB_POST,16)            

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet
End Sub
{
****************************************************************************
* Name    : getD(PRIVATE)                                              
* Purpose : get D1,D2 - digital pressure and temperature data
****************************************************************************
}
Sub getD()
    // get D1
    Shift.Out(LSB_FIRST,$2F,8)
    Shift.Out(LSB_FIRST,$00,2)    

    Shift.Out(LSB_FIRST,$00,2)
    If WaitOnDoutFall() Then
        D1 = Shift.In(MSB_POST,16)
    EndIf

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet

    //get D2   
    Shift.Out(LSB_FIRST,$4F,8)
    Shift.Out(LSB_FIRST,$00,3)

    Shift.Out(LSB_FIRST,$00,1)
    If WaitOnDoutFall() Then
        D2 = Shift.In(MSB_POST,16)
    EndIf

    Shift.Out(LSB_FIRST,$00,1) // to be compliant with the data sheet         
End Sub
{
****************************************************************************
* Name    : ConvertWtoC(PRIVATE)                                              
* Purpose : Convert calibration data to coefficients
****************************************************************************
}
Sub ConvertWtoC()
    Dim x As Word
    Dim y As Word

    C1 = (W1 >> 1) And $7FFF

    x = (W3 << 6) And $0FC0
    y = W4 And $003F
    C2 = x Or y

    C3 = (W4 >> 6) And $03FF

    C4 = (W3 >> 6) And $03FF

    x = (W1 << 10) And $0400
    y = (W2 >> 6 ) And $03FF
    C5 = x Or y

    C6 = W2 And $003F
End Sub
{
****************************************************************************
* Name    : CalcPT(PUBLIC)                                              
* Purpose : Calculate pressure and temperature
****************************************************************************
}
Public Sub CalcPT(ByRef PRES As Float, ByRef TEMP As Float)
    Dim UT1 As Float
    Dim dT As Float       

    Dim OFF As Float
    Dim SENS As Float
    Dim X As Float

    getW() //Get the calibration data
    getD() //Get pressure and temperature data
    ConvertWtoC() //Get calibration coefficients

    UT1 = 8 * C5 + 20224           //Calculate Calibration Temperature
    dT  = D2 - UT1                 //Calculate actual temperature
    TEMP = DT * (C6 + 50)
    TEMP = (200 + (TEMP / 1024)) / 10.0 //Temperature in C
    TEMP = (TEMP * 9 /5) + 32   //Temperature in F

    OFF = ((C4 - 512.0) * dT)
    OFF = C2 * 4 + OFF / 4096 

    SENS = (C3 * dT) / 1024
    SENS = C1 + SENS + 24576

    X = SENS * (D1 - 7168.0)
    X = X / 16384 - OFF

    PRES = (((X * 10) / 32) + 2500) / 10.0 //millibars
    PRES = PRES * 0.0295333727 //inches of mercury
End Sub
{
****************************************************************************
* Name    : Init(PUBLIC)                                              
* Purpose : Initialize the pins and MS5540C
****************************************************************************
} 
Public Sub Init()    
    Shift.SetClock(CLK,TRUE) //initialise shiftOUT clock pin, IDLE HIGH
    Shift.SetInput(SDI)
    Shift.SetOutput(SDO) //initialise shiftOUT pin 
    Reset_MS() 
End Sub 

End