MS5540C
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 MS_CLK.MS_CLK@ Dim SDI As MS_SDI.MS_SDI@ Dim SDO As MS_SDO.MS_SDO@ // 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 MS_CLK.MS_CLK@ Dim SDI As MS_SDI.MS_SDI@ Dim SDO As MS_SDO.MS_SDO@ // 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