Hallo! Ich möchte - so wie es im Tutorial beschrieben ist - über die RS232 von meinem STK500 das Zeichen "x" ausgeben. Klappt jedenfalls nicht: Kompilierfehler: undefined UCR, UBRR, usw. #include <inttypes.h> #include <avr/io.h> #define F_CPU 4000000 #define UART_BAUD_RATE 9600 int main (void) { UCR |= (1<<TXEN); UBRR = F_CPU / (UART_BAUD_RATE * 16L) - 1; while (! (USR & (1<<UDRE))) { } UDR = 'x'; } Woran kann das liegen? Woher weiß ich die Taktfrequenz vom µC?
>Kompilierfehler: undefined UCR, UBRR, usw. >Woran kann das liegen? Das er UCR, UBRR nicht kennt?
M@cFreak wrote: > > Woran kann das liegen? Welchen Prozessor benutzt du? Danach holst du dir von Atmel das Datenblatt und siehst nach, wie die bewussten Register in deinem Prozessor heissen. Je nach AVR heissen die ein klein wenig anders. > > Woher weiß ich die Taktfrequenz vom µC? Wenn du nichts gemacht hast, dann läuft der Prozessor wahrscheinlich auf 1Mhz mit internem Takt. Mach dich schon mal darauif gefasst, dass eine stabile RS232 damit nicht funktionieren wird. Der andere Fall ist: Du hast auf externen Quarz oder Quarzoszillator umgestellt. Dann steht auf dem Quarz bzw. Oszillator drauf, wie schnell er taktet.
>der Compiler oder der µC?
Eigentlich: DU
Lies das Datenblatt da findest du die Namen und auch ein Beispiel
ich habe einen ATmega8515, bin mir nicht sicher, dass ich nichts verstellt habe. Habe nämlich schon ein paar Programme auf ihm laufen gehabt. ich verwende das STK500. Da ist doch ein Quarz drauf....Weiß aber nicht wie der taktet
habe es nun so abgeändert: #include <inttypes.h> #include <avr/io.h> #define F_CPU 4000000 #define UART_BAUD_RATE 9600 int main (void) { UCSRB |= (1<<TXEN); UBRRL = F_CPU / (UART_BAUD_RATE * 16L) - 1; while (! (UCSRB & (1<<TXEN))) { } UDR = 'x'; }
Und warum? Gehts? Lies die Fueses aus, nimm das Datenblatt, und schau nach, mit welcher Taktquelle der Prozessor läuft. Alles andere ist Raterei. Oliver
also ich habe nun die Fuses auf "Int Osc 4 Mhz" gesetzt... Auf welche RS232 vom STK500 muss ich meine Leitung zum Rechner anschließen?
@ M@cFreak >also ich habe nun die Fuses auf "Int Osc 4 Mhz" gesetzt... Falsche Einstellung! http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART#Senden MFG Falk
RS232 SPARE wenn du am PC empfangen willst. Sind die Bilder in der AVRStudio Hilfe noch nicht bunt genug?
was heißt bunt genug...kannst du mir vllt. helfen, was in dem Datenblatt in der Tabelle "Examples of UBRR Settings for commoncly used oscillator frequencies" die zahlen 41 83 usw unter "U2x =1" sein sollen? ist das Hex, was in das Register reingeschrieben werden muss???
Vergiss die Tabelle. Du hast doch eine schöne Formel in die du nur die Werte einsetzen musst (eigentlich macht das sogar der Compiler) und schon kriegst du die richtigen Werte raus. Aber du kannst ja spasseshalber einfach mal einen Taschenrechner nehmen und deine Zahlen einsetzen und schaun was dabei rauskommt. Die Zahl dann probehalber mal auf Hex umrechnen und dann beides (dezmal und hex) mit den Angaben im Datenblatt vergleichen.
Hallo zusammen! Also, ich habe auch kein Glück mit der UART. Ich bin leider auch Anfänger und hoffe, Ihr könnt mir helfen. Das mit der Taktfrequenz habe ich auch nicht ganz verstanden. Ja, die Formel habe ich gesehen. [UBRR = Taktfrequenz / (16 *Baudrate)-1] Leider weiß ich nicht, mit welcher Frequenz mein AVR Butterfly getaktet wird (32KHz für RTC) und ob und wie ich die Interne Taktfrequenz ändern kann. Liegt daran... bin Anfänger. Wäre super, wenn Ihr mir weiterhelfen könnt... Danke!! Gruß Christian #include <avr/interrupt.h> #include <avr/io.h> #include <avr/iom169p.h> #include <avr/portpins.h> #include <avr/sfr_defs.h> #include <stdint.h> #define BAUD 9600 #define FOSC 1843200 //Taktgeschwindigkeit 1,8 Mhz #define MYUBRR FOSC/16/BAUD-1 //what ever that mean... Formel??? // Receive Interrupt ISR(USART0_RX_vect ) // veraltet: SIGNAL(SIG_OVERFLOW0) { // ISR: Zeichen wurde empfangen while ( !( UCSR0A & (0x20)) ); //Warten bis alles empfangen wurde = UART Data empty // UDR0 = UDR0 + 1; // Gesendet: 0x01 Antwort: 0xFF UDR0 = 0x01; // Gesendet: 0x01 Antwort: Endlosschleife 20 04 3F 20 3F 44 80 10 20 3F 04... //Frage, warum bekomme ich bei 0x01 eine Endlosschleife??? } //Zeichen wurde komplett gesendet ISR(USART0_TX_vect ) // veraltet: SIGNAL(SIG_OVERFLOW0) { } void USART_Init (unsigned int ubrr) { // zuerst Baudrate setzen UBRR0H = (unsigned char) (ubrr>>8); UBRR0L = (unsigned char) (ubrr); //nun Sender und Empfänger initialisieren UCSR0A = 0x00; /* RXC TXC UDRE Frame Error DOR USart Parity Error Double USART Transmission Speed MPCM: Multi processor Comm. Mode */ UCSR0B = 0xF8; /* RXCIE RX Complete Interrupt Enable TXCIE TX Complete Interrupt Enable UDRIE USART Data Register Empty IE RXEN Receiver Enable TXEN Transmitter Enable UCSZ2 Character Size (Number of Databits RXB8 Receive Data Bit 8 TXB8 Transmit Data Bit 8 */ //Frameformat setzen: 8 Datenbits, 1 Stopbits UCSR0C = 0x86; /* ---- No Funktion UMSEL USART Mode Select (Synch / ASynch) UMP1 Parity Mode UMP2 Parity Mode USBS Stop Bit Select UCXZ1 Character Size UCXZ0 Character Size UCPOL Clock Polarity (only synch Mode) */ } // UART main int main(void) { DDRD = 0xff; //enable PortD as output sei(); //enable Interrupt USART_Init (MYUBRR); while (1) { }; }
Christian Beuge wrote: > Hallo zusammen! > > Anfänger und hoffe, Ihr könnt mir helfen. Das mit der Taktfrequenz habe > ich auch nicht ganz verstanden. Ja, die Formel habe ich gesehen. > [UBRR = Taktfrequenz / (16 *Baudrate)-1] Ist nicht weiter schwer. Eine UART arbeitet in einem fixen Zeitraster. Dieses Zeitraster wird durch 2 Faktoren bestimmt * zum einen die gewünschte Baudrate, * zum anderen die fixe Taktgeschwindigkeit des Prozessors. Stell es dir einfach so vor: Die UART muss zwischen dem Versenden von einzelnen Bits gewisse Wartezeiten einhalten. Zum einen bestimmt natürlich die gewünschte Baudrate wie lange (in Zeiteinheiten) die UART 'Däumchen drehen' muss. Zum anderen bestimmt natürlich die vorhandene Taktfrequenz wie schnell die UART 'Däumchen drehen kann'. Ergo muss man irgendwann mal ausrechnen, wieviele 'Däumchen gedreht werden müssen', damit eine bestimmte Zeit vergeht. Genau das macht die Formel. Sie rechnet aus, wie oft die UART in einer Schleife laufen muss, bis die für eine bestimmte Baudrate notwendige Wartezeit zwischen 2 Bits abgelaufen ist. > > Leider weiß ich nicht, mit welcher Frequenz mein AVR Butterfly getaktet > wird (32KHz für RTC) und ob und wie ich die Interne Taktfrequenz ändern > kann. Liegt daran... bin Anfänger. Steht im Datenblatt. Gewöhn dich daran. Du wirst das Datenblatt noch oft brauchen. Laut Datenblatt arbeitet dein Mega169 mit 1Mhz Taktfrequenz (leider auf internem Oszillator. Der ist leider meist seht ungenau. Ob damit eine vernünftige Verbindung mittels RS232 zusatande kommt, ist fraglich. Aber möglich). > > Wäre super, wenn Ihr mir weiterhelfen könnt... Schreib am Anfang kein so 'kompliziertes' Programm, das mittels Interrupt Zeichen verschickt. Machs dir einfach. Und im übrigen solltest du dch an die Beispiele im Tutorial halten. Angepasst an die Registernamen die auf deinem µC gelten.
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | |
4 | #ifndef F_CPU
|
5 | #define F_CPU 1000000 /* Oszillator-Frequenz in Hz */ |
6 | #endif
|
7 | |
8 | // Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)
|
9 | #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
|
10 | |
11 | #define UART_BAUD_RATE 9600
|
12 | |
13 | int main(void) |
14 | {
|
15 | UCSRB |= ( 1 << TXEN ); // UART TX einschalten |
16 | UCSRC |= ( 3<<UCSZ0 ); // Asynchron 8N1 |
17 | |
18 | // Baudrate setzen
|
19 | UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 ); |
20 | UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ); |
21 | |
22 | while( 1 ) { |
23 | //
|
24 | // warten bis die UART 'fertig' meldet
|
25 | //
|
26 | while (!(UCSRA & (1<<UDRE))) |
27 | ;
|
28 | |
29 | //
|
30 | // und ein Zeichen senden
|
31 | //
|
32 | UDR = 'x'; |
33 | }
|
34 | }
|
so. Jetzt stelle ich mal mein Beispiel rein, mit dem es auf der RS232 SPARE von meinem STK 500 ebenfalls nicht funktioniert: Vllt. könntet ihr mir den Fehler sagen. Ich habe übrigens keinen externen Oscillator/Quarz, sondern den Internen auf 4 MHz in den Fuses gesetzt. ---------------------------------- #include <inttypes.h> #include <avr/io.h> #define F_CPU 4000000 /////////////////// Im Terminalprogramm wird eine Baudrate von 9600 eingestellt int main (void) { UCSRB |= (1<<TXEN); //Senden aktivieren UCSRC |= (1<<URSEL)|(3<<UCSZ0); // UBRRH = 00; //Baudrate einstellen UBRRL = 25; //UCSRA |= (1<<U2X); //UCSRA: Bit "U2x" setzen BRAUCHE ICH DAS?????? while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } UDR = 'x'; //x zum senden ins Datenregister while (1); } Vielen Dank
> BRAUCHE ICH DAS?????? Nein, das ist in dem Falle (für 9600 Baud) sogar falsch! U2X verdoppelt die Baudrate bei gleichen UBRRx-Settings. Du hast damit also 19200 Baud. Außerdem: Bist Du sicher, dass die Einstellungen vom Hyperterminal exakt mit denen des Controllers übereinstimmen (Stopbits, Parity)? Außerdem ist der interne Oszillator der AVRs für asynchrone Datenübertragung nicht wirklich geeignet, weil er u.U. zu ungenau ist und eine starke Temperaturdrift hat. Es kann Dir also auch passieren, dass bei korrekten Einstellungen am PC nur Murks ankommt. Wenn es zuverlässig laufen soll, nimm einen Quarz. Mit dem internen Oszi ist das alles Glückssache.
Also. Danke erstmal für deine antwort. Ich habe - wie du geschrieben hast - nun einen Quarz von 8 MHz. Somit auch 8 MHz in den Fuses eingestellt. Jetzt kommentiere ich das mit dem U2X noch aus,....habe nun 9600 Baudrate: Terminal-Einstellungen: Data: 8bit, Parity: none, Stop: 1 bit. Stimmt das soweit? danke
...sorry, nochwas.: und ich muss natürlich auch diese "UBRRL = 25" auf "UBRRL = 51" stellen. Danke!
Ich kann nur sagen: Wenn deine Taktfrequenz stimmt, dann läuft das Pgm das ich gepostet habe einwandfrei. Wenn das bei dir also nicht klappt, dann liegt das * falscher Prozessor Taktfrequenz * Kabel * sontiges Hardwareproblem
Ich versuche nachzuvollziehen, warum du solche Probleme beim Einstieg hast. Auf dieser Seite gibt es ein Tutorial da steht eine ganze Menge drin aber nicht speziell zum STK500 aber der Stolperstein Fuseproblematik ist angesprochen. Im Datenblatt ab Seite 151 findest du C-Programmcode zur Initialisierung der UART und zum Senden, den kannst du übernehmen (copy und Paste) Im AVR-Studio in der Hilfe ist die Beschreibung des STK500 und speziell Description of User RS232 Interface da sind Bilder (ok nicht bunt) zum Anschluß und es steht da welche du benutzen mußt. Dein Terminalprogramm mußt du nur auf die Werte der Verbindung einstellen (Baudrate,Stopbits, Parität) Das solltest du selbst wissen wie das geht. Bis jetzt habe ich nur die Erklärung, daß du die dir zur Verfügung stehenden Informationsquellen nicht ordentlich nutzt. Ändere das, sonst wird das ein sehr frustrierender Einstieg. Wenn du ins Forum postest sind Sätze wie "...ebenfalls nicht funktioniert:" nicht sehr hilfreich. Beschreibe was passiert, bei welchen Einstellungen.
aber wenn meines richtig ist und deines richtig ist, dann müsste doch auch meins funktionieren und kein Unterschied von der Funktion gegeben sein.... Jedenfalls funktioniert die Lösung aus dem Tutorial NICHT
M@cFreak wrote: > aber wenn meines richtig ist und deines richtig ist, dann müsste doch > auch meins funktionieren und kein Unterschied von der Funktion gegeben > sein.... > > Jedenfalls funktioniert die Lösung aus dem Tutorial NICHT Doch die funktioniert. Wenns bei dir nicht funktioniert, dann liegt der Fehler in einem Bereich, der ausserhalb des Tutorials liegt: * irgendwas in der Hardware * Kabel falsch rum beschaltet * am häufigsten aber: Die angegebene Taktfrequenz stimmt nicht mit der Realität überein. Was mich zb. verblüfft ist, dass du als Anfänger in noch nicht mal einer Stunde einen Quarz eingebaut hast und den auch noch korrekt gefused hast. Allerdings gibt mir der Satz zu denken: "Somit auch 8 MHz in den Fuses eingestellt." Das klingt nicht danach, als ob du den externen Quarz aktiviert hast. Das hört sich eher an als ob du die CLKDIV Fuse ausgeschaltet hast. Dein µC läuft dann zwar mit 8Mhz aber immer noch am internen Oszillator.
Der Quarzeinbau ist bei dem STK500 ja nur gesteckt. Ich habe also einen 8 MHz Quarz reingesteckt. Als nächstes habe ich in meinem Programmcode UBRRL = 51 gesetzt. Dann habe ich unter "Fuses" das Häkchen bei "Ext. Crystal/Resonator Medium Frequ.; Start-up time: 1K CK + 64 ms;" gesetzt, welches vorher bei int RC Osc. 4 MHz stand. Dann habe ichs kompiliert, Terminal geöffnet, Auf RS232 SPARE umgesteckt und Nix empfangen. so ist der Stand der dinge
@ M@cFreak >UBRRL = 51 gesetzt. Dann habe ich unter "Fuses" das Häkchen bei "Ext. >Crystal/Resonator Medium Frequ.; Start-up time: 1K CK + 64 ms;" gesetzt, >welches vorher bei int RC Osc. 4 MHz stand. Hoffentlich ist auch die DIV8 Fuse NICHT programmiert. MFG Falk
>Dann habe ichs kompiliert, Terminal geöffnet, Auf RS232 SPARE umgesteckt >und Nix empfangen. Du sagst weder welche Einstellungen du im Terminal hast, noch ob du dir die Hilfe im AVRStudio durchgelesen hast. Da ist nämlich auch zu sehen, daß du eine Verbindung zwischen den Portpins und den RX/TX Anschlüssen des STK500 machen mußt. Kann es sein das du dies vergessen hast?
#include <inttypes.h> #include <avr/io.h> #define F_CPU 8000000 /////////////////// Im Terminalprogramm wird eine Baudrate von 9600 eingestellt int main (void) { UCSRB |= (1<<TXEN); //Senden aktivieren UCSRC |= (1<<URSEL)|(1<<USBS)|(1<<UCSZ1); // UBRRH = 0; //Baudrate einstellen UBRRL = 51; while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } UDR = 'x'; //x zum senden ins Datenregister while (1); } Hier nochmal der momentane Code
Hier nochmal die Einstellungen im Terminal: habe nun 9600 Baudrate: Terminal-Einstellungen: Data: 8bit, Parity: none, Stop: 1 bit. Die Hilfe habe ich noch nicht durchgelesen. Danke
habe nun eine Leitung von RS232 SPARE zu PORTD PD0/PD1. Geht aber trotzdem nicht.
Ändere mal dein Programm um: Lass den µC in einer Endlosschleife ständig senden
1 | while( 1 ) { |
2 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ |
3 | {
|
4 | }
|
5 | |
6 | UDR = 'x'; //x zum senden ins Datenregister |
7 | }
|
8 | }
|
Und dann begibst du dich mit einem Voltmeter auf Fehlersuche. Du kannst auch eine LED + Vorwiderstand (330 Ohm) nehmen. Damit überprüfst du mal direkt an den Prozessorpins (PD0, PD1), ob der Prozessor sendet. Mit einer LED müsstest du an einem der Pins ein deutliches Flackern sehen. Wenn du das Flackern hast, dann verfolgst du es weiter (über alle Verbindungen), bis du am Stecker angelangt bist. (Led + Vorwiderstand: Ein Bein von der Led kommt an den Prozessorpin, das andere an den Vorwiderstand. Von dort gehts weiter zum Widerstand und das andere Bein vom Widerstand kommt fix an Masse. Probier aber aus, ob du die Led richtig rum gepolt hast. Wenn du das frei Led Beinchen an +5V hälts, muss sie leuchten).
Hier der aktuelle Code. Den obigen könnt ihr vergessen. War en Fehler drin. #include <inttypes.h> #include <avr/io.h> #define F_CPU 8000000 /////////////////// Im Terminalprogramm wird eine Baudrate von 9600 eingestellt int main (void) { UCSRB |= (1<<TXEN); //Senden aktivieren UCSRC |= (1<<URSEL)|(3<<UCSZ0); // UBRRH = 00; //Baudrate einstellen UBRRL = 51; while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } UDR = 'x'; //x zum senden ins Datenregister while (1); }
Also...ich habe nun bei meinem ATmega8515 eine Leuchtdiode wie folgt drangehalten: An Pin11 (Transmit-Pin) die Anode der Diode und an Pin 20 (mit vorwiderstand) die Katode der Diode. Sie Leuchtet! von flackern ist nichts zu sehen.
Sie kann nicht flackern. Du schickst exakt ein Zeichen 'x'. Dessen wackelnden Bits sind schneller weg, als du kucken kannst. Du solltest die Programmmodifikation von Karl heinz einbauen.
welche Programmmodifikation denn genau? Weil alles doppelt im code zu haben ist auch nicht gut....
achso, du meinst diese While-Schleife....die habe ich schon drin... Dass er praktisch nonstop dieses Zeichen schickt: ich sagte, mit der "Modifikation" leuchtet meine Diode permanent. (wird wohl flackern, ist eben nicht zu sehen). Habe leider kein Oszi zur verfügung.
M@cFreak wrote: > achso, du meinst diese While-Schleife....die habe ich schon drin... > > Dass er praktisch nonstop dieses Zeichen schickt: ich sagte, mit der > "Modifikation" leuchtet meine Diode permanent. (wird wohl flackern, ist > eben nicht zu sehen). > Dann geh mit der Baudrate runter. 300 Baud musst du sehen können. > Habe leider kein Oszi zur verfügung.
wie komme ich denn auf 300 Baud? die Tabelle zeigt mir die Möglichkeit nur bis 2400 zu gehen
Aus meinen Erinnerungen zu Modemzeiten: 2400 Baud siehst du auch. Wenn wider Erwarten nicht, dann rufe eine Warteschleife z.B. _delay_ms(10) nach jedem Zeichen auf. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29
ok :-) es funktioniert! Vielen Dank! Und was war der Fehler? --> Im Terminal-Programm anstatt COM1 war COM3 eingestellt AAAAAAAHHHH
woran kann das liegen? wenn ich z.b. das "x" in der Schleife laufen lasse, dann kommen "$$$$$"
Dann stimmt am Timing was nicht. Also nochmal: Taktfrequenz kontrollieren #define F_CPU 8000000 #include <avr/io.h> #include <utils/delay.h> int main() { int i; DDRB = 0xFF; // Port B auf Ausgang oder wo du halt sonst // ein paar LED drann hast while( 1 ) { PORTB = 0xFF; for( i = 0; i < 100; ++i ) _delay_ms( 10 ); PORTB = 0x00; for( i = 0; i < 100; ++i ) _delay_ms( 10 ); } } Die Leds müssen im Sekundentakt blinken (das kann man auch mit freiem Auge noch gut abschätzen).
ähm, gute idee, mal das Timing zu testen. aber die <utils/delay.h> kennt der compiler nicht. "no such file or directory"
die leuchten bei mir etwa 1,9 sec. Also länger als 1 secunde! Was soll ich nun machen??
Hattest du die Taktfrequenz nicht auf 4 Mhz eingestellt?
würde den Zeitunterschied 1:2 erklären.
>Was soll ich nun machen??
Setz dich hin und lies die Doku.
AHHHH, liegt wohl am Quarz, denn wenn ich den aus der Fassung ziehe, dann läuft im Terminal alles wie wenn er drinnensteckt. Ist also doch was mit der Einstellung zum Oszillator falsch
Hast du debug compiliert, oder den Optimizer eingeschaltet. Damit die delay Funktionen klappen, muss der Optimizer eingeschaltet sein. Im AVR Studio findest sich das im 2-ten Menüpunkt ganz unten (hab keines da, drum kann ich nicht nachschauen wie der heist: Irgendwas mit Project - Properties oder so ähnlich). Stell die Optimierung auf -Os Wenn du dann immer noch 1.9 Sekunden hast, dann läuft der µC offensichtlich nicht mit 8 Mhz.
ok habe das gemacht. Schwer mit der Stoppuhr zu messen. Jedenfalls länger als 1 Sekunde blinken die.
also nochmal, Karl-Heinz. Wo kann ich , dass er 8 MHz von meinem Quarz schwingt, einstellen. Vllt. habe ich da einen Denkfehler. Danke
M@cFreak wrote: > ok habe das gemacht. Schwer mit der Stoppuhr zu messen. Das brauchts auch nicht. Meistens hat man ja ein Vielfaches. Wenn also im Pgm 8 Mhz steht und der µC macht in Wirklichkeit 4Mhz, dann sind die Leds anstelle von 1 Sekunde deren 2 eingeschaltet. Läuft der µC gar nur auf 1 Mhz, dann leuchten die Led ganze 8 Sekunden statt 1 Das erkennt auch ein Blinder. > Jedenfalls länger als 1 Sekunde blinken die. Schlecht. http://www.mikrocontroller.net/articles/AVR_Fuses Da du einen Quarz benutzt ist die richtige Einstellung bei dir "external Crystal".
> ok habe das gemacht. Schwer mit der Stoppuhr zu messen. Miss den Puls deines AVR ;-) Setz dir eine vernünftige Zeitspanne fest z.B. 20 Sekunden. Zähle wie oft es in der Zeitspanne blinkt. Teile Zählwert durch Zeitspanne und du hast die Frequenz.
Stefan wrote: >> ok habe das gemacht. Schwer mit der Stoppuhr zu messen. > > Miss den Puls deines AVR ;-) > > Setz dir eine vernünftige Zeitspanne fest z.B. 20 Sekunden. Zähle wie > oft es in der Zeitspanne blinkt. Teile Zählwert durch Zeitspanne und du > hast die Frequenz. Aber Achtung: Das Programm lässt die LED 1 Sekunde eingeschaltet und 1 Sekunde ausgeschaltet. Das ergibt eine Soll-Frequenz von 0.5 Herz. Und weil es wichtig ist: Die Zeiten stimmen nur dann, wenn im Compiler die Optimierung eingeschaltet ist.
Ja die Optimierung ist eingeschaltet. Habe ich so gemacht, wie es Karl-Heinz beschrieben hat. Möchte vielmehr sicher gehen, dass der Mikrocontroller "einfach" über den Quarz taktet. Anscheinend tut er das ja nicht, habe ja vorhin scho ngeschrieben, dass die Daten in das Terminal weiterhin strömen, wenn ich den Quarz rausziehe! danke
M@cFreak wrote: > Ja die Optimierung ist eingeschaltet. Habe ich so gemacht, wie es > Karl-Heinz beschrieben hat. > > Möchte vielmehr sicher gehen, dass der Mikrocontroller "einfach" über > den Quarz taktet. Anscheinend tut er das ja nicht, habe ja vorhin scho > ngeschrieben, dass die Daten in das Terminal weiterhin strömen, wenn ich > den Quarz rausziehe! > Oha. Das ist aber ein deutliches Indiz dafür, dass der µC auf 'interner Oszillator' läuft.
ja, bloß was kann ich mehr machen, als den Haken auf "Ext. Crystal/Resonator" und anschließend auf "Program" zu klicken???
Wenn du nach dem Programmieren die Fuses wieder einlesen lässt, ist der Haken dann immer noch gesetzt? Blöde Frage: Den Haken bei 'int Oszillator' hast du weg gemacht?
ok, hat jetzt super geklappt. Und woran lags? An nem Jumper, der von internal Osc. am STK500 auf external Osc. schaltet ES funktioniert 100 %ig :) vielen Dank für euere Hilfe (und Geduld)!
und nun zum Empfangen vom terminal. Mein Ziel ist es, ein Zeichen ins Terminal zu schreiben und dieses dann an "PORTB" (Leuchtdioden) ausgeben, damit ich seh, ob was bei µC ankommt: Würde das funktionieren? ------------------------------------------------------------- #include <avr/io.h> int main (void) { DDRB = 0xFF; UCSRB |= (1<<RXEN); UBRRH = 00; //Baudrate auf 9600 einstellen UBRRL = 51; while (!(UCSRA & (1<<RXC))); PORTB = UDR; } ---------------------------------------------------------------- Danke!
Und wieder die übliche Frage: Was funktioniert denn nicht? ('funktioniert nicht' ist keine vernünftige Fehlermeldung) PS: Du solltest dir wirklich angewöhnen, solche Dinge in Schleifen zu packen. while( 1 ) { // warte auf ein Zeichen while (!(UCSRA & (1<<RXC))); // und am Port das Bitmuster ausgeben PORTB = UDR; } } PS2: Einrückungen sind kein Luxus! Sie helfen die Struktur eines Programmes schneller zu erfassen.
hm ich kann schon garnichts auf mein Terminal schreiben......Muss ich die RS232 fürs Terminal weiterhin verwenden?
M@cFreak wrote:
> hm ich kann schon garnichts auf mein Terminal schreiben.
Das ist bei Hyperterminal normal.
Da ist standardmässig das 'lokale Echo' ausgeschaltet.
Das heist: Du siehst nicht was du tippst.
Das heist aber nicht, dass die Zeichen nicht rausgehen.
Die Zeichen gehen sehr wohl raus. Das Standardverfahren
ist: Die Zeichen gehen raus und der Empfänger schickt
die empfangenenn Zeichen sofort wieder zurück. Und erst
dann zeigt das Terminal sie an.
Das hat den Vorteil, dass man eine unterbrochene Verbindung
sofort erkennt.
Man kann allerdings auf den meisten Terminals auch ein
sog. 'lokales Echo' einschalten. Dann schreibt das Terminal
mit, was es so rausgeschickt hat.
ja, aber es leuchten trotzdem keine LEDs, nachdem ich etwas eingegeben habe. Habe auch "local Echo" aktiviert
Moment: Du hast 'lokal Echo' aktiviert und siehst immer noch nicht was du tippst? Ja: Schalte das Hardwarehandshaking im Hyperterminal aus.
Ich sehe schon, was ich schreibe, aber es kommt anscheinend nicht beim µC an, da keine LEDs leuchten. Wird wohl noch ein Fehler in der Software sein?!
Probier das mal aus:
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | |
4 | #ifndef F_CPU
|
5 | #define F_CPU 8000000 /* Oszillator-Frequenz in Hz */ |
6 | #endif
|
7 | |
8 | // Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)
|
9 | #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
|
10 | |
11 | #define UART_BAUD_RATE 9600
|
12 | |
13 | int main(void) |
14 | {
|
15 | char c; |
16 | |
17 | UCSRB |= ( 1 << TXEN ) | ( 1 << RXEN ); |
18 | UCSRC |= ( 1 << URSEL) | ( 3<<UCSZ0 ); // Asynchron 8N1 |
19 | |
20 | // Baudrate setzen
|
21 | UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 ); |
22 | UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ); |
23 | |
24 | while( 1 ) { |
25 | // warte auf ein Zeichen
|
26 | while (!(UCSRA & (1<<RXC))) |
27 | ;
|
28 | |
29 | // das Zeichen holen
|
30 | c = UDR; |
31 | |
32 | // warten bis die UART 'fertig' meldet
|
33 | while (!(UCSRA & (1<<UDRE))) |
34 | ;
|
35 | |
36 | // und das Zeichen zurückschicken
|
37 | UDR = c; |
38 | }
|
39 | }
|
Tut er aber anscheinend nicht. Und das kann verschiedene Ursachen haben. Der Vorschlag von Karl heinz (1) läuft darauf hinaus, einen anderen - bekannt zuverlässigen - Code einzusetzen, um die grundsätzliche Funktion der Entwicklungsumgebung zu testen. Ich sehe als Schwachpunkt deines Codes (2) die mehrfach angesprochene fehlende Endlosschleife. Dein Code ist ruckizucki fertig und main() wird verlassen. U.U. so schnell, dass PORTB zwar gesetzt wird aber der µC sich einen Mückenwimpernschlag später schon in einen undefinierten Zustand verrannt hat. (1) Beitrag "Re: UART-Fehler :(" (2) Beitrag "Re: UART-Fehler :("
Stefan wrote: > Tut er aber anscheinend nicht. Und das kann verschiedene Ursachen haben. > Ich denke mal die Hauptursache ist das fehlende UCSRC |= ( 1 << URSEL) | ( 3<<UCSZ0 ); // Asynchron 8N1 aber um ehrlich zu sein bin ich jetzt zu faul im Datenblatt nachzusehen, wofür die UCSZ0 und UCSZ1 Bits gut sind (Was URSEL macht weiss ich auswendig :-) Das ist meine Standard-UART-Initialisierung. Wenn ich eine UART brauche, dann hole ich mir den Code mit Cut&Paste in das aktuelle Projekt und fertig. Von dem Code weiss ich dass er funktioniert und ich sehe wirklich keinen Sinn darin, jedesmal wieder für dieselbe Funktionalität die Bits aus dem Datenblatt raussuchen zu müssen. Aus demselben Grund bin ich auch gegen die Zuweisung von 51 an das Baudratenregister allergisch. Ich setzte einfach die Formel mittels Cut&Paste ein, achte darauf dass der F_CPU Wert stimmt und mach ein #define für die gewünschte Baudrate. Ich mach mir doch nicht die Finger mit schnöden Taschenrechnertricks ( FOSC/16/BAUD-1 selber ausrechnen, igitt) oder raussuchen aus Tabellen schmutzig. Diese 'Drecksarbeit' überlasse ich dem Compiler. Ich kümmere mich lieber darum wo die Daten herkommen, die über die UART müssen.
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.