Hi PicNick,
ich hab' mal die Endlosschleife beim Slave ergänzt (das fehlende TWDR war zu Testzwecken, er sollte mir den Statuscode zurückgeben); so schauts momentan aus:
Slave:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/twi.h>
uint8_t i2c_getbyte(void);
void i2c_init(uint8_t Adress);
uint8_t i2c_status(void);
int main (void)
{
DDRD = 0xFF;
uint8_t buffer = 0;
i2c_init(26);
while(1)
{
buffer = i2c_getbyte(); //Empfangen des Bytes
PORTD = buffer; //Ausgabe zur Kontrolle
}
return(0);
void i2c_init(uint8_t Adress)
{
TWSR = 0;
TWAR = (Adress << 1);
TWCR = (1 << TWEA) | (1 << TWEN) | (0 << TWSTA) | (0 << TWSTO);
}
uint8_t i2c_getbyte(void)
{
uint8_t Status = 0;
uint8_t Byte = 0;
//Warten, bis der Slave angesprochen wurde
Status = i2c_status();
Byte = TWDR;
TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (0 << TWSTA) | (0 << TWSTO); //TWINT-Bit zurücksetzen, um nächste Aktion auszulösen
return(Byte);
}
uint8_t i2c_status()
{
//Warten, bis das Interrupt-Bit gesetzt und so das erfolgreiche Ende einer Busaktion angekündigt wurde
while(!(TWCR & (1 << TWINT)));
//Ausmaskieren der Prescaler-Bits und Rückgabe des Statuswertes
return(TWSR & 0xF8);
}
Master:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/twi.h>
void i2c_init (void);
uint8_t i2c_sendbyte (uint8_t Adress, uint8_t Data);
uint8_t i2c_status (void);
volatile uint8_t TWIStatus = 0;
int main (void)
{
DDRD = 0xFF;
uint8_t Status = 0;
i2c_init();
Status = i2c_sendbyte (26,15);
PORTD = Status; //Ausgabe des Status zu Debugzwecken
while(1);
return(0);
}
void i2c_init (void)
{
//Einstellen des Bustaktes auf 400kHz:
TWSR = 0;
TWBR = 12;
}
uint8_t i2c_sendbyte (uint8_t Adress, uint8_t Data)
{
uint8_t TWIStatus = 0; //Variable für Fehlercode
//Senden der Startbedingung und zurücksetzen des Flags:
TWCR = (1 << TWSTA) | (1 << TWEN);
//Warten auf Abschluss der Aktion:
TWIStatus = i2c_status();
/* -------------------------------------------------------------------------- */
/* Falls der Bus nicht gerade als "busy" gesetzt ist, wurde das TWI-Interrupt */
/* Bit gesetzt, der Statuswert kann nun ausgelesen werden. */
/* Ist kein Fehler aufgetreten, kann die Adresse mit gesetztem Write-Bit */
/* ausgegeben werden. */
/* -------------------------------------------------------------------------- */
PORTD = TWIStatus;
if ((TWIStatus == 0x08) || (TWIStatus == 0x10))
{
//Zugriff auf Bus erlaubt, nun wird die Slaveadresse mit gesetztem Write-Bit ausgegeben:
TWDR = (Adress << 1) & 0xFE;
TWCR = (1 << TWINT) | (1 << TWEN) | (0 << TWSTA); //TWINT-Bit zurücksetzen, um nächste Aktion auszulösen
//Warten auf Abschluss der Aktion:
TWIStatus = i2c_status();
PORTD = TWIStatus;
if (TWIStatus == 0x18)
{
//Slaveadresse wurde erfolgreich gesendet, nun können Daten verschickt werden:
TWDR = Data;
TWCR = (1 << TWINT) | (1 << TWEN); //TWINT-Bit zurücksetzen, um nächste Aktion auszulösen
//Warten auf Abschluss der Aktion:
TWIStatus = i2c_status();
PORTD = TWIStatus;
if ((TWIStatus == 0x28) || (TWIStatus == 0x30))
{
TWIStatus = 255; //kein Fehler
}
}
}
//Senden der Stoppbedingung:
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
return(TWIStatus);
}
uint8_t i2c_status()
{
//Warten, bis das Interrupt-Bit gesetzt und so das erfolgreiche Ende einer Busaktion angekündigt wurde
while(!(TWCR & (1 << TWINT)));
//Ausmaskieren der Prescaler-Bits und Rückgabe des Statuswertes
return(TWSR & 0xF8);
}
Ich habe mir die Statuscodes beim Master mal angesehen, da schauts so aus, als ob er kein ACK vom Slave bekommt, obwohl bei diesem das TWEA-Bit gesetzt ist.
Viele Grüße
Lesezeichen