Here are two short pieces of code I wrote to test two Sparkfun sensors - the LIS3LV030Z serial accelerometer and the MicroMag3 Magnetometer. These were compiled in AVR Studio 4 using avr-gcc. I used an ATMega16 chip and a serial LCD to output the values, but this can be changed easily enough.
/*
Accelerometer.c - Communicate with LIS3LV030Z serial accelerometer
Written by Frank Kienast in November, 2007
Target is ATMega16 with 12MHz xtal clock.
Sparkfun Serial LCD (9600 baud) connected to TX.
*/
#define F_CPU 12000000
#define BAUD 9600
#define UBRR (((F_CPU / (BAUD * 16UL))) - 1)
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define DD_MOSI DDB5
#define DD_SCK DDB7
#define DD_SS DDB4
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
//Forward declarations
int main();
void init_serial();
void lcd_clear();
void lcd_writec(unsigned char c);
void lcd_writes(char *s);
void lcd_line2();
void init_spi();
uint8_t read_spi(uint8_t adrs);
void write_spi(uint8_t adrs, uint8_t data);
uint8_t spi_comm(uint8_t data);
int main()
{
char s[20];
uint8_t resp;
int delay;
int16_t x = 0, y = 0, z = 0;
int16_t lastx = 0, lasty = 0, lastz = 0;
init_serial();
init_spi();
resp = read_spi(0x0f);
lcd_clear();
sprintf(s,"Response %x",resp);
lcd_writes(s);
for(delay = 0; delay < 1000; delay++)
_delay_ms(1);
//Control register 1 normal mode, x,y,z activated
write_spi(0x20,0b10000111);
//Control register 2 wait for read before next sample
write_spi(0x21,0b01000000);
for(;;)
{
x = read_spi(0x28) | (read_spi(0x29) << 8);
y = read_spi(0x2a) | (read_spi(0x2b) << 8);
z = read_spi(0x2c) | (read_spi(0x2d) << 8);
lcd_clear();
sprintf(s,"%04x %04x",x,y);
lcd_writes(s);
lcd_line2();
sprintf(s,"%04x",z);
lcd_writes(s);
//Turn on LED on PB0 if there is motion
if((abs(x-lastx) > 2) || (abs(y-lasty) > 2) || (abs(z-lastz) > 2))
PORTB |= (1<<0);
else
PORTB &= ~(1<<0);
lastx = x; lasty = y; lastz = z;
//Delay between measurements
for(delay = 0; delay < 100; delay++)
_delay_ms(1);
}
}
void init_serial()
{
// Set baud rate
UBRRH = (UBRR>>8);
UBRRL = UBRR;
// Set frame format: 8data, 1stop bit
UCSRC = (1<<URSEL) |(3<<UCSZ0);
// Enable transmitter
UCSRB = (1<<TXEN);
}
void lcd_clear()
{
lcd_writec(0xfe);
lcd_writec(0x01);
}
void lcd_line2()
{
lcd_writec(0xfe);
lcd_writec(0xc0);
}
void lcd_writec(unsigned char c)
{
// Wait for empty transmit buffer
while ( !( UCSRA & (1<<UDRE)));
// Put data into buffer, sends the data */
UDR = c;
// Wait for empty transmit buffer
while ( !( UCSRA & (1<<UDRE)));
}
void lcd_writes(char *s)
{
int i;
for(i = 0; i < strlen(s); i++)
lcd_writec(s[i]);
}
void init_spi()
{
//SS high
PORT_SPI |= (1<<DD_SS);
// Set MOSI and SCK output, all others input
DDR_SPI = (1 << DD_SS) | (1<<DD_MOSI)|(1<<DD_SCK) | (1<<0);
// Enable SPI, Master, set clock rate fck/64
SPCR = (1<<SPE)|(1<<MSTR)| (1<<SPR1) | (1<<SPR0);
}
uint8_t read_spi(uint8_t adrs)
{
uint8_t data;
//Set read
adrs |= (1 << 7);
//SS low
PORT_SPI &= ~(1<<DD_SS);
//Send address
spi_comm(adrs);
//Read byte
data = spi_comm(0);
//SS high
PORT_SPI |= (1<<DD_SS);
return data;
}
void write_spi(uint8_t adrs, uint8_t data)
{
//SS low
PORT_SPI &= ~(1<<DD_SS);
//Send address
spi_comm(adrs);
//Send byte
spi_comm(data);
//SS high
PORT_SPI |= (1<<DD_SS);
}
uint8_t spi_comm(uint8_t data)
{
// Start transmission
SPDR = data;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
return SPDR;
}
/*
Magnetometer.c - Communicate with MicroMag3 Magnetometer
Written by Frank Kienast in November, 2007
Target is ATMega16 with 12MHz xtal clock.
Sparkfun Serial LCD (9600 baud) connected to TX.
*/
#define F_CPU 12000000
#define BAUD 9600
#define UBRR (((F_CPU / (BAUD * 16UL))) - 1)
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define PIN_SPI PINB
#define DD_MOSI DDB5
#define DD_SCK DDB7
#define DD_SS DDB4
#define DD_RST DDB1
#define DD_RDY DDB0
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Forward declarations
int main();
void init_serial();
void lcd_clear();
void lcd_writec(unsigned char c);
void lcd_writes(char *s);
void lcd_line2();
void init_spi();
uint8_t spi_comm(uint8_t data);
int main()
{
char s[20];
int delay;
int16_t x = 0, y = 0, z = 0, b = 0;
init_serial();
init_spi();
for(;;)
{
//x axis
//lcd_writes("1");
PORT_SPI &= ~(1<<DD_SS);
//Pulse RST
PORT_SPI |= (1<<DD_RST);
_delay_ms(1);
PORT_SPI &= ~(1<<DD_RST);
spi_comm(0b01110001);
while(!(PIN_SPI & (1<<DD_RDY)));
x = (spi_comm(0) << 8) | spi_comm(0);
PORT_SPI |= (1<<DD_SS);
//y axis
//lcd_writes("2");
PORT_SPI &= ~(1<<DD_SS);
//Pulse RST
PORT_SPI |= (1<<DD_RST);
_delay_ms(1);
PORT_SPI &= ~(1<<DD_RST);
spi_comm(0b01110010);
while(!(PIN_SPI & (1<<DD_RDY)));
y = (spi_comm(0) << 8) | spi_comm(0);
PORT_SPI |= (1<<DD_SS);
//z axis
PORT_SPI &= ~(1<<DD_SS);
//Pulse RST
PORT_SPI |= (1<<DD_RST);
_delay_ms(1);
PORT_SPI &= ~(1<<DD_RST);
spi_comm(0b01110011);
while(!(PIN_SPI & (1<<DD_RDY)));
z = (spi_comm(0) << 8) | spi_comm(0);
PORT_SPI |= (1<<DD_SS);
//Net
b = sqrt((double)x*(double)x + (double)y*(double)y + (double)z*(double)z);
lcd_clear();
sprintf(s,"%5d %5d",x,y);
lcd_writes(s);
lcd_line2();
sprintf(s,"%5d %5d",z,b);
lcd_writes(s);
//Delay between measurements
for(delay = 0; delay < 500; delay++)
_delay_ms(1);
}
}
void init_serial()
{
// Set baud rate
UBRRH = (UBRR>>8);
UBRRL = UBRR;
// Set frame format: 8data, 1stop bit
UCSRC = (1<<URSEL) |(3<<UCSZ0);
// Enable transmitter
UCSRB = (1<<TXEN);
}
void lcd_clear()
{
lcd_writec(0xfe);
lcd_writec(0x01);
}
void lcd_line2()
{
lcd_writec(0xfe);
lcd_writec(0xc0);
}
void lcd_writec(unsigned char c)
{
// Wait for empty transmit buffer
while ( !( UCSRA & (1<<UDRE)));
// Put data into buffer, sends the data */
UDR = c;
// Wait for empty transmit buffer
while ( !( UCSRA & (1<<UDRE)));
}
void lcd_writes(char *s)
{
int i;
for(i = 0; i < strlen(s); i++)
lcd_writec(s[i]);
}
void init_spi()
{
//SS high
PORT_SPI |= (1<<DD_SS);
//RST low
PORT_SPI &= ~(1<<DD_RST);
// Set SS, MOSI, SCK, RST output, rest input
DDR_SPI = (1 << DD_SS) | (1<<DD_MOSI) | (1<<DD_SCK) | (1<<DD_RST);
// Enable SPI, Master, set clock rate fck/64
SPCR = (1<<SPE)|(1<<MSTR)| (1<<SPR1) | (1<<SPR0);
}
uint8_t spi_comm(uint8_t data)
{
// Start transmission
SPDR = data;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)));
return SPDR;
}
Frank