// // hello.ADXL343.c // // ADXL343 accelerometer hello-world // 9600 baud FTDI interface // // Neil Gershenfeld 11/8/15 // (c) Massachusetts Institute of Technology 2015 // // This work may be reproduced, modified, distributed, // performed, and displayed for any purpose. Copyright is // retained and must be preserved. The work is provided // as is; no warranty is provided, and users accept all // liability. // #include #include #define output(directions,pin) (directions |= pin) // set port direction for output #define input(directions,pin) (directions &= (~pin)) // set port direction for input #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 102 // bit delay for 9600 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define serial_port PORTB #define serial_direction DDRB #define serial_pin_out (1 << PB2) #define I2C_secondary_address 0x53 // ADXL345 alt address #define I2C_delay() _delay_us(5) #define SCL_pin (1 << PB3) #define SCL_pins PINB #define SCL_port PORTB #define SCL_direction DDRB #define SDA_pin (1 << PB4) #define SDA_pins PINB #define SDA_port PORTB #define SDA_direction DDRB void SCL_write(char bit) { // // write SCL bit // if (bit == 0) { output(SCL_direction,SCL_pin); clear(SCL_port,SCL_pin); } else { input(SCL_direction,SCL_pin); while (pin_test(SCL_pins,SCL_pin) == 0); // check for clock stretching } } void SDA_write(char bit) { // // write SDA bit // if (bit == 0) { output(SDA_direction,SDA_pin); clear(SDA_port,SDA_pin); } else input(SDA_direction,SDA_pin); } void I2C_init() { // // initialize I2C lines // SDA_write(1); SCL_write(1); } char I2C_master_write_byte(unsigned char byte) { // // master write I2C byte // unsigned char bit; // // loop over bits // for (bit = 0; bit < 8; ++bit) { if ((byte & 0x80) == 0) SDA_write(0); else SDA_write(1); SCL_write(1); I2C_delay(); SCL_write(0); I2C_delay(); byte <<= 1; } // // check for ACK // SDA_write(1); SCL_write(1); I2C_delay(); if (pin_test(SDA_pins,SDA_pin) != 0) { // // no ACK, return 1 // return 1; } // // yes ACK, return 0 // SCL_write(0); I2C_delay(); return 0; } char I2C_master_write(unsigned char* data, unsigned char nbytes, unsigned char secondary_address) { // // I2C master write // unsigned char index,ret,secondary_address_write; // // send start // SDA_write(0); I2C_delay(); SCL_write(0); I2C_delay(); // // send secondary address // secondary_address_write = secondary_address << 1; if (I2C_master_write_byte(secondary_address_write) != 0) // // no ACK, return 1 // return 1; // // loop over bytes // for (index = 0; index < nbytes; ++index) { ret = I2C_master_write_byte(data[index]); if (ret != 0) // // no ACK, return 1 // break; // // yes ACK, continue // } // // send stop // SCL_write(1); I2C_delay(); SDA_write(1); I2C_delay(); return ret; } void I2C_master_read_byte(unsigned char* data, unsigned char index, unsigned char nbytes) { // // master read I2C byte // unsigned char byte,bit; SDA_write(1); byte = 0; // // loop over bits // for (bit = 0; bit < 8; ++bit) { SCL_write(1); I2C_delay(); if (pin_test(SDA_pins,SDA_pin) != 0) byte |= (1 << (7-bit)); SCL_write(0); I2C_delay(); } data[index] = byte; if (index < (nbytes-1)) { // // not done, send ACK // SDA_write(0); SCL_write(1); I2C_delay(); SCL_write(0); SDA_write(1); I2C_delay(); } else { // // done, send NACK // SDA_write(1); SCL_write(1); I2C_delay(); SCL_write(0); I2C_delay(); } } char I2C_master_read(unsigned char* data, unsigned char nbytes, unsigned char secondary_address) { // // I2C master read // unsigned char index,secondary_address_read; // // send start // SDA_write(0); I2C_delay(); SCL_write(0); I2C_delay(); // // send secondary address // secondary_address_read = (secondary_address << 1) + 1; if (I2C_master_write_byte(secondary_address_read) == 1) // // no ACK, return 1 // return 1; // // loop over bytes // for (index = 0; index < nbytes; ++index) I2C_master_read_byte(data,index,nbytes); // // send stop // SCL_write(1); I2C_delay(); SDA_write(1); I2C_delay(); return 0; } void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } int main(void) { // // main // unsigned char data[6]; unsigned char ret; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize output pins // set(serial_port, serial_pin_out); output(serial_direction, serial_pin_out); // // main loop // I2C_init(); data[0] = 0x2D; // POWER_CTL register data[1] = 8; // turn on measure bit ret = I2C_master_write(data,2,I2C_secondary_address); while (1) { /* // // read device ID // data[0] = 0x00; // device ID register ret = I2C_master_write(data,1,I2C_secondary_address); ret = I2C_master_read(data,1,I2C_secondary_address); put_char(&serial_port,serial_pin_out,data[0]); */ // // send framing // put_char(&serial_port,serial_pin_out,1); put_char(&serial_port,serial_pin_out,2); put_char(&serial_port,serial_pin_out,3); put_char(&serial_port,serial_pin_out,4); // // read and send data // data[0] = 0x32; // X0 register ret = I2C_master_write(data,1,I2C_secondary_address); ret = I2C_master_read(data,6,I2C_secondary_address); put_char(&serial_port,serial_pin_out,data[0]); put_char(&serial_port,serial_pin_out,data[1]); put_char(&serial_port,serial_pin_out,data[2]); put_char(&serial_port,serial_pin_out,data[3]); put_char(&serial_port,serial_pin_out,data[4]); put_char(&serial_port,serial_pin_out,data[5]); } }