Code:
A'****************************************************************
'* Name : BMP085_PDS_IMU_B.bas *
'* Author : Ryan O'Hara *
'* Notice : Copyright (c) 2011 OHARARP LLC *
'* : All Rights Reserved *
'* Date : 6/8/2011 *
'* Version : 1.0 *
'* Notes : Getting this device to work was a P.I.T.A *
'****************************************************************
Device = 18F26K22
Xtal = 10
All_Digital = TRUE
;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings
Declare Reminders Off
@ CONFIG_REQ = 0 ; Override Compiler's configuration settings
Asm-
Config FOSC = HSMP ;EC oscillator (medium power, 4-16 MHz)
Config PLLCFG = OFF ;Oscillator used directly
Config PRICLKEN = On ;Primary clock enabled
Config FCMEN = OFF ;Fail-Safe Clock Monitor disabled
Config IESO = OFF ;Oscillator Switchover mode disabled
Config PWRTEN = OFF ;Power up timer disabled
Config BOREN = SBORDIS ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
Config BORV = 190 ;VBOR set to 1.90 V nominal
Config WDTEN = OFF ;Watch dog timer is always disabled. SWDTEN has no effect.
Config WDTPS = 256 ;1:256
Config CCP2MX = PORTC1 ;CCP2 input/output is multiplexed with RC1
Config PBADEN = OFF ;PORTB<5:0> pins are configured as digital I/O on Reset
Config CCP3MX = PORTB5 ;P3A/CCP3 input/output is multiplexed with RB5
Config HFOFST = On ;HFINTOSC output and ready status are not delayed by the oscillator stable status
Config T3CMX = PORTC0 ;T3CKI is on RC0
Config P2BMX = PORTB5 ;P2B is on RB5
Config MCLRE = EXTMCLR ;MCLR pin enabled, RE3 input pin disabled
Config STVREN = On ;Stack full/underflow will cause Reset
Config LVP = On ;Single-Supply ICSP enabled if MCLRE is also 1
Config XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
Config Debug = OFF ;Disabled
Config CP0 = OFF ;Block 0 (000800-003FFFh) not code-protected
Config CP1 = OFF ;Block 1 (004000-007FFFh) not code-protected
Config CP2 = OFF ;Block 2 (008000-00BFFFh) not code-protected
Config CP3 = OFF ;Block 3 (00C000-00FFFFh) not code-protected
Config CPB = OFF ;Boot block (000000-0007FFh) not code-protected
Config CPD = OFF ;Data EEPROM not code-protected
Config WRT0 = OFF ;Block 0 (000800-003FFFh) not write-protected
Config WRT1 = OFF ;Block 1 (004000-007FFFh) not write-protected
Config WRT2 = OFF ;Block 2 (008000-00BFFFh) not write-protected
Config WRT3 = OFF ;Block 3 (00C000-00FFFFh) not write-protected
Config WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
Config WRTB = OFF ;Boot Block (000000-0007FFh) not write-protected
Config WRTD = OFF ;Data EEPROM not write-protected
Config EBTR0 = OFF ;Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
Config EBTR1 = OFF ;Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
Config EBTR2 = OFF ;Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
Config EBTR3 = OFF ;Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
Config EBTRB = OFF ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Endasm-
Declare Reminders On
;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------
' Software Defines (variables and pins)
Dim Upres As Dword 'uncompensated temp reading
Dim wUpres As Word
Dim Cpres As Dword 'compensated pressure
Dim Cpres2 As Dword 'temp variable
Dim CpresHg As Float 'Pres in inHg
Dim Utemp As Dword 'uncompensated pressure reading
Dim wUtemp As Word 'uncompensated pressure reading
Dim CTemp As Float 'Compensated (real) temperature DegC
Dim CtempF As Float 'Compensated (real) temperature DegF
Dim i2c_Reg As Byte 'variable for target i2c register address
Dim idx As Byte
Symbol SCL = PORTC.3 ' I2C clock pin
Symbol SDA = PORTC.4 ' I2C data pin
Symbol OSS = 3 'This value is the Over Sampling Setting for the BMP085
'0 = minimum, 3 = maximum. Also change value in Read_pres if you alter OSS
Dim wAC1h As Byte
Dim wAC1l As Byte
Dim wAC1 As Word
Dim wAC2 As Word
Dim wAC3 As Word
Dim wAC4 As Word
Dim wAC5 As Word
Dim wAC6 As Word
Dim wB1 As Word
Dim wB2 As Word
Dim wMB As Word
Dim wMC As Word
Dim wMD As Word
Dim AC1 As Dword
Dim AC2 As Dword
Dim AC3 As Dword
Dim AC4 As Dword
Dim AC5 As Dword
Dim AC6 As Dword
Dim B1 As Dword
Dim B2 As Dword
Dim MB As Dword
Dim MC As Dword
Dim MD As Dword
Dim X1 As Dword
Dim X2 As Dword
Dim X3 As Dword
Dim B3 As Dword
Dim B4 As Dword
Dim B5 As Dword
Dim B6 As Dword
Dim B7 As Dword
'Main loop -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Main:
GoSub Read_cal
GoSub Read_temp 'get Temp via I2C
GoSub Read_pres
GoSub Cal_temp
GoSub Cal_pres
SerOut PORTB.7,84,["UT=",SDec Utemp," ",13,10]
SerOut PORTB.7,84,["UP=",SDec Upres," ",13,10]
SerOut PORTB.7,84,["TempC = ",SDec CTemp," TempF = ",SDec CtempF,13,10]
SerOut PORTB.7,84,["hPa = ",SDec Cpres," inHg = ",SDec CpresHg,13,10,13,10]
GoTo Main
'SUBROUTINES -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Cal_temp:
'Calculate temperature in 1/10ths of Deg C from lUTemp ' Note 2^15 = 32768 Dec or $8000
X1 = (Utemp - AC6) * AC5
X1 = X1 >> 15
X2 = MC << 11
X2 = X2 / (X1 + MD)
B5 = X1 + X2
CTemp = (B5 + 8) / 160
CtempF = CTemp * 9 / 5
CtempF = CtempF + 32
Return
Cal_pres:
'Calculate pressure in Pascals from uncompensated pressure dUpres (1/100th's of hPa's)
B6 = B5 - 4000
'SerOut PORTB.7,84,["B6=",SDec B6,13,10]
X1 = B2 * B6 * B6
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X1 = (X1 / $1000) / $800
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X2 = (AC2 * B6) / $800
'SerOut PORTB.7,84,["X2=",SDec X2,13,10]
X3 = X1 + X2
'SerOut PORTB.7,84,["X3=",SDec X3,13,10]
B3 = (AC1 * 4 + X3)
'SerOut PORTB.7,84,["B3=",SDec B3,13,10]
B3 = (B3 << OSS) + 2
'SerOut PORTB.7,84,["B3=",SDec B3,13,10]
B3 = B3 >> 2 'OSS = Over Sampling constant set above
'SerOut PORTB.7,84,["B3=",SDec B3,13,10]
X1 = (AC3 * B6) / $2000
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X2 = B1 * B6 * B6
'SerOut PORTB.7,84,["X2=",SDec X2,13,10]
X2 = (X2 / $1000) / $10000
'SerOut PORTB.7,84,["X2=",SDec X2,13,10]
X3 = X1 + X2 + 2
'SerOut PORTB.7,84,["X3=",SDec X3,13,10]
X3 = X3 / 4
'SerOut PORTB.7,84,["X3=",SDec X3,13,10]
B4 = AC4 * (X3 + 32768)
'SerOut PORTB.7,84,["B4=",SDec B4,13,10]
B4 = B4 / $8000
'SerOut PORTB.7,84,["B4=",SDec B4,13,10]
B7 = Upres - B3
'SerOut PORTB.7,84,["B7=",SDec B7,13,10]
B7 = B7 * (50000 >> OSS) 'OSS = Over Sampling constant set above
'SerOut PORTB.7,84,["B7=",SDec B7,13,10]
If B7 < $80000000 Then 'branch if value is above or below range
Cpres = (B7 * 2) / B4
Else
Cpres = (B7 / B4) * 2
EndIf
'SerOut PORTB.7,84,["Cpres=",SDec Cpres,13,10]
X1 = Cpres /256
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X1 = X1 * Cpres /256
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X1 = (X1 * 3038) >> 16
'SerOut PORTB.7,84,["X1=",SDec X1,13,10]
X2 = (7357 * Cpres) >> 16
X2 = -X2
'SerOut PORTB.7,84,["X2=",SDec X2,13,10]
Cpres2 = X1 + X2 + 3791
'SerOut PORTB.7,84,["Cpres2=",SDec Cpres2,13,10]
Cpres2 = Cpres2 / 16
'SerOut PORTB.7,84,["Cpres2=",SDec Cpres2,13,10]
Cpres = Cpres + Cpres2 'Cpres is the true pressure in Pa
'SerOut PORTB.7,84,["Cpres=",SDec Cpres,13,10]
CpresHg = Cpres / 3386.0 'Pascals to inHg
Return
Read_cal:
i2c_Reg =$AA 'Start address of the BMP085 calibration data
I2CIn SDA,SCL,$EF,i2c_Reg, [wAC1,wAC2,wAC3,wAC4,wAC5,wAC6,wB1,wB2,wMB,wMC,wMD] 'Read 11 words out of sensor MSB then LSB
AC1 = (wAC1.HighByte<<8) + wAC1.LowByte
AC2 = (wAC2.HighByte<<8) + wAC2.LowByte
AC2 = AC2-65536
AC3 = (wAC3.HighByte<<8) + wAC3.LowByte
AC3 = AC3-65536
AC4 = (wAC4.HighByte<<8) + wAC4.LowByte
AC5 = (wAC5.HighByte<<8) + wAC5.LowByte
AC6 = (wAC6.HighByte<<8) + wAC6.LowByte
B1 = (wB1.HighByte<<8) + wB1.LowByte
B2 = (wB2.HighByte<<8) + wB2.LowByte
MB = (wMB.HighByte<<8) + wMB.LowByte
MB = MB - 65536
MC = (wMC.HighByte<<8) + wMC.LowByte
MC = MC - 65536
MD = (wMD.HighByte<<8) + wMD.LowByte
SerOut PORTB.7,84,["AC1=",SDec AC1,13,10]
SerOut PORTB.7,84,["AC2=",SDec AC2,13,10]
SerOut PORTB.7,84,["AC3=",SDec AC3,13,10]
SerOut PORTB.7,84,["AC4=",SDec AC4,13,10]
SerOut PORTB.7,84,["AC5=",SDec AC5,13,10]
SerOut PORTB.7,84,["AC6=",SDec AC6,13,10]
SerOut PORTB.7,84,["B1=",SDec B1,13,10]
SerOut PORTB.7,84,["B2=",SDec B2,13,10]
SerOut PORTB.7,84,["MB=",SDec MB,13,10]
SerOut PORTB.7,84,["MC=",SDec MC,13,10]
SerOut PORTB.7,84,["MD=",SDec MD,13,10,13,10]
Return
Read_pres:
i2c_Reg = $F4 '$F4 is the control register address
I2COut SDA,SCL,$EE,i2c_Reg,[$F4] 'Write $34+(oss << 6) to set pressure conversion
DelayMS 30 'Delay 10ms after each write (30mS for HiRes results (oss=3))
i2c_Reg = $F6 '$F6 is the result register MSB
I2CIn SDA,SCL,$EF,i2c_Reg,[Upres] 'Read pressure MSB, LSB, XLSB, $F9 ($F9 not actually wanted).
Upres = Upres >> (16 - OSS) 'remove $F9 from result (>>8), and left shift result back to 16 to 19 Bits (OSS value dependant)
Return 'we only want top 19bits of the result.
Read_temp:
i2c_Reg = $F4 '$F4 is the control register address
I2COut SDA,SCL,$EE,i2c_Reg,[$2E] 'Write $2E to set temperature conversion
DelayMS 10 'Delay 10ms after each write
i2c_Reg = $F6 '$F6 is the result register MSB
I2CIn SDA,SCL,$EF,i2c_Reg,[wUtemp] 'Read temperature MSB, LSB.
'SerOut PORTB.7,84,["wut=",Hex wUtemp.HighByte,32,Hex wUtemp.LowByte,13,10]
Utemp = (wUtemp.HighByte<<8) + wUtemp.LowByte
'SerOut PORTB.7,84,["ut=",Hex Utemp.Byte3,32,Hex Utemp.Byte2,32,Hex Utemp.Byte1,32,Hex Utemp.Byte0,32,13,10]
Return