Hallo Leute

Ich hab hier eine fertige Software von mikrocontroller.net für die USI vom ATTiny26 für einen I²C Slave.

http://www.mikrocontroller.net/topic/38917#287918

Danke an dieser Stelle, falls er es liest

Der Slave scheint einwandfrei zu funktionieren wenn ich nur 1nen Attiny am Bus habe.
Gebe ich aber einen zweiten Tiny hinzu Addressen (0xA0, 0xB0) hab ich das Problem, das mir auf eine Anfrage auf Addresse 0xA0, BEIDE antworten...
Genauso auch umgekehrt, er ignoriert also die Addresse...


Code:

#ifndef _I2C_SLAVE_C_
#define _I2C_SLAVE_C_


#include <avr/io.h>
#include <avr/interrupt.h>
#include "i2c_slave.h"


#define USI_DATA   			USIDR
#define USI_STATUS  		USISR
#define USI_CONTROL 		USICR

//Standart Device Address


#define NONE				0
#define ACK_PR_RX			1
#define BYTE_RX				2
#define ACK_PR_TX			3
#define PR_ACK_TX			4
#define BYTE_TX				5

// Device dependant defines

#define DDR_USI             DDRB
#define PORT_USI            PORTB
#define PIN_USI             PINB
#define PORT_USI_SDA        PORTB0
#define PORT_USI_SCL        PORTB2

#define NONE 				0


volatile unsigned char USI_address = NONE;
volatile uint8_t COMM_STATUS = NONE;
volatile unsigned char send_usi = NONE;


void USI_set(unsigned char data)
{
send_usi = data ;
}

void USI_init(unsigned char address) {
	// Set the Device Address for the Slave Address+1 = Address with Reading 
	USI_address = address;
	// 2-wire mode; Hold SCL on start and overflow; ext. clock
	USI_CONTROL |= (1<<USIWM1) | (1<<USICS1);
	USI_STATUS = 0xf0;  // write 1 to clear flags, clear counter
	DDR_USI  &= ~(1<<PORT_USI_SDA);
	PORT_USI &= ~(1<<PORT_USI_SDA);
	DDR_USI  |=  (1<<PORT_USI_SCL);
	PORT_USI |=  (1<<PORT_USI_SCL);
	// startcondition interrupt enable
	USI_CONTROL |= (1<<USISIE);
}



ISR(USI_STRT_vect) {
    uint8_t tmpUSI_STATUS;
	tmpUSI_STATUS = USI_STATUS;
	COMM_STATUS = NONE;
	// Wait for SCL to go low to ensure the "Start Condition" has completed.
	// otherwise the counter will count the transition
	while ( (PIN_USI & (1<<PORT_USI_SCL)) );
	USI_STATUS = 0xf0; // write 1 to clear flags; clear counter
	// enable USI interrupt on overflow; SCL goes low on overflow
	USI_CONTROL |= (1<<USIOIE) | (1<<USIWM0);
}


ISR(USI_OVF_vect) {

    uint8_t BUF_USI_DATA = USI_DATA;
	switch(COMM_STATUS) {
	case NONE:
		if (((BUF_USI_DATA & 0xfe)) != USI_address & 0xfe) {	// if not receiving my address
			// disable USI interrupt on overflow; disable SCL low on overflow
			USI_CONTROL &= ~((1<<USIOIE) | (1<<USIWM0));
		}
		else { // else address is mine
			DDR_USI  |=  (1<<PORT_USI_SDA);
			USI_STATUS = 0x0e;	// reload counter for ACK, (SCL) high and back low
			if (BUF_USI_DATA & 0x01) COMM_STATUS = ACK_PR_TX; else COMM_STATUS = ACK_PR_RX;
		}
		break;
	case ACK_PR_RX:
		DDR_USI  &= ~(1<<PORT_USI_SDA);
		COMM_STATUS = BYTE_RX;
		break;
	case BYTE_RX:
		/* Save received byte here! ... = USI_DATA*/
		DDR_USI  |=  (1<<PORT_USI_SDA);
		USI_STATUS = 0x0e;	// reload counter for ACK, (SCL) high and back low
		COMM_STATUS = ACK_PR_RX;
		break;
	case ACK_PR_TX:
		/* Put first byte to transmit in buffer here! USI_DATA = ... */
		USI_DATA = send_usi;
		PORT_USI |=  (1<<PORT_USI_SDA); // transparent for shifting data out
		COMM_STATUS = BYTE_TX;
		break;
	case PR_ACK_TX:
		if(BUF_USI_DATA & 0x01) {
			COMM_STATUS = NONE; // no ACK from master --> no more bytes to send
		}
		else {
			/* Put next byte to transmit in buffer here! USI_DATA = ... */
			PORT_USI |=  (1<<PORT_USI_SDA); // transparent for shifting data out
			DDR_USI  |=  (1<<PORT_USI_SDA);
			COMM_STATUS = BYTE_TX;
		}
		break;
	case BYTE_TX:
		DDR_USI  &= ~(1<<PORT_USI_SDA);
		PORT_USI &= ~(1<<PORT_USI_SDA);
		USI_STATUS = 0x0e;	// reload counter for ACK, (SCL) high and back low
		COMM_STATUS = PR_ACK_TX;
		break;
	}
	USI_STATUS |= (1<<USIOIF); // clear overflowinterruptflag, this also releases SCL
}

#endif
Bis auf ein paar Kleinigkeiten wurde am Code eigentlich nichts geändert. Sieht wer den Fehler?

mfg