Moin, ich versuche eine LED, die an dem einen µC angeschlossen, durch den anderen µC zu steuern. Problem ist, dass er anscheinend zwar sendet aber der andere µC nichts empfängt. Vielleicht kann mir ja jemand von euch helfen. Die µC sind so verbunden: TX----------RX Code: Sender: #define F_CPU 1000000UL #include <avr/io.h> int main(void) { //Buttons und LED definieren DDRD |= (1<< PD6); DDRB &= ~(1<<PINB0); PORTB |=(1<<PINB0); int UBRR_Value = 25; UBRRH = (unsigned char) (UBRR_Value>>8); UBRRL = (unsigned char) UBRR_Value; UCSRB |= (1<<TXEN); UCSRC |= (1<<USBS) | (3 << UCSZ0); /* Replace with your application code */ while (1) { if (!(PINB & (1<<PINB0))){ // wenn button gedrückt wird while(! (UCSRA & (1<<UDRE))); //warte auf senden UDR=0b11110000; //sende PORTD ^=(1<<PIND6); // toggle led } } } Empfänger: #define F_CPU 1000000UL #include <avr/io.h> int main(void) { DDRB |= (1<<PB0); int UBRR_Value = 25; //baud = 2400 |||| UBBR = ( 1,000,000 / 16 * 2400) -1 = 25.0416667 = 25 UBRRH = (unsigned char) (UBRR_Value>>8); UBRRL = (unsigned char) UBRR_Value; UCSRB |= (1<<RXEN); UCSRC |= (1<<USBS) | (3 << UCSZ0); unsigned char receiveData; while(1) { while(!(UCSRA & (1<<RXC))); //Warten receiveData=UDR; //emfange byte if (receiveData == 0b11110000) PORTD^=(1<<PD6); // wenn byte = true dann toggle LED } }
Mach mal eine LED an die serielle Verbindung. Flackert sie? Hast du GND von beiden µC miteinander verbunden? Hast du bei beiden µC die CLK_DIV8 Fuse und die anderen Fuses zur Wahl der Taktquelle gleich eingestellt? Verwendest du einen R/C Oszillator? Das wäre keine gute Idee, die sind zu ungenau.
Hab ich gemacht, funktioniert irgendwie trotzdem nicht Danke erstmal für die schnelle Antwort. 1.Die LED flackert sobald ich den Button betätige. 2.Ja die beiden µC sind miteinander auf GND verbunden 3.Ich bin noch Anfänger und weiß nicht genau was du mit CLK_DIV8 Fuse meinst. 4.Nein benutze ich nicht.
:
Bearbeitet durch User
Also ich hab jetzt etwas am Code geändert und zwar: while(!(UCSRA & (1<<RXC))); //Warten receiveData=UDR; //emfange byte switch(receiveData) { case 0b11110000: PORTD &= ~(1<<PD6); break; default: PORTD |= (1<<PD6); zustand=1; break; } if (zustand==1) { _delay_ms(1000); zustand=0; PORTD &= ~(1<<PD6); } Jetzt empfängt er zwar etwas, aber es ist noch nicht das richtige. Die LED geht durch die default case an und nach 1 sec wieder aus, wie oben im Programm beschrieben.
> UCSRC |= (1<<USBS) | (3 << UCSZ0);
Diese Zeile ist falsch, es fehlt das URSEL. Und ob man der Veroderung
trauen darf? Aus dem Datenblatt:
"Doing a read access to the UBRRH or the UCSRC Register is a more
complex operation. However, in most applications, it is rarely necessary
to read any of these registers."
Vermutlich ist es nicht die Fehlerursache, aber ich würde es trotzdem
korrigieren.
Wenn du nicht weisst, was eine Fuse ist, dann verwendest du die R/C Oszillatoren. Und die sind für UART Kommunikation nicht genau genug.
Mit nicht genau genug wäre ich vorsichtig. Es handelt sich um 2400 baud. Das kriegt man auch noch hin mit bit-banging. Ich denke eher, dass die Clockselection nicht die gleiche ist auf beiden Controllern. Clkdiv8 wurde ja schon erwähnt.
> Mit nicht genau genug wäre ich vorsichtig. Es handelt sich um 2400 baud.
Der alte Irrtum; bei einem relativen Fehler ist die absolute
Geschwindigkeit egal.
S. Landolt schrieb: > bei einem relativen Fehler ist... Fehler ist jedoch in etwa relativ zum takt und nicht zur baudrate. Bitte nachdenken. Die margen Steigen mit sinkender Baudrate.
:
Bearbeitet durch User
Vielleicht haben Sie mich falsch verstanden: wenn ich um 10 % daneben liege, dann gilt das für 2400 Bd ebenso wie für 115.2 kBd.
Das mit dem Fehler will ich ja gar nicht abstreiten. Einzelne bytes müssten aber trotzdem lesbar bleiben. Das nicht alles passt ist klar. Taktunterschied bedeutet, das beide beide Controller ausseinander laufen. Sie müssten sich bei 2400 baud aber irgendwann auch wieder treffen. Und dann stimmen die bytes für eine gewisse Zeit. Mit höherer Baudraten sinkt die Zeit, in der beide "synchron" sind.
Das sehe ich anders: der interne RC-Oszillator schwankt im wesentlichen in Abhängigkeit von Betriebsspannung und Temperatur; beides wird sich im µs-Bereich nur wenig ändern. Allerdings stimme ich mit Ihnen insofern überein, dass ich ebenfalls den Fehler nicht an dieser Stelle vermute.
B.eng schrieb: > Und dann stimmen die bytes für eine gewisse Zeit. ist nicht richtig, es handelt sich um eine asynchrone Übertragung, dabei wird bei jedem Startbit neu synchronsiert
Die serielle Übertragung versagt, sobals ein Bit im falschen Moment abgetastet wird. Die Abtastung beginnt mit der Mitte des Startbits. Dann kommen in der Regel 8 Datenbits und ein Stopbit. Das sind 9 Abtastungen nach dem Startbit. Wenn die beiden Kommunikationspartner in ihrer Taktfrequenz um mehr als 10% auseinander liegen, tastet der Empfänger mindestens das Stopbit (oder noch mehr Bits) zum falschen Zeitpunkt ab. Je höher die Abweichung, umso mehr Bits werden verfälscht. Der R/C Oszillator hat typischerweise weniger als 10% Abweichung von der Soll-Frequenz, aber bei zwei R/C Oszillatoren sind bis zu 20% Abweichung vorstellbar, wenn der eine zu schnell läuft und der andere zu langsam. Abgesehen davon, hatte ich auch mal einen Chip erwischt, der mehr als 10% Abweichung unter den im Datenblatt angegebenen Bedingungen hatte. Der nächste Chip aus der selben Tüte war viel besser. Sowas kommt vor. Die Baudrate spielt dabei keine Rolle. Wenn die Taktfrequenz des µC um 10% abweicht, dann weicht auch die Baudrate um 10% ab. Denn die wird von der Taktfrequenz abgeleitet. Ich erinnere daran: > int UBRR_Value = 25; //baud = 2400 > // UBBR = ( 1,000,000 / 16 * 2400) -1 = 25.0416667 = 25 Du kannst die tatsächliche Taktfrequenz messen und dann die "1,000,000" in deiner Berechnung dementsprechend anpassen. Oder du kalibrierst die R/C Oszillatoren.
Stefan U. schrieb: > Der R/C Oszillator hat typischerweise weniger als 10% Abweichung von der > Soll-Frequenz, aber bei zwei R/C Oszillatoren sind bis zu 20% Abweichung > vorstellbar, wenn der eine zu schnell läuft und der andere zu langsam. Ja, aber nur wenn der eine bei 1,8V in der Kühltruhe und der andere bei 5V im Backofen betrieben wird.
Nein, dann ist die Abweichung mit Sicherheit noch viel größer. Laut Datenblatt darf die Taktfrequenz für 3V bei 25°C bis zu + und - 10% abweichen. Macht zusammen bis zu 20%. Wie gesagt habe ich in der Praxis auch schonmal mehr als 10% Abweichung erlebt, bei 3.3V und ungefähr 25°C. Was dem Datenblatt auch nicht widerspricht.
Stefan U. schrieb: > Laut Datenblatt darf die Taktfrequenz für 3V bei 25°C bis zu + und - 10% > abweichen. Macht zusammen bis zu 20%. Blödsinn. Calibrated Internal RC Oscillator The Calibrated Internal RC Oscillator provides a fixed 1.0, 2.0, 4.0, or 8.0 MHz clock. All frequencies are nominal values at 5V and 25⋅C. [...] At 5V, 25⋅C and 1.0, 2.0, 4.0 or 8.0 MHz Oscillator frequency selected, this calibration gives a frequency within ± 3% of the nominal frequency. Stefan U. schrieb: > Wie gesagt habe ich in der Praxis auch schonmal mehr als 10% Abweichung > erlebt, bei 3.3V und ungefähr 25°C. Ja, ja.
Daniel D. schrieb: > case 0b11110000: > PORTD &= ~(1<<PD6); Wenn das "richtige" Zeichen kommt, machst du die LED aus. Sollte sie nicht den Zustand wechseln?
Vorab: mir ist klar, dass eine Stichprobe von 18 Stück nicht besonders aussagekräftig ist; mir ist auch klar, dass es Daniel D. in seinem speziellen Fall nicht unbedingt weiterhilft; um sicher zu sein, müsste er messen oder auf Quarz umstellen. Trotzdem, da es mich interessierte, eben gemessen, ATmega16A-PU, der interne 1 MHz-RC-Oszillator: (1339): 125.07, 124.26, 125.20, 125.56 (1340): 126.60, 126.80, 126.33, 126.16, 126.26, 126.72, 126.35, 126.55, 126.87, 126.75, 126.24, 125.81, 126.06, 126.75 jeweils *8 in kHz. Vorausgesetzt, Daniels Controller stammen aus der gleichen Charge, vermute ich nach wie vor sein Problem an anderer Stelle.
S. Landolt schrieb: > Vorausgesetzt, Daniels Controller stammen aus der gleichen Charge, > vermute ich nach wie vor sein Problem an anderer Stelle. Ja. Und zwar genau hier: S. Landolt schrieb: >> UCSRC |= (1<<USBS) | (3 << UCSZ0); Solange das URSEL-Bit nicht gesetzt ist, landet dieser Wert im UBRRH-Register.
>> Laut Datenblatt darf die Taktfrequenz für 3V bei 25°C bis zu + und - 10% >> abweichen. Macht zusammen bis zu 20%. > Blödsinn. Ich habe das dem Datenblatt des ATmega328 entnommen. Siehe Anhang. In welchem Datenblatt hast diese völlig anderen Angaben gefunden?
>> if (receiveData == 0b11110000) PORTD^=(1<<PD6); > Wenn das "richtige" Zeichen kommt, machst du die LED aus. Nein. Schau richtig hin und zittiere richtig.
Stefan U. schrieb: > zittiere richtig. Ich zittere nicht. Sieh dir den Code von gestern, 18:30 an, den der TO geschrieben hat.
Stefan U. schrieb: > In welchem Datenblatt hast diese völlig anderen Angaben gefunden? Atmega16. Um den geht es hier doch. Stefan U. schrieb: > Ich habe das dem Datenblatt des ATmega328 entnommen Das ist einer der neueren Controller. Der Atmega16 gehört noch zur alten Generation, wie auch der Atmega8. Die alten Controller haben mehrere Oszillatoren für die internen Frequenzen, die mit den CKSEL0..3 eingestellt werden. Sie haben keine CKDIV8-Fuse und auch kein Clock Prescale Register(CLKPR). Die Oscillator Accuracy liegt bei 3%. Die 10% der Atmega48..328, wie auch der 164..1284, gelten für den gesamten Spannungs- und Temperaturbereich(1,8 - 5,5V; -40 - 85°C). Bei der werkskalibrierten Einstellung bei 3V/25°C beträgt die Abweichung, wie bei der User-Kalibrierung, 1%. Die User-Kalibrierung lässt sich natürlich auch unter jeder anderen Betriebsbedingung durchführen. Deswegen beträgt diese über den gesamten Bereich 1%. Das lässt sich alles sehr schön nachprüfen, indem man den Timer2 mit Uhrenquarz im CTC laufen lässt und den entsprechenden Ausgang auf den ICP des Timer1 gibt und dann z.B. eine quarzgetaktete Sekunde schältet und sich dann ansieht, was der Timer1 mit internem Oszillator dabei rausbekommt. Verändert man dann mit Föhn, Kältespray und LNT die Bedingungen, erkennt man schnell die Tendenzen, die bei allen Controllern gleich sind. DÜ per UART funktioniert deswegen auch bei den 328ern und Co. grundsätzlich bei 3V/25°C/1%. Beim 16er und Co. nur zufällig, da die Toleranz bei 5V/25°C 3% beträgt, was für DÜ grundsätzlich zu hoch ist.
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.