Ich habe versucht die Sache umzuschreiben. Aber leider läuft jetzt garnix mehr. Und ich weis einfach nicht warum.
MASTER:
Code:
#include <avr/io.h> // I/O Port definitions
#include <avr/interrupt.h> // Interrupt macros
#include <util/twi.h>
#include <util/delay.h>
#define F_CPU 16000000UL //CPU Tackt
unsigned volatile char adresse;
unsigned volatile char daten;
void twi_init(void);
void twi_start(char adresse);
int twi_senden( char daten);
void twi_stop(void);
int main(void)
{
twi_init();
adresse = 0x40;
while(1)
{
twi_start(adresse);
daten = 1;
twi_senden( daten);
_delay_ms(100);
daten = 100;
twi_senden(daten);
_delay_ms(100);
daten = 200;
twi_senden( daten);
_delay_ms(250);
twi_stop();
};
}
void twi_init(void)
{
DDRC &= !((1<<DD0) | (DD1));
PORTC = (1<<DD0) | (1<<DD1);
TWSR = 0x00; //Prescaler
TWBR = 12; //TWI 400khz
};
void twi_start(char adresse)
{
uint8_t twst;
while(1)
{
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //TWI aktivieren und Start condition auslösen
while(!(TWCR & (1<<TWINT))); //Warten auf Start condition
twst = TW_STATUS & 0xF8;
//if((TWSR & 0xF8) != 0x08);
if ((twst != TW_START) && (twst != TW_REP_START))continue;
TWDR = adresse /*& (0xFE)*/; //Adresse mit Schreibbit(xxxxxxx0) in Register
TWCR = (1<<TWINT) | (1<<TWEN); //senden
//if((TWSR & 0xF8) != 0x18);
while(!(TWCR & (1<<TWINT))); //warten auf ACK oder NACK
twst = TW_STATUS & 0xF8;
if ((twst == TW_MT_SLA_NACK) || (twst == TW_MR_DATA_NACK))
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
while(TWCR & (1<<TWSTO));
continue;
}
break;
}
}
int twi_senden(char daten)
{
TWDR = daten; //Byte in Datenregister laden
TWCR = (1<<TWINT) | (1<<TWEN); //senden
while (!(TWCR & (1<<TWINT))); //warten auf ACK oder NACK
//if ((TWSR & 0xF8) != 0x28);
//TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //STOP Conditions auslösen
return 0;
};
void twi_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
while(TWCR & (1<<TWSTO));
}
SLAVE:
Code:
#include <avr/io.h> //I/O Port definitions
#include <avr/interrupt.h> //Interrupt macros
#include <util/twi.h> //TWI STATUS
#define F_CPU 16000000UL //CPU Tackt
#define buffer_size 3
unsigned volatile char adresse, daten; //Slaveadresse, Daten
volatile uint8_t buffer_adr;
volatile uint8_t rxbuffer[buffer_size];
//1000 = 1ms(links), 1500 = 1,5ms(mitte), 2000 = 2ms(rechts)
volatile int schulter= 0;
volatile int huefte = 0;
volatile int knie = 0;
void twi_slave(char adresse) //TWI initialisieren
{
TWAR = adresse; //Slaveadresse
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE); //ack, TWI enable, Interupt
TWSR = 0;
buffer_adr=0xFF;
};
//ACK nach empfangenen Daten senden/erwarten
#define TWCR_ACK TWCR = (1<<TWEN) | (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWWC)
//NACK nach empfangenen Daten senden/erwarten
#define TWCR_NACK TWCR =(1<<TWEN) | (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWWC)
ISR(TWI_vect) //TWI Interupt (Ausgelöst bei Bus Ereignis)
{
switch(TW_STATUS) //TWI-Statusregister prüfen und agieren
{
case TW_SR_SLA_ACK: //0x60, Slave Receiver wurde adressiert
TWCR_ACK;
buffer_adr = 0xFF; //ACK
break;
case TW_SR_DATA_ACK: //0x80, Slave Receiver Daten empfangen
daten = TWDR; //Daten auslesen
TWCR_ACK;
if (buffer_adr == 0xFF)
{
if(daten<=buffer_size)
{
buffer_adr = daten;
}
else
{
buffer_adr=0;
}
TWCR_ACK;
}
else
{
rxbuffer[buffer_adr] = daten;
buffer_adr++;
if (buffer_adr<(buffer_size-1))
{
TWCR_ACK;
}
else
{
TWCR_NACK;
}
}
break;
TWCR_NACK; //Ende
}
TWCR |= 0b10000000;
};
int main(void)
{
sei(); //Globale Interupts zulassen
adresse = 0x40; //Slave 1
twi_slave(adresse); //TWI initialisieren
DDRB |= (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3); //B... AUSGANG
PORTB &= ~((1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3)); //B.. Low
while(1)
{
schulter = rxbuffer[1];
huefte = rxbuffer[2];
knie = rxbuffer[3];
if(schulter == 100)
PORTB |= (1<<PORTB1);
if (huefte == 200)
PORTB |= (1<<PORTB2);
}
}
Ich hoffe es hat jemand(du?) eine Idee
Lesezeichen