Hallo Wir wollen Daten per SPI von einem ATMega88 zu einem anderen ATMega88 schicken. Wir verwenden folgenden Code: SIGNAL (SIG_SPI) { received_character = SPDR; } void SPI_SlaveInit (void) { DDRB |= (1<<PB4); SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0); } Beim Simulieren springt er auch nach dem setzen der SPI Interrupt Flag in SIGNAL (SIG_SPI) nun wird aber kein Wert vom SPDR in received_character übernommen. received_character haben wir als uint8_t definiert. Kann uns jemand helfen? Deyn
Hallo, habt ihr die Variable received_character auch als volatile deklariert? Grüße Peter
Wir haben es nun so deklariert:
1 | volatile uint8_t received_character; |
Funktioniert aber immer noch nicht.
Hier mal unser kompletter c-Code
1 | volatile uint8_t received_character; |
2 | |
3 | //Variablen
|
4 | bool takt_1s = false; |
5 | bool takt_100ms = false; |
6 | bool takt_10ms = false; |
7 | unsigned int vorteiler = VORTEILER; |
8 | unsigned int zehntel = ZEHNTEL; |
9 | unsigned int hundertstel = HUNDERTSTEL; |
10 | |
11 | //Funktionsprototypen
|
12 | void SPI_SlaveInit (void); |
13 | void timer0 (void); |
14 | |
15 | |
16 | |
17 | int main () |
18 | {
|
19 | //Init
|
20 | sei(); |
21 | SPI_SlaveInit(); //set enable interrupt |
22 | timer0(); |
23 | |
24 | DDRB = 0x0f; |
25 | DDRC = 0x0f; |
26 | DDRD = 0xff; |
27 | |
28 | PORTC = 0x0f; |
29 | |
30 | while(1) |
31 | {
|
32 | if (takt_1s == true) |
33 | {
|
34 | takt_1s = false; |
35 | if (received_character == 1) |
36 | {
|
37 | PINC = 0xFF; |
38 | PIND = 0xFF; |
39 | }
|
40 | }
|
41 | }
|
42 | }
|
43 | |
44 | // Timer 0 Initialisierung
|
45 | |
46 | void timer0 (void) |
47 | {
|
48 | TCCR0A |= (0<<WGM00) | (0<<WGM01); |
49 | TCCR0B |= (0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00); |
50 | TIMSK0 |= (1<<TOIE0); |
51 | }
|
52 | |
53 | // Interrupt-Routine
|
54 | |
55 | ISR (TIMER0_OVF_vect) |
56 | {
|
57 | vorteiler --; |
58 | |
59 | if (vorteiler == 0) |
60 | {
|
61 | vorteiler = VORTEILER; |
62 | takt_10ms = 1; |
63 | hundertstel --; |
64 | }
|
65 | |
66 | |
67 | |
68 | if (hundertstel == 0) |
69 | {
|
70 | hundertstel = HUNDERTSTEL; |
71 | takt_100ms = 1; |
72 | zehntel --; |
73 | }
|
74 | |
75 | |
76 | if (zehntel == 0) |
77 | {
|
78 | zehntel = ZEHNTEL; |
79 | takt_1s = true; |
80 | }
|
81 | }
|
82 | |
83 | SIGNAL (SIG_SPI) |
84 | {
|
85 | received_character = SPDR; |
86 | }
|
87 | |
88 | void SPI_SlaveInit (void) |
89 | {
|
90 | DDRB |= (1<<PB4); |
91 | SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0); |
92 | }
|
> Beim Simulieren springt er auch nach dem setzen der SPI Interrupt Flag > in SIGNAL (SIG_SPI) nun wird aber kein Wert vom SPDR in > received_character übernommen. JTAG oder Simulator? Stimmen die CPOL / CPHA Parameter? Wird SS richtig angesteuert? Wenn SS nach HIGH wechselt und die CPOL / CPHA nicht passt, dann wird das Datenbyte verworfen. Zur näheren Analyse wäre der Sourcecode des Senders hilfreich.
cpol cpha sagt uns nichts... wir haben es simuliert im avr studio... hier mal der c-code des sender (masters) :
1 | //Variablen
|
2 | bool takt_1s = false; |
3 | bool takt_100ms = false; |
4 | bool takt_10ms = false; |
5 | unsigned int sekunden = 50; |
6 | unsigned int minuten = 59; |
7 | unsigned int stunden = 23; |
8 | unsigned int vorteiler = VORTEILER; |
9 | unsigned int zehntel = ZEHNTEL; |
10 | unsigned int hundertstel = HUNDERTSTEL; |
11 | unsigned int wert = 1; |
12 | |
13 | //Funktionsprototypen
|
14 | void SPI_MasterInit (void); |
15 | void SPI_MasterTransmit (unsigned int cData); |
16 | |
17 | void Stellfunktion (void); |
18 | void timer0 (void); |
19 | |
20 | |
21 | int main () |
22 | {
|
23 | //Init
|
24 | sei(); |
25 | SPI_MasterInit(); |
26 | timer0(); |
27 | |
28 | DDRC = 0x0f; |
29 | DDRD = 0xff; |
30 | |
31 | PORTC = 0x0f; |
32 | |
33 | while(1) |
34 | {
|
35 | if (takt_1s == true) |
36 | {
|
37 | takt_1s = false; |
38 | |
39 | SPI_MasterTransmit(wert); |
40 | }
|
41 | }
|
42 | }
|
43 | |
44 | // Timer 0 Initialisierung
|
45 | |
46 | void timer0 (void) |
47 | {
|
48 | TCCR0A |= (0<<WGM00) | (0<<WGM01); |
49 | TCCR0B |= (0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00); |
50 | TIMSK0 |= (1<<TOIE0); |
51 | }
|
52 | |
53 | // Interrupt-Routine
|
54 | |
55 | ISR (TIMER0_OVF_vect) |
56 | {
|
57 | vorteiler --; |
58 | |
59 | if (vorteiler == 0) |
60 | {
|
61 | vorteiler = VORTEILER; |
62 | takt_10ms = 1; |
63 | hundertstel --; |
64 | }
|
65 | |
66 | |
67 | |
68 | if (hundertstel == 0) |
69 | {
|
70 | hundertstel = HUNDERTSTEL; |
71 | takt_100ms = 1; |
72 | zehntel --; |
73 | }
|
74 | |
75 | |
76 | if (zehntel == 0) |
77 | {
|
78 | zehntel = ZEHNTEL; |
79 | takt_1s = 1; |
80 | }
|
81 | }
|
82 | |
83 | void SPI_MasterInit(void) |
84 | {
|
85 | DDRB |= (1<<PB2)|(1<<PB3)| (1<<PB5); |
86 | DDRB &= ~(1<<PB4); |
87 | PORTB |= (1<<PB2)| (1<<PB5); |
88 | SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); |
89 | }
|
90 | |
91 | void SPI_MasterTransmit(unsigned int cData) |
92 | {
|
93 | PORTB &= ~(1<<PB2); |
94 | SPDR = wert; |
95 | while(!(SPSR & (1<<SPIF))); |
96 | PORTB|=(1<<PB2); |
97 | |
98 | }
|
ersetzt doch mal: SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0); durch: SPCR |= (1<<SPE) | (1<<SPIE) | (1<<SPR0);
> cpol cpha sagt uns nichts... Also, wenn ihr den Atmega 88 einsetzt, dann schaut mal auf die Seite 164 im Datenblatt (SPCR-Register). Da gibt es zwei Bits CPHA CPOL. Diese müssen bei beiden Controllern identisch sein. Zum Thema Simulation im AVR Studio: Woher soll das Datenbyte kommen, wenn "außen" kein zweiter Controller dranhängt? Ich würde empfehlen eine Schaltung mit zwei Controllern aufzubauen und an beide Controller ein AVR JTAG-ICE-MKII oder einen AVR Dragon (geht bis 32k Flashgröße) dranzuhängen. Und dann das Ganze per ICE durchspielen. Beim SPI kann man normalerweise nicht viel falsch machen, wenn man das Datenblatt aufmerksam gelesen hat und weiss, wie ein Schieberegister funktioniert.
Also mal zur Codeanalyse:
1 | // Ich würde statt "unsigned int" einen "uint8_t" nehmen. Der int ist
|
2 | // mit einer Kanone auf den Spatz geschossen!
|
3 | void SPI_MasterTransmit(unsigned int cData) |
4 | {
|
5 | uint8_t dummy; |
6 | PORTB &= ~(1<<PB2); |
7 | SPDR = wert; // Wieso "wert"? hier sollte doch cData stehen? |
8 | while(!(SPSR & (1<<SPIF))); // Hier wird auf das IRQ-Flash gewartet... |
9 | PORTB|=(1<<PB2); // SS wierder auf High |
10 | |
11 | //Und wo wird das IRQ-Flag gelöscht?
|
12 | //Laut Datenblatt wird das Flag gelöscht wenn man das Statusregister
|
13 | //abfragt und dann einen Zugriff auf das Datenregister macht. Ihr lest zwar
|
14 | //das Statusregister in der while() oben, aber dann fehlt:
|
15 | dummy = SPDR; |
16 | }
|
Bei der Empfangsroutine solltet ihr darauf achten, dass das Datenbyte sicher verarbeitet ist, bevor ein weiteres kommt. Ansonsten liegt der Fehler wohl beim Sender....
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.