JeyBee
05.06.2010, 20:22
Moin
Ich hatte mal wieder Zeit, um an meinem TWI (in C) weiter zu machen. Bisher kann ich Daten vom Master (atmega48) zum Slave (atmega8) übertragen.
Nun wollte ich hinzufügen, dass ich ganz einfach ohne Interrupt Daten vom Slave abholen kann (also dass der Slave dem Master daten zur verfügung stellen kann). Nachdem ich das Datenblatt studiert hatte, war ich nicht viel schlauer.
Verstehe ich den Ablauf richtig?
1. Slave-TWI wartet so lange, bis Adr angkommt und setzt dann TWINT auf 1
2. Der Master setzt das Bit 0 auf 1, und sendet so ein READ-Komando.
3. Der Slave gerät so in den sog. "ST"-Modus.
4. Sobald im Statusregister 0xA8 steht, kann ich einen Wert ins TWDR schreiben, der dann der master mit i2c_readNak(); auselsen kann
5. 0xC0 bestätigt übertragung und Nak
Soweit stimmen die Werte des Statusregisters im TWI-Slave auch. Beim Master kriege ich über den i2c_readNak(); Befehl jedoch immer nur 0xCD raus.
Hier mal mein Slave Programm:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h"
#define UART_BAUD_RATE 9600
void twi_slave_init(uint8_t slaveadr)
{
TWAR = slaveadr;
TWCR |= (1<<TWEN) | (1<<TWEA);
}
int main(void)
{
uint8_t transfer; // Datentransfer Variable
uint8_t status; // Statuscode Variable
unsigned char buffer[10]; // Buffer für itoa
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
twi_slave_init(0xCC); // TWI Slave initialisieren & Adresse festloegen
sei();
while(1)
{
while(!(TWCR & 0b10000000)); //solange warten, bis was ankommt
status = TWSR; // Status abfragen..
uart_puts("\r 0x");
uart_puts(itoa(status, buffer, 16)); //Status ausgeben
TWCR &=~ (1<<TWINT); //TWINT auf 0 setzten damit TWI wieder arbeitet
TWCR |= (1<<TWEA); //TWEA auf 1 setzten um Ack zu senden
if(TWSR == 0xA8) //Warten bis Slave Adr mit READ empfangen
{
TWDR = 0xAA; //Zu Übermittelnden Wert in TWDR schreiben
}
}
}
Was mache ich denn falsch?
Gruss Jey
Ich hatte mal wieder Zeit, um an meinem TWI (in C) weiter zu machen. Bisher kann ich Daten vom Master (atmega48) zum Slave (atmega8) übertragen.
Nun wollte ich hinzufügen, dass ich ganz einfach ohne Interrupt Daten vom Slave abholen kann (also dass der Slave dem Master daten zur verfügung stellen kann). Nachdem ich das Datenblatt studiert hatte, war ich nicht viel schlauer.
Verstehe ich den Ablauf richtig?
1. Slave-TWI wartet so lange, bis Adr angkommt und setzt dann TWINT auf 1
2. Der Master setzt das Bit 0 auf 1, und sendet so ein READ-Komando.
3. Der Slave gerät so in den sog. "ST"-Modus.
4. Sobald im Statusregister 0xA8 steht, kann ich einen Wert ins TWDR schreiben, der dann der master mit i2c_readNak(); auselsen kann
5. 0xC0 bestätigt übertragung und Nak
Soweit stimmen die Werte des Statusregisters im TWI-Slave auch. Beim Master kriege ich über den i2c_readNak(); Befehl jedoch immer nur 0xCD raus.
Hier mal mein Slave Programm:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h"
#define UART_BAUD_RATE 9600
void twi_slave_init(uint8_t slaveadr)
{
TWAR = slaveadr;
TWCR |= (1<<TWEN) | (1<<TWEA);
}
int main(void)
{
uint8_t transfer; // Datentransfer Variable
uint8_t status; // Statuscode Variable
unsigned char buffer[10]; // Buffer für itoa
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
twi_slave_init(0xCC); // TWI Slave initialisieren & Adresse festloegen
sei();
while(1)
{
while(!(TWCR & 0b10000000)); //solange warten, bis was ankommt
status = TWSR; // Status abfragen..
uart_puts("\r 0x");
uart_puts(itoa(status, buffer, 16)); //Status ausgeben
TWCR &=~ (1<<TWINT); //TWINT auf 0 setzten damit TWI wieder arbeitet
TWCR |= (1<<TWEA); //TWEA auf 1 setzten um Ack zu senden
if(TWSR == 0xA8) //Warten bis Slave Adr mit READ empfangen
{
TWDR = 0xAA; //Zu Übermittelnden Wert in TWDR schreiben
}
}
}
Was mache ich denn falsch?
Gruss Jey