Hallo,
ich bin gerade dabei, eine Datenübertragung zwischen zwei ATmega8
mittels dem TWI zu realisieren. Leider stoße ich dabei auf ein paar
Probleme, die wahrscheinlich auf mein Halbwissen zum Thema TWI
zurückzuführen sind ;-)
Ich habe mich schon auf einigen Seiten im Netz belesen und unter anderem
mit Hilfe des Datenblattes ein einfaches Programm geschrieben. Der
Master soll dabei ein Byte an den Slave senden. Mehr ist es bisher
nicht.
Guckst du hier:
Master-Transmitter:
1 | #define F_CPU 3686400
|
2 | #include <avr\io.h>
|
3 | #include <avr\interrupt.h>
|
4 |
|
5 | #define Slave_Adresse_W 0x02 // Slave-Adresse inklusive WRITE-Bit (0)
|
6 |
|
7 | char daten = 0x04;
|
8 |
|
9 | //----Hauptprogramm--------------------------------------------------------
|
10 | int main (void)
|
11 | {
|
12 | DDRD = 0x1C; // LED's zum Auslesen von Fehlern (4-rot,8-gelb,16-grün)
|
13 |
|
14 | TWBR = 10; // Bitrate von 10 ergibt ein SCL von ca. 100kHz
|
15 | sei(); // globale Interrupts freigeben
|
16 |
|
17 | void twi_Start();
|
18 | void twi_Adresse();
|
19 | void twi_Daten();
|
20 | void twi_Stop();
|
21 |
|
22 | while (true) // Mainloop
|
23 | {
|
24 | PORTD = 0x08; // gelbe LED
|
25 | twi_Start();
|
26 | PORTD = 0x08; // gelbe LED
|
27 | twi_Adresse();
|
28 | PORTD = 0x08; // gelbe LED
|
29 | twi_Daten();
|
30 | PORTD = 0x08; // gelbe LED
|
31 | twi_Stop();
|
32 | }
|
33 | return 0;
|
34 | }
|
35 | //-------------------------------------------------------------------------
|
36 |
|
37 | //----Funktionen-----------------------------------------------------------
|
38 | void twi_Start()
|
39 | {
|
40 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Start senden
|
41 | while (!(TWCR & (1<<TWINT))); // warten
|
42 | if ((TWSR & 0xF8) != 0x08){ // Überprüfen, ob Senden erfolgreich
|
43 | PORTD = 0x04; // rote LED (Fehlerbehandlung)
|
44 | waitMs(500);
|
45 | } else {
|
46 | PORTD = 0x10; // grüne LED
|
47 | waitMs(500);
|
48 | }
|
49 | PORTD = 0x00;
|
50 | waitMs(250);
|
51 | }
|
52 |
|
53 | void twi_Adresse()
|
54 | {
|
55 | TWDR = Slave_Adresse_W; // Slave-Adresse in Adressregister übertragen
|
56 | TWCR = (1<<TWINT) | (1<<TWEN); // Slave-Adresse und WRITE-Bit senden
|
57 | while (!(TWCR & (1<<TWINT))); // warten
|
58 | if ((TWSR & 0xF8) != 0x18){ // Überprüfen, ob Senden erfolgreich
|
59 | PORTD = 0x04; // rote LED (Fehlerbehandlung)
|
60 | waitMs(500);
|
61 | } else {
|
62 | PORTD = 0x10; // grüne LED
|
63 | waitMs(500);
|
64 | }
|
65 | PORTD = 0x00;
|
66 | waitMs(250);
|
67 | }
|
68 |
|
69 | void twi_Daten()
|
70 | {
|
71 | TWDR = daten; // zu sendendes Datenbyte in Datenregister uebertragen
|
72 | TWCR = (1<<TWINT) | (1<<TWEN); // Datenbyte senden
|
73 | while (!(TWCR & (1<<TWINT))); // warten
|
74 | if ((TWSR & 0xF8) != 0x28){ // Überprüfen, ob Senden erfolgreich
|
75 | PORTD = 0x04; // rote LED (Fehlerbehandlung)
|
76 | waitMs(500);
|
77 | } else {
|
78 | PORTD = 0x10; // grüne LED
|
79 | waitMs(500);
|
80 | }
|
81 | PORTD = 0x00;
|
82 | waitMs(250);
|
83 | }
|
84 |
|
85 | void twi_Stop()
|
86 | {
|
87 | TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
|
88 | while (!(TWCR & (1<<TWINT))); // warten
|
89 | PORTD = 0x1C; // alle drei LED's
|
90 | waitMs(500);
|
91 | PORTD = 0x00;
|
92 | waitMs(250);
|
93 | }
|
94 | //-----------------------------------------------------------------------------
|
und Slave-Receiver:
1 | #define F_CPU 1000000
|
2 | #include <avr\io.h>
|
3 | #include <avr\interrupt.h>
|
4 |
|
5 | #define Slave_Adresse_GC 0x02 // Slave-Adresse ist 1, GCEN ist 0 (uninteressant)
|
6 |
|
7 | char daten = 0;
|
8 |
|
9 | //----TWI-Interrupt-Routine----------------------------------------------------
|
10 | ISR(TWI_vect){
|
11 | if (TWSR == 0x60) // Adresse erkannt und ACK zurückgesendet
|
12 | PORTD = 0x04;
|
13 |
|
14 | if (TWSR == 0x88) // wenn Daten erfolgreich empfangen
|
15 | PORTD = 0x10;
|
16 | //daten = TWDR; // empfangene Daten sichern
|
17 | }
|
18 | //-----------------------------------------------------------------------------
|
19 |
|
20 | //----Hauptprogramm------------------------------------------------------------
|
21 | int main (void)
|
22 | {
|
23 | DDRD = 0x0C; // LEDs zur Anzeige der Status
|
24 |
|
25 | TWAR = Slave_Adresse_GC; // Slave-Adresse ins Adress-Register schreiben
|
26 | TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
|
27 | sei();
|
28 |
|
29 | while (true)
|
30 | {
|
31 | //PORTD = daten; // empfangene Daten auf PORTD ausgeben
|
32 | }
|
33 | return 0;
|
34 | }
|
35 | //-----------------------------------------------------------------------------
|
Der Master soll anhand der 3 LEDs den aktuellen Status anzeigen, der
Slave soll anzeigen, ob die letzte Aktion erfolgreich war.
Bisherige Beobachtungen: Master blinkt 2 mal hintereinander grün auf,
bleibt dann auf gelb stehen (zwischen dem Senden der Adresse und den
Daten).
Beim Slave leuchtet nach dem zweiten grünen Blinken am Master die LED an
PIN D2 auf (signalisiert, dass der Slave angesprochen und daraufhin ein
ACK gesendet wurde).
Wieso hängt der Master fest? Ist der Code für den Slave zum Empfangen
ausreichend oder hab ich da was falsch verstanden (sehr wahrscheinlich)?