This talks to the AD345XL accelerometer using interrupts without using the arduino library.
It prints a “K” (kinetic, since I’m adding it to other code), then X,Y,Z as three hex digits each.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define TXBUFLEN (256)
static unsigned char txbuf[TXBUFLEN];
static unsigned char txhead;
static unsigned char txtail;
ISR(USART_UDRE_vect)
{
if (txhead == txtail)
UCSR0B &= ~0x20;
else
UDR0 = txbuf[txtail++];
}
void txenqueue(unsigned char *dataOut, unsigned length)
{
// should try to prevent overruns?
while (length--)
txbuf[txhead++] = *dataOut++;
UCSR0B |= 0x20;
}
unsigned char hobuf[8];
static void send2(unsigned char prefix, unsigned char val1, unsigned char val)
{
unsigned char *h = hobuf, i;
*h++ = prefix;
i = val1 & 15;
*h++ = i > 9 ? 'A' - 10 + i : '0' + i;
i = val >> 4;
i &= 15;
*h++ = i > 9 ? 'A' - 10 + i : '0' + i;
i = val & 15;
*h++ = i > 9 ? 'A' - 10 + i : '0' + i;
txenqueue(hobuf, h - hobuf);
}
#if 0
static void send(unsigned char val)
{
unsigned char *h = hobuf, i;
i = val >> 4;
i &= 15;
*h++ = i > 9 ? 'A' - 10 + i : '0' + i;
i = val & 15;
*h++ = i > 9 ? 'A' - 10 + i : '0' + i;
txenqueue(hobuf, h - hobuf);
}
#endif
#define CXXX ((1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // 0x80 4 1
#define CSTR (CXXX|(1<<TWSTA)) // 0x20
#define CXFN CXXX
#define CXFA (CXXX|(1<<TWEA)) // 0x40
#define CSTP (CXXX|(1<<TWSTO)) // 0x10
#define SSTR 0x08
#define SRPS 0x10
#define SAWA 0x18
#define SAWN 0x20
#define SDWA 0x28
#define SDWN 0x30
#define LARB 0x38
#define SARA 0x40
#define SARN 0x48
#define SDRA 0x50
#define SDRN 0x58
struct twist {
unsigned char state; // expected
unsigned char data;
unsigned char nextcmd;
unsigned char flag;
};
struct twist statetab[] = {
{0x00, 0x00, CSTP, 0 },
// 1 read 0x39
{SSTR, 0x3a, CXFN, 1 },
{SAWA, 0x39, CXFN, 1 },
{SDWA, 0x00, CSTR, 0 },
{SRPS, 0x3b, CXFN, 1 },
{SARA, 0x00, CXFN, 0 },
{SDRN, 0x00, CSTP, 2 },
// 7 - Read 6 bytes from 0x32
{SSTR, 0x3a, CXFN, 1 },
{SAWA, 0x32, CXFN, 1 },
{SDWA, 0x00, CSTR, 0 },
{SRPS, 0x3b, CXFN, 1 },
{SARA, 0x00, CXFA, 0 },
{SDRA, 0x00, CXFA, 2 },
{SDRA, 0x00, CXFA, 2 },
{SDRA, 0x00, CXFA, 2 },
{SDRA, 0x00, CXFA, 2 },
{SDRA, 0x00, CXFN, 2 },
{SDRN, 0x00, CSTP, 2 },
// 18 - write register to val
{SSTR, 0x3a, CXFN, 1 }, //17
{SAWA, 0x00, CXFN, 4 },
{SDWA, 0x00, CXFN, 4 },
{SDWA, 0x00, CSTP, 0 },
// 22
};
unsigned char twistate, twireturn;
unsigned char twibuf[10], *twiptr;
ISR(TWI_vect) {
if ((TWSR & 0xf8) == statetab[twistate].state ) {
if ( statetab[twistate].flag & 2 )
*twiptr++ = TWDR;
if ( statetab[twistate].flag & 1 )
TWDR = statetab[twistate].data;
if ( statetab[twistate].flag & 4 )
TWDR = *twiptr++;
if( CSTP != statetab[twistate].nextcmd ) {
TWCR = statetab[twistate++].nextcmd;
return;
}
}
twireturn = twistate;
TWCR = CSTP;
twistate = 0;
}
void xfertwi(unsigned char cmd)
{
twistate = cmd;
twiptr = twibuf;
twireturn = 0;
TWCR = CSTR;
while( twistate )
sleep_mode();
}
void writereg(unsigned char reg, unsigned char val)
{
twibuf[0] = reg;
twibuf[1] = val;
xfertwi(18);
return;
}
int main(void)
{
DDRB = 0x20;
PORTB &= ~0x20; // LED
// Crystal based: xtal/16 or xtal/8 for clk / baud - 1
#define BAUD (57600)
UBRR0 = 1000000 / BAUD - 1;
UCSR0C = 0x06; //8N1 (should be this from reset)
UCSR0A = 0xE2; // clear Interrupts, UART at 2x (xtal/8)
UCSR0B = 0x18; // oring in 0x80 would enable rx interrupt
txhead = txtail = 0;
PORTC |= 0x30;
TWCR = CSTP;
TWAMR = TWDR = TWAR = 0;
TWSR = 0;
TWBR = 2;//32;//2
sei();
writereg(0x2d,8);
writereg(0x31,0xb);
writereg(0x38,0x9f);
// writereg(0x2c,0x0a); // rate, default 100hz/A
writereg(0x2c,0x0c); // rate, default 100hz/A
for(;;) {
if( !twistate ) { // data available
if( twireturn == 17 ) {
// print grabbed data
send2( 'K', twibuf[1] , twibuf[0] );
send2( ',', twibuf[3] , twibuf[2] );
send2( ',', twibuf[5] , twibuf[4] );
txenqueue( (unsigned char *) "\r\n", 2);
// fallthrough instead of contiue will keep it busy,
// twireturn = 0;
// else something else needs to break the next sleep
}
if( twireturn != 6 || !twibuf[0] ) {
twibuf[0] = 0;
twistate = 1;
}
else // data ready, grab it
twistate = 7;
twiptr = twibuf;
twireturn = 0;
TWCR = CSTR;
}
sleep_mode();
}
sleep_mode();
}