SparkFun Forums 

Where electronics enthusiasts find answers.

Your source for all things Atmel.
By SnapBeThrown
#124260
I am having a problem with interfacing my Attiny861 with the magnetic field sensor, the HMC5843. I have the right address, but the chip doesn't drop SDA low when I try to read the ACK bit. A little more about my setup is that it is a single master and a single slave without pull-up resistors. I also am not using the USI features or registers, and manually changing the ports.

The relevant code looks something like this:
Code: Select all

#define F_CPU 1000000UL	// Sets up the default speed for delay.h
#define T2_TWI    5 		// >4,7us
#define T4_TWI    4 		// >4,0us

void i2c_setup(void)
{
	int i;
	unsigned char messageBuf1[MESSAGEBUF1_SIZE] = {0x3C, 0x0A};
	unsigned char size = 2;
	unsigned char temp, data;
	
	USI_TWI_Master_Initialise();
	USI_TWI_Master_Start();					//Send a start command

	USI_TWI_Master_Transfer( messageBuf1[0], 8, 0);	//1st is variable, then bit length, then R/!W
	temp = USI_TWI_Master_Transfer( temp , 1, 1);	//Read ACK
	PORT_LED = (temp);

unsigned char USI_TWI_Master_Transfer( unsigned char a, int b, int c )
{
	int i;
	unsigned char tmp;
	if(c == 0) //write
	{
		DDR_USI |= (1<<PIN_USI_SDA);
		for(i=0;i<b;i++)
		{
			tmp = a;								//Set the Write Data to tmp
			PORT_USI &= ~(1<<PIN_USI_SDA);			// Zero the Data Pin
			PORT_USI |= (0x01&(tmp>>(b-i-1)));		// Put a bit on the bus based on the loop number
			_delay_us(T2_TWI);
 			PORT_USI |= (1<<PIN_USI_SCL);			// Generate positive SCL edge.
			while( !(PIN_USI & (1<<PIN_USI_SCL)) );	// Wait for SCL to go high.
			_delay_us(T4_TWI);
			PORT_USI &= ~(1<<PIN_USI_SCL);			// Pull SCL LOW.
		}
	PORT_USI |= (1<<PORT_USI_SDA);
	}
	else //read
	{
		for(i=0;i<b;i++)
		{
			DDR_USI &= ~(1<<PIN_USI_SDA);   //Set to intput
			_delay_us(T2_TWI);
			PORT_USI |= (1<<PIN_USI_SCL);			// Generate positve SCL edge.
			while( !(PIN_USI & (1<<PIN_USI_SCL)) );	// Wait for SCL to go high.
			tmp = ((PIN_USI & (1<<PIN_USI_SDA))<<(b-i-1));	// Read a bit shifted up by total loop number - number of loops
			_delay_us(T4_TWI);
			PORT_USI &= ~(1<<PIN_USI_SCL);			// Pull SCL LOW.
		}		
	}
	
  
	_delay_us(T2_TWI);
	return tmp;                             // Return the data from the USIDR
}

unsigned char USI_TWI_Master_Start( void )
{
	/* Release SCL to ensure that (repeated) Start can be performed */
	PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
	while( !(PIN_USI & (1<<PIN_USI_SCL)) );          // Verify that SCL becomes high.
	_delay_us(T2_TWI);

	/* Generate Start Condition */
	PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
	_delay_us(T4_TWI);                         
	PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.

  return (TRUE);
}

unsigned char USI_TWI_Master_Stop( void )
{
  DDR_USI |= (1<<PIN_USI_SDA)|(1<PIN_USI_SCL);
  PORT_USI &= ~(1<<PIN_USI_SDA);           // Pull SDA low.
  PORT_USI |= (1<<PIN_USI_SCL);            // Release SCL.
  while( !(PIN_USI & (1<<PIN_USI_SCL)) );  // Wait for SCL to go high.  
	_delay_us(T4_TWI);
  PORT_USI |= (1<<PIN_USI_SDA);            // Release SDA.
	_delay_us(T2_TWI);

  return (TRUE);
}