Rev Author Line No. Line
2770 kaklik 1 /*
2 MPL115A1 SPI Digital Barometer Test Code
3 Created on: April 20, 2010
4 By: Jim Lindblom - jim at sparkfun.com
5  
6 This is a simple test program for the MPL115A1 Pressure Sensor (SPI version).
7 UBRR0 is set to 51 and U2X0 is not set, so the baud rate will be 9600@8MHz and 19200@16MHz.
8 Press the spacebar to get the pressure measurement.
9  
10 Hardware: ATmega328 (I used the Arduino Pro platform)
11 Powered at 3.3V, running at 8MHz.
12 The sensor is 5V tolerant, and this code should also work on 5V/16MHz Arduinos.
13  
14 MPL115A1 Breakout ------------- Arduino
15 ----------------- -------
16 SDN ------------------- D9 (PB1)
17 CSN ------------------- D8 (PB0)
18 SDO ------------------- D12 (PB4)
19 SDI ------------------- D11 (PB3)
20 SCK ------------------- D13 (PB5)
21 GND --------------------- GND
22 VDD ------------------- VCC (3.3V)
23  
24 License: CCAv3.0 Attribution-ShareAlike (http://creativecommons.org/licenses/by-sa/3.0/)
25 You're free to use this code for any venture, but I'd love to hear about what you do with it,
26 and any awesome changes you make to it. Attribution is greatly appreciated.
27 */
28  
29 //======================//
30 // Includes //
31 //======================//
32 #include <avr/io.h>
33 #include <stdio.h>
34 #include "MPL115A1.h"
35  
36 //======================//
37 // Macros //
38 //======================//
39 #define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))
40 #define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))
41  
42 //======================//
43 // MPL115A1 Defines //
44 //======================//
45 #define CS 0 //pin for chip select
46 #define SDN 1 // pin for interrupt
47  
48 //======================//
49 // General Functions //
50 //======================//
51 void ioinit(void);
52 void delay_ms(uint16_t x);
53 void delay_us(uint16_t x);
54 static int uart_putchar(char c, FILE *stream);
55 uint8_t uart_getchar(void);
56 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
57  
58 //======================//
59 // MPL115A1 Functions //
60 //======================//
61 void init_SPI(void);
62 void txdata(char data);
63 char rxdata(void);
64 char read(uint8_t address);
65 void write(uint8_t address, char data);
66 float calculatePressure(void);
67  
68 //======================//
69 // Global Variables //
70 //======================//
71 signed char sia0MSB, sia0LSB;
72 signed char sib1MSB, sib1LSB;
73 signed char sib2MSB, sib2LSB;
74 signed char sic12MSB, sic12LSB;
75 signed char sic11MSB, sic11LSB;
76 signed char sic22MSB, sic22LSB;
77 signed int sia0, sib1, sib2, sic12, sic11, sic22, siPcomp;
78 float decPcomp;
79 signed long lt1, lt2, lt3, si_c11x1, si_a11, si_c12x2;
80 signed long si_a1, si_c22x2, si_a2, si_a1x1, si_y1, si_a2x2;
81 unsigned int uiPadc, uiTadc;
82 unsigned char uiPH, uiPL, uiTH, uiTL;
83  
84  
85 int main(void)
86 {
87 ioinit();
88  
89 init_SPI();
90 sbi(PORTB,CS); // CS Idle High
91 sbi(PORTB,SDN); // SDN high turns sensor on
92  
93 printf("\n***************MPR115A1 Test****************\n\n");
94  
95 // main program loop
96 while(1){
97 printf("\nPress space to print pressure\n");
98 while( !(UCSR0A & (1<<RXC0)) )
99 ;
100 if (UDR0 == ' ')
101 printf("Pressure = %f\n", calculatePressure());
102 }
103 }
104  
105 float calculatePressure()
106 {
107 write(0x24, 0x00); // Start Both Conversions
108 // write(0x20, 0x00); // Start Pressure Conversion
109 // write(0x22, 0x00); // Start temperature conversion
110 delay_ms(10); // Typical wait time is 3ms
111  
112 // Read pressure
113 uiPH = read(PRESH);
114 uiPL = read(PRESL);
115 uiTH = read(TEMPH);
116 uiTL = read(TEMPL);
117  
118 uiPadc = (unsigned int) uiPH << 8;
119 uiPadc += (unsigned int) uiPL & 0x00FF;
120 uiTadc = (unsigned int) uiTH << 8;
121 uiTadc += (unsigned int) uiTL & 0x00FF;
122  
123 // Placing Coefficients into 16-bit Variables
124 // a0
125 sia0MSB = read(A0MSB);
126 sia0LSB = read(A0LSB);
127 sia0 = (signed int) sia0MSB << 8;
128 sia0 += (signed int) sia0LSB & 0x00FF;
129  
130 // b1
131 sib1MSB = read(B1MSB);
132 sib1LSB = read(B1LSB);
133 sib1 = (signed int) sib1MSB << 8;
134 sib1 += (signed int) sib1LSB & 0x00FF;
135  
136 // b2
137 sib2MSB = read(B2MSB);
138 sib2LSB = read(B2LSB);
139 sib2 = (signed int) sib2MSB << 8;
140 sib2 += (signed int) sib2LSB & 0x00FF;
141  
142 // c12
143 sic12MSB = read(C12MSB);
144 sic12LSB = read(C12LSB);
145 sic12 = (signed int) sic12MSB << 8;
146 sic12 += (signed int) sic12LSB & 0x00FF;
147  
148 // c11
149 sic11MSB = read(C11MSB);
150 sic11LSB = read(C11LSB);
151 sic11 = (signed int) sic11MSB << 8;
152 sic11 += (signed int) sic11LSB & 0x00FF;
153  
154 // c22
155 sic22MSB = read(C22MSB);
156 sic22LSB = read(C22LSB);
157 sic22 = (signed int) sic22MSB << 8;
158 sic22 += (signed int) sic22LSB & 0x00FF;
159  
160 // Coefficient 9 equation compensation
161 uiPadc = uiPadc >> 6;
162 uiTadc = uiTadc >> 6;
163  
164 // Step 1 c11x1 = c11 * Padc
165 lt1 = (signed long) sic11;
166 lt2 = (signed long) uiPadc;
167 lt3 = lt1*lt2;
168 si_c11x1 = (signed long) lt3;
169  
170 // Step 2 a11 = b1 + c11x1
171 lt1 = ((signed long)sib1)<<14;
172 lt2 = (signed long) si_c11x1;
173 lt3 = lt1 + lt2;
174 si_a11 = (signed long)(lt3>>14);
175  
176 // Step 3 c12x2 = c12 * Tadc
177 lt1 = (signed long) sic12;
178 lt2 = (signed long) uiTadc;
179 lt3 = lt1*lt2;
180 si_c12x2 = (signed long)lt3;
181  
182 // Step 4 a1 = a11 + c12x2
183 lt1 = ((signed long)si_a11<<11);
184 lt2 = (signed long)si_c12x2;
185 lt3 = lt1 + lt2;
186 si_a1 = (signed long) lt3>>11;
187  
188 // Step 5 c22x2 = c22*Tadc
189 lt1 = (signed long)sic22;
190 lt2 = (signed long)uiTadc;
191 lt3 = lt1 * lt2;
192 si_c22x2 = (signed long)(lt3);
193  
194 // Step 6 a2 = b2 + c22x2
195 lt1 = ((signed long)sib2<<15);
196 lt2 = ((signed long)si_c22x2>1);
197 lt3 = lt1+lt2;
198 si_a2 = ((signed long)lt3>>16);
199  
200 // Step 7 a1x1 = a1 * Padc
201 lt1 = (signed long)si_a1;
202 lt2 = (signed long)uiPadc;
203 lt3 = lt1*lt2;
204 si_a1x1 = (signed long)(lt3);
205  
206 // Step 8 y1 = a0 + a1x1
207 lt1 = ((signed long)sia0<<10);
208 lt2 = (signed long)si_a1x1;
209 lt3 = lt1+lt2;
210 si_y1 = ((signed long)lt3>>10);
211  
212 // Step 9 a2x2 = a2 * Tadc
213 lt1 = (signed long)si_a2;
214 lt2 = (signed long)uiTadc;
215 lt3 = lt1*lt2;
216 si_a2x2 = (signed long)(lt3);
217  
218 // Step 10 pComp = y1 + a2x2
219 lt1 = ((signed long)si_y1<<10);
220 lt2 = (signed long)si_a2x2;
221 lt3 = lt1+lt2;
222  
223 // Fixed point result with rounding
224 //siPcomp = ((signed int)lt3>>13);
225 siPcomp = lt3/8192;
226  
227 // decPcomp is defined as a floating point number
228 // Conversion to decimal value from 1023 ADC count value
229 // ADC counts are 0 to 1023, pressure is 50 to 115kPa respectively
230 decPcomp = ((65.0/1023.0)*siPcomp)+50;
231  
232 return decPcomp;
233 }
234  
235 void write(uint8_t address, char data)
236 {
237 //write any data byte to any single address
238 //adds a 0 to the MSB of the address byte (WRITE mode)
239  
240 address &= 0x7F;
241  
242 //printf("\nWriting 0x%x to 0x%x\n", data, address);
243  
244 cbi(PORTB,CS);
245 delay_ms(1);
246 txdata(address);
247 delay_ms(1);
248 txdata(data);
249 delay_ms(1);
250 sbi(PORTB,CS);
251 }
252  
253 char read(uint8_t address)
254 {
255 //returns the contents of any 1 byte register from any address
256 //sets the MSB for every address byte (READ mode)
257  
258 char byte;
259  
260 address |= 0x80;
261  
262 cbi(PORTB,CS);
263 txdata(address);
264 byte = rxdata();
265 sbi(PORTB,CS);
266  
267 return byte;
268 }
269  
270 char rxdata(void)
271 {
272 SPDR = 0x55;
273  
274 while((SPSR&0x80) == 0x00)
275 ;
276  
277 return SPDR;
278 }
279  
280 void txdata(char data)
281 {
282 SPDR = data;
283 while((SPSR&0x80) == 0x00)
284 ;
285 }
286  
287 void init_SPI(void)
288 {
289 sbi(SPCR,MSTR); //make SPI master
290 cbi(SPCR,CPOL); cbi(SPCR,CPHA); //SCL idle low, sample data on rising edge
291 cbi(SPCR,SPR1); cbi(SPCR,SPR0); sbi(SPSR,SPI2X); //Fosc/4 is SPI frequency
292 sbi(SPCR,SPE); //enable SPI
293 }
294  
295 static int uart_putchar(char c, FILE *stream)
296 {
297 if (c == '\n') uart_putchar('\r', stream);
298  
299 loop_until_bit_is_set(UCSR0A, UDRE0);
300 UDR0 = c;
301  
302 return 0;
303 }
304  
305 uint8_t uart_getchar(void)
306 {
307 while( !(UCSR0A & (1<<RXC0)) )
308 ;
309 return(UDR0);
310 }
311  
312  
313 void ioinit (void)
314 {
315 int MYUBRR = 51; // Results in 9600bps@8MHz or 19200bps@16MHz
316  
317 //1 = output, 0 = input
318 //DDRA = 0b00000000; //ADC inputs
319 DDRB = 0b11101111; //MISO input
320 DDRC = 0b11111111; //All outputs
321 DDRD = 0b11111110; //PORTD (RX on PD0)
322 stdout = &mystdout; //Required for printf init
323  
324 UBRR0H = (MYUBRR) >> 8;
325 UBRR0L = MYUBRR;
326 UCSR0B = (1<<RXEN0)|(1<<TXEN0);
327 UCSR0C = (3<<UCSZ00);
328  
329 TCCR2B = (1<<CS21);
330 }
331  
332 //General short delays
333 void delay_ms(uint16_t x)
334 {
335 for (; x > 0 ; x--)
336 delay_us(1000);
337 }
338  
339 //General short delays
340 void delay_us(uint16_t x)
341 {
342 while(x > 256)
343 {
344 TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
345 TCNT2 = 0; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
346 while( (TIFR2 & (1<<TOV2)) == 0);
347  
348 x -= 256;
349 }
350  
351 TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
352 TCNT2= 256 - x; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
353 while( (TIFR2 & (1<<TOV2)) == 0);
354 }
355