Това е програма за четене на данни от датчик за налягане bmp085 и изчисляване на реалните температура и атмосферно налягане използвайки целочислена аритметика. В случая се използва DSPIC33FJ256MC710 микроконтролер на Microchip, но би трябвало да работи и с всеки друг. За извеждане на данните се използва двуредов дисплей.
#include „./dspic33.h“
#INCLUDE <math.h>
#use delay(clock=20000000)
//#use rs232(UART1,baud=19200,parity=N,bits=8,stream=uart1)
#use i2c(Master,Fast,sda=PIN_G3,scl=PIN_G2)
#define LCD_RS_PIN PIN_D1////
#define LCD_RW_PIN PIN_D2
#define LCD_ENABLE_PIN PIN_D3 ////
#define LCD_DATA4 PIN_D12 ////
#define LCD_DATA5 PIN_D13 ////
#define LCD_DATA6 PIN_D4 ////
#define LCD_DATA7 PIN_D5
#include <LCD.C>
int oss=0; //oversampling 0-low current 1-standart, 2,3- precision
signed int32 UT ;
unsigned int32 UP;
signed int16 AC1,AC2,AC3;
unsigned int16 AC4,AC5,AC6;
signed int16 B1,B2,MB,MC,MD;
signed int32 X1,X2,B5,temperature,B6,X3,B3, pressure;
unsigned int32 B4,B7;
float altitude;
signed int16 bmp085_read(int reg_address);
void bmp085_write_control(int data);
void main()
{
lcd_init();
lcd_putc(„\fDesigned by\n“);
lcd_putc(„Martin Nikiforov“);
delay_ms(1000);
lcd_putc(„\f“);
AC1=bmp085_read(0xAA); // read parameters from bmp085’s eeprom
AC2=bmp085_read(0xAC);
AC3=bmp085_read(0xAE);
AC4=bmp085_read(0xB0);
AC5=bmp085_read(0xB2);
AC6=bmp085_read(0xB4);
B1=bmp085_read(0xB6);
B2=bmp085_read(0xB8);
MB=bmp085_read(0xBA);
MC=bmp085_read(0xBC);
MD=bmp085_read(0xBE);
oss=3;//0-low current for more accuracy 1,2,3
while(true)
{
bmp085_write_control(0x2E); //0x2E set to measure temperature 4,5ms
delay_ms(5);
UT=(unsigned int16)bmp085_read(0xF6); //read 0xF6 register temperature
bmp085_write_control(0x34+(0x40*oss)); //0x34 – oss=0 set to measure pressure 4,5ms conv
//oss=1 the value must be 0x74 oss =2 0xb4 , oss=3 0xF4
delay_ms(7*(oss+1));
UP=(unsigned int16)bmp085_read(0xF6);//pressure
UP<<=8;
UP=(UP+(((unsigned int16)bmp085_read(0xF8))>>8))>>(8-oss);//XLSB extra precision byte
X1=((UT-AC6)*AC5)>>15;
X2=(((signed int32)MC)<<11)/(X1+MD);
B5=X1+X2;
temperature=(B5+8)>>4;
B6=B5-4000;
X1=(((signed int32)B2)*((B6*B6)/4096))/2048;
X2=(((signed int32)AC2)*B6)/2048;
X3=X1+X2;
B3=((((((signed int32)AC1)*4)+X3)*((int)pow(2,oss)))+2)/4;
X1=(((signed int32)AC3)*B6)/8192;
X2=(((signed int32)B1)*((B6*B6)/4096))/65536;
X3=((X1+X2)+2)/4;
B4=(((unsigned int32)AC4)*(unsigned int32)(X3+32768))>>15;
B7=(unsigned int32)(((unsigned int32)UP)-B3)*(50000>>oss);
if(B7<0x80000000){pressure=(B7<<1)/B4;}
else {pressure=(B7/B4)*2;}
X1=(pressure>>8)*(pressure>>8);
X1=(((unsigned int32)X1)*3038)/65536;
X2=(-7357*pressure)/65536;
pressure=pressure+(X1+X2+3791)/16;
altitude= 44330.0*(1.0-pow((pressure/102325.0),(1/5.255)));
//calculate altitude 102325.0 must be 101325.0 but where i live give me negative altitude
printf(lcd_putc,“\aT=%4.1gC P=%5.1g\nAltitude%6.1g m\n“,temperature/10.0,pressure/100.0,altitude);
// screen refresh slowly when using \f
delay_ms(200);
}
}
signed int16 bmp085_read(int reg_address)
{
int msb,lsb;
int16 data=0;
i2c_start();
i2c_write(0b11101110); // Device address
i2c_write(reg_address); // Data to device
i2c_start(); // Restart
i2c_write(0b11101111); // to change data direction
msb=i2c_read(1); // Now read from slave
lsb=i2c_read(0);
i2c_stop();
data=msb;
data<<=8;
data=data|lsb;
return (data);
}
void bmp085_write_control(int data)
{
i2c_start();
i2c_write(0b11101110);// // Device address
i2c_write(0xF4); //control reg address
i2c_write(data); //write the data
i2c_stop();
}