Custom I2C Library

I took it on myself to develop a master transmit / receive library for the two wire interface (I2C). Then port this to an interrupt service routine.

I've made good progress. However, I cannot quite seem to figure out how to setup the bus. Problem is this. If I include the wire.h library my code works. I don't even have to call any functions from the library. Just include it. However, if I do not include wire.h the slave will not acknowledge SLA (slave address).

Can any body see what I'm missing to setup the bus? Here's my initialization code:

void setup()
{
Serial.begin(9600);

// Init I2C
PORTC |= 0x18; // Connect Pull-Up resistors
TWSR &= 0xF9; // Set bit rate prescalar (p239)
TWBR = 0x0a; // Set two wire bit rate
TWCR = (1 << TWEN); // Enable I2C
}

I'd take a look at the .h file. It will be something in there.

Hi,

I took it on myself to develop a master transmit / receive library for the two wire interface (I2C). Then port this to an interrupt service routine.

What is wrong with the Wire-lib, I think it does exactly what you want to do?
It can act as a Master, and a Slave. See the index for topic TWI here

Problem is this. If I include the wire.h library my code works. I don't even have to call any functions from the library. Just include it.

The Wire-lib installs an Interrupt-service routine for receiving data,maybe that interfers with your code?

Eberhard Fahle

I'm having trouble getting low level help with the TWI interface. So I think I'll have to use the wire library. I never got far enough on my own to implement an ISR.

My code will transmit and receive. The receive routine matches the implementation example in the Atmel data sheet. However, if I loop it, the code crashes after so many iterations. If I loop the wire implementation it never crashes.

I'm wondering if it's a setup issue. The data sheet is rather lacking in that respect.

Here's the full code:

#include <Wire.h>

#define DEBUG
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22

void setup( void )
{
Serial.begin(9600);

// Init I2C
PORTC |= 0x18; // Connect Pull-Up resistors
TWSR &= 0xF8; // Set bit rate prescalar (p239)
TWBR = 0x0a; // Set two wire bit rate
TWCR = (1 << TWEN);// Enable I2C
}

void loop( void )
{
int i = 0;

while(1)
{
Serial.print( "#: " );
Serial.print( i );

start();
TX( 0x3A );
TX( 0x0F );
start();
TX( 0x3B );
RX();
stop();

Serial.print( " D: " );
Serial.println( TWDR, HEX );

i++;

delay( 1000 );
}
}

void start()
{
// ******* Send Start Sequence
/* TWINT - Clear Interrupt Flag
TWSTA - Transmit start
TWEN - Enable I2C Bus
TWEA - Enable Acknoledge */
TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA) | (1 << TWEA);
while( !(TWCR & (1 << TWINT) ) );

#if defined DEBUG
Serial.print( "STA:" );
Serial.println( TWSR, HEX );
#endif
}

void TX( byte data )
{
// ******* Send register address
TWDR = data;
/* TWINT - Clear Interrupt Flag
TWEN - Enable I2C Bus
TWEA - Enable Acknoledge */
TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN);
while( !(TWCR & (1 << TWINT) ) );

#if defined DEBUG
Serial.print( "TX: " );
Serial.println( TWSR, HEX );
#endif
}

void RX()
{
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
while( !(TWCR & (1 << TWINT) ) );

#if defined DEBUG
Serial.print( "RX: " );
Serial.println( TWSR, HEX );
#endif
}
void stop( void )
{
TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWINT) | (1 |TWSTO);
while( TWCR & (1 << TWINT) );

#if defined DEBUG
Serial.print( "STO:" );
Serial.println( TWSR, HEX );
#endif
}

Hi,

I'm having trouble getting low level help with the TWI interface. So I think I'll have to use the wire library.

Good idea. I havn't seen any complaints about the the Wire-lib around here. so it seems to be working fine for most people.

I never got far enough on my own to implement an ISR.

I don't think you could write a library for the TWI without using Interrupts. (the Wire-sources provide a good example how to do this :slight_smile: )

Sorry, I did not go through your code maybe someone else will do that...
Eberhard

Yeah you can write a library for the I2C not using interrupts but polling instead. Going through the Wire library code I see polling all over the place. However, I'm not able to completely figure out their mnemonics so I don't know exactly what they are polling.

I was going to trigger a state machine off the TWI interrupt bit. Then the machine would transmission based off of the Status Register. There would be a TX buffer and RX buffer to queue the data in. However, I could not get the TWI port to setup correctly.

My motivation for this was to streamline the code as much as possible. I would like to try and read a GPS as well as emulate a USB port on the same microprocessor. So I'll need every scrap of power and space I can muster up.

I'm working to make an inertial referencing circuit that saves it's data on a thumb drive. If there's any space left over I'll also implement a CAN sniffer so I can capture ECU data off a car to the thumb drive as well.

I'm using the Wire library with Arduino and am running into a huge problem. If I request data from devices not on the bus, they reply with the data of the last successful response from a device actually one the bus.

Has anyone run into this problem? Is this a problem with the implementation of the library or an intended design decision.

Is there a way to set the response of a device not yet on the bus? Surely there must be a way around this.

Sounds like the data buffer doesn't get cleared. Makes since. Looking at the wire library I didn't see anywhere where they did do this. But the library is kind of overwhelming so I could have missed something.