/* 8-6-06 3-6-07 Copyright Spark Fun Electronics© 2007 Nathan Seidle nathan at sparkfun.com SCP1000-D01 SPI pressure sensor ATmega8 with a USB interface over an FT232RL VCP connection. mods by Jim Remington, sjames_remington at yahoo dot com */ #include #include #include #include #define DEBUG #define FOSC 8000000 //internal RC #define BAUD 9600 #define MYUBRR FOSC/16/BAUD-1 #define sbi(var, mask) ((var) |= (uint8_t) (1 << mask)) #define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask)) // PORT bit definitions // PORTB #define STATUS_LED 0 // PORTC, bit banged SPI for interface with SCP1000 #define SCP_CSB 0 #define SCP_MISO 1 #define SCP_MOSI 2 #define SCP_SCK 3 void ioinit (void); // initializes IO void scp_read(void); uint8_t read_register(uint8_t register_name); uint16_t read_register16(uint8_t register_name); void write_register(uint8_t register_name, uint8_t register_value); uint8_t spi_comm(uint8_t outgoing_byte); void print_decimal(uint32_t number, uint8_t place, uint8_t pad); void Delay_us( unsigned int microseconds ); void Delay_ms( unsigned int milliseconds ); static int uart_putchar(char c, FILE *stream); // globals uint32_t pressure,pav,tav; uint16_t counter,temperature; volatile unsigned char global_ticks; volatile unsigned char flag; static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); ISR (TIMER2_OVF_vect) { global_ticks++; if(global_ticks == 250) //250 ticks/second { flag = 1; //One second has hit global_ticks = 0; } TCNT2 = 256-125; //Preload timer 2 for 125 clicks. 8MHz/256 = 31250 incs/sec / 125 => 250 incs/sec } int main (void) { uint8_t x,i; counter = 0; global_ticks=0; ioinit (); //Boot up defaults sbi(PORTB, STATUS_LED); printf("\nPressure Firmware v1.0"); Delay_ms(60); cbi(PORTB, STATUS_LED); // startup error checking for(i=1; i<7; i++) { x = read_register(0x07); //STATUS register if ((x&1)==0) break; //successful if LSB=0 Delay_ms(10); } // reinitialize to fix checksum error //write_register(place, thing) write_register(0x06, 0x01); //write 1 to RSTR (software reset) Delay_ms(60); for(i=1; i<7; i++) { x = read_register(0x07); //STATUS register if ((x&1)==0) break; Delay_ms(10); } x = read_register(0x1F); //DATARD8 register if (x==1) puts("-OK"); else puts("-Startup failure!"); //should equal 1 if eeprom checksum OK //Configure SCP1000 with low noise configuration //===================================== //write_register(place, thing) write_register(0x02, 0x2D); write_register(0x01, 0x03); write_register(0x03, 0x02); Delay_ms(100); //Select High Resolution Mode write_register(0x03, 0x0A); //===================================== while(1) { tav=0; pav=0; for(x=0; x<60; x++) { //60 second average scp_read(); //read pressure and temperature from SCP1000 tav+=temperature; pav+=pressure; while(flag == 0); //wait until 1 second has passed flag = 0; } sbi(PORTB, STATUS_LED); tav=tav/60; pav=pav/60; /* temperature = (90*temperature)/5 + 3200; print_decimal(temperature, 2, 5); printf(" F"); */ print_decimal(pav, 2, 6); printf(","); print_decimal(tav, 1, 3); counter++; printf(","); print_decimal(counter, 0, 6); printf("\n"); cbi(PORTB, STATUS_LED); } return (0); } void ioinit (void) { //1 = output, 0 = input DDRB = (1<> 8; UBRRL = MYUBRR; UCSRB = (1< 0 ; i--) { nums[i] = number % 10; number /= 10; } //Pad the number of spots if (pad <= 10 && (pad > (10 - i)) ) i = 10 - pad; for(i++ ; i < 11 ; i++) { printf("%d", nums[i]); //Check for decimal printing if ( ((i + place) == 10) && (place != 0) ) printf("."); } } // void scp_read(void) { int32_t temp_data; //Wait for new data while(1) { temp_data = read_register(0x07); //Check the status register for bit 6 to go high if (temp_data & 32) break; } temperature = read_register16(0x21); //Read the temperature data temp_data = read_register(0x1F); //Read MSB pressure data - 3 lower bits pressure = read_register16(0x20); temperature /= 2; //This is (temp * 10) / 20 so that the answer of 27.9 comes out as 279 (easier to print) temp_data <<= 16; //Shift it pressure = temp_data | pressure; pressure >>= 2; } static int uart_putchar(char c, FILE *stream) { if (c == '\n') uart_putchar('\r', stream); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return 0; } //Read 8-bit register uint8_t read_register(uint8_t register_name) { uint8_t in_byte; register_name <<= 2; register_name &= 0b11111100; //Read command cbi(PORTC, SCP_CSB); //Select SPI Device in_byte = spi_comm(register_name); //Write byte to device //in_byte is nothing, we need to clock in another 8 bits in_byte = spi_comm(0x00); //Send nothing, but we should get back the register value sbi(PORTC, SCP_CSB); return(in_byte); } //Read 16-bit register uint16_t read_register16(uint8_t register_name) { uint16_t in_byte; register_name <<= 2; register_name &= 0b11111100; //Read command cbi(PORTC, SCP_CSB); //Select SPI Device in_byte = spi_comm(register_name); //Write byte to device //in_byte is nothing, we need to clock in another 8 bits in_byte = spi_comm(0x00); //Send nothing, but we should get back the register value in_byte <<= 8; in_byte |= spi_comm(0x00); //Send nothing, but we should get back the register value sbi(PORTC, SCP_CSB); return(in_byte); } //Sends a write command to SCP1000 void write_register(uint8_t register_name, uint8_t register_value) { uint8_t in_byte; register_name <<= 2; register_name |= 0b00000010; //Write command cbi(PORTC, SCP_CSB); //Select SPI device in_byte = spi_comm(register_name); //Send register location in_byte = spi_comm(register_value); //Send value to record into register sbi(PORTC, SCP_CSB); //Return nothing } //Basic SPI send and receive uint8_t spi_comm(uint8_t outgoing_byte) { uint8_t incoming_byte, x; incoming_byte = 0; for(x = 8 ; x > 0 ; x--) { cbi(PORTC, SCP_SCK); //Toggle the SPI clock //Put bit on SPI data bus if(outgoing_byte & (1 << (x-1))) sbi(PORTC, SCP_MOSI); else cbi(PORTC, SCP_MOSI); sbi(PORTC, SCP_SCK); //Read bit on SPI data bus incoming_byte <<= 1; if ( (PINC & (1 << SCP_MISO)) ) incoming_byte |= 1; } return(incoming_byte); } /* * Delay_us * * wait in a loop for the specified number of microseconds. * */ void Delay_us( unsigned int microseconds ) { register unsigned int loop_count; /* 8mhz clock, 4 instructions per loop_count */ loop_count = microseconds<<1; __asm__ volatile ( "1: sbiw %0,1" "\n\t" "brne 1b" : "=w" ( loop_count ) : "0" ( loop_count ) ); } /* Delay_ms * * wait in a loop for the specified number of milliseconds. * */ void Delay_ms( unsigned int milliseconds ) { uint16_t i; for ( i = 0; i < milliseconds; ++i ) { Delay_us( 1000 ); } }