This is my result:
Memory usage as reported by compiler:
Nothing enabled : 2064 bytes, 200 ram.
with ENABLE_WIRE : 4070 bytes, 408 ram.
with ENABLE_TWI : 3838 bytes, 407 ram.
with ENABLE_JREMINGTON : 2418 bytes, 200 ram.
SoftwareWire : 4284 bytes, 261 ram.
I used a development version of SoftwareWire.
Perhaps the Wire object is created with the twi version as well. I could copy the twi_init and twi_writeTo into my sketch, but have not done that yet.
The Arduino Wire library is the only one that is compatible with other processors of course.
My test sketch:
// What is the difference between the Wire object and calling twi functions.
//
// forum:
// Use of low level libraries
// http://forum.arduino.cc/index.php?topic=392526.0
//
// Tested with Arduino Uno, Arduino IDE 1.6.8 and HMC5883L magnetometer.
// Memory usage as reported by compiler:
// Nothing enabled : 2064 bytes, 200 ram.
// with ENABLE_WIRE : 4070 bytes, 408 ram.
// with ENABLE_TWI : 3838 bytes, 407 ram.
// with ENABLE_JREMINGTON : 2418 bytes, 200 ram.
// SoftwareWire : 4284 bytes, 261 ram. (development version of SoftwareWire)
// select an option
// ----------------
#define ENABLE_WIRE
// #define ENABLE_TWI
// #define ENABLE_JREMINGTON
#ifdef ENABLE_WIRE
#include <Wire.h>
#endif
#ifdef ENABLE_TWI
#include <Wire.h> //I2C library
extern "C"
{
#include <utility/twi.h>
}
#endif
const int compass = 0x1E; // a HMC5883L magnetometer
void setup()
{
Serial.begin(9600);
Serial.println(F( "\nStarted"));
#ifdef ENABLE_WIRE
Wire.begin();
#endif
#ifdef ENABLE_TWI
twi_init();
#endif
#ifdef ENABLE_JREMINGTON
I2C_Init();
#endif
}
void loop()
{
#ifdef ENABLE_WIRE
Wire.beginTransmission( compass);
int status = Wire.endTransmission();
Serial.println( status);
#endif
#ifdef ENABLE_TWI
// The 'wait' must 1, or else the return value can not be used.
uint8_t ret = twi_writeTo( compass, NULL, 0, 1 , 1); // length = 0, wait = 1 ?, stop = 1
Serial.println( ret);
#endif
#ifdef ENABLE_JREMINGTON
unsigned char det = I2C_Detect( compass<<1);
I2C_Stop();
Serial.println( det);
#endif
delay(1000);
}
#ifdef ENABLE_JREMINGTON
/*
Simple I2C routines
ATmega328 @ 16 MHz Atmel Studio IV/ avr-gcc
*/
#define F_CPU 16000000UL
#include <avr/io.h>
// ---------------------------------------------------------------------------
// I2C (TWI) ROUTINES
//
// The standard clock rate is 100 KHz, and set by I2C_Init
// FIXED I2C_Stop() sjr
#define F_SCL 100000L // I2C clock speed 100 KHz
#define READBIT 1 //low bit of device address for read
#define TW_START 0xA4 // send start condition (TWINT,TWSTA,TWEN)
#define TW_STOP 0x94 // send stop condition (TWINT,TWSTO,TWEN)
#define TW_ACK 0xC4 // return ACK to slave
#define TW_NACK 0x84 // return NACK to slave
#define TW_SEND 0x84 // send data (TWINT,TWEN)
#define TW_READY (TWCR & 0x80) // ready when TWINT returns to logic 1.
#define TW_STATUS (TWSR & 0xF8) // returns value of status register
void I2C_Init(){
// at 16 MHz, the SCL frequency will be 16/(16+2(TWBR)), assuming prescalar of 0.
// so for 100KHz SCL, TWBR = ((F_CPU/F_SCL)-16)/2 = ((16/0.1)-16)/2 = 72
TWSR = 0; // prescalar to zero
TWBR = ((F_CPU/F_SCL)-16)/2; // set SCL frequency in TWI bit register
}
void I2C_Stop(void) {
TWCR=TW_STOP;
// wait for stop condition to be executed on bus
// TWINT is not set after a stop condition!
while(TWCR & _BV(TWSTO));
}
unsigned char I2C_Detect(unsigned char addr){
// look for device at specified address; return 1=found, 0=not found
TWCR = TW_START; // send start condition
while (!TW_READY); //wait
TWDR = addr; // load device's bus address
TWCR = TW_SEND; // and send it
while (!TW_READY);
return (TW_STATUS==0x18); // return 1 if found; 0 otherwise
}
void ShowDevices(void){
// search all 127 addresses, report those present on the I2C bus
for (unsigned char addr=1; addr<128; addr++) {
if (I2C_Detect(addr<<1)) // I2C detected?
printf(" .%02X",addr<<1);
I2C_Stop();
}
}
void I2C_Start (unsigned char slaveAddr) {
I2C_Detect(slaveAddr);
}
unsigned char I2C_Write (unsigned char data) {
// sends a byte to slave
TWDR = data; // load data to be sent
TWCR = TW_SEND; // and send it
while (!TW_READY); // wait
return (TW_STATUS!=0x28); //0 if successful, 1 if not
}
unsigned char I2C_ReadACK () {
// reads a byte from slave
TWCR = TW_ACK; // ack = will read more data
while (!TW_READY); // wait
return TWDR;
//return (TW_STATUS!=0x28);
}
unsigned char I2C_ReadNACK () {
// reads a byte from slave
TWCR = TW_NACK; // nack = not reading more data
while (!TW_READY); // wait
return TWDR;
//return (TW_STATUS!=0x28);
}
void I2C_WriteByte (unsigned char busAddr, unsigned char data) {
// write byte to slave
I2C_Start(busAddr); // send bus address
I2C_Write(data); // then send the byte
I2C_Stop();
}
void I2C_WriteRegister(unsigned char busAddr, unsigned char deviceRegister, unsigned char data){
I2C_Start(busAddr); // send bus address
I2C_Write(deviceRegister); // first unsigned char = device register address
I2C_Write(data); // second unsigned char = data for device register
I2C_Stop();
}
unsigned char I2C_ReadRegister(unsigned char busAddr, unsigned char deviceRegister) {
// read single byte of data in register
unsigned char data = 0;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister); // set register pointer
I2C_Start(busAddr+READBIT); // restart as a read operation
data = I2C_ReadNACK(); // read the register data
I2C_Stop(); // stop
return data;
}
// Read a two-byte word, low order first
signed int I2C_ReadWord(unsigned char busAddr, unsigned char deviceRegister) {
unsigned int data = 0;
unsigned char l;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister | 0x80); // set register pointer, autoincrement
I2C_Start(busAddr+READBIT); // restart as a read operation
l = I2C_ReadACK(); // read the register data
data |= I2C_ReadNACK(); //read next unsigned char
I2C_Stop(); // stop
return (signed int) ((data<<8)|l);
}
// read a 3 byte value, lowest order byte first
signed long I2C_ReadPressureRaw(unsigned char busAddr, unsigned char deviceRegister) {
unsigned char pxl,pl,ph;
I2C_Start(busAddr); // send device address
I2C_Write(deviceRegister | 0x80); // set register pointer, autoincrement
I2C_Start(busAddr+READBIT); // restart as a read operation
pxl = I2C_ReadACK(); // read ls byte
pl = I2C_ReadACK(); // read middle
ph = I2C_ReadNACK(); // read high
I2C_Stop(); // stop
return (int32_t)ph << 16 | (uint16_t)pl << 8 | pxl;
}
#endif
The signals are the same for Wire and twi:
But the begin and end are shorter for the jremington version: