Habe folgendes Problem: Ich möchte empfangene Zeichen wieder zurücksenden. Das ganze soll über einen Interrupt - wenn Zeichen empfangen - erfolgen. Sobald der µC ein Zeichen empfängt sendet er wahllos Zeichen in einer Endlosschleife zurück. Ich muss erwähnen, dass ich gerade von Assembler auf GCC umsteige. Also kein GCC-Profi #include <avr/io.h> #include <avr/iom8515.h> #include <avr/interrupt.h> ISR(USART_RXC_vect) { unsigned char Zeichen; Zeichen = UDR; while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = Zeichen; // sende Zeichen } int main(void) { UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // UART TX,RX und INTRx einschalten UBRRH = 0; // Highbyte ist 0 UBRRL = 51; // Lowbyte ist 51 ( dezimal ) while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = '38'; // sende Zeichen sei(); while(1) { /*Endlosschleife*/ } }
Probiere es mal so: int main(void) { UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // UART TX,RX und INTRx einschalten UBRRH = 0; // Highbyte ist 0 UBRRL = 51; // Lowbyte ist 51 ( dezimal sei(); while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = '38'; // sende Zeichen while(1) /*Endlosschleife*/ { } } So müsste er einmal am anfang die '38'schicken und dann immer das zeichen schicken was er empfangen hat. Das mit dem wahllos senden müsste man allerdings anders gestalten.
Achso was ich noch fragen wollte! Hat denn dein Compiler nicht gemeckert ?
Danke erstmal, aber was soll daran besser sein, wenn ich vor Senden der '38' die Globalen Interrupts zulasse? Mit meinem Programm(s.o.) sendet er wahllos Zeichen sobald er etwas empfängt. Zudem ist das erste Zeichen was er antwortet, nicht das gleiche welcher er über RxD erhalten hat. Mit deiner Änderung sendet er kein Zeichen zurück. Zudem habe ich einen Kontrollport(PortB) aktiviert. Wenn er in Interuptroutine springen soll schaltet er die LED um. -> Macht er nicht, d.h er springt nicht in die Interruptroutine! Aber warum? Nochmal mein Programm: #include <avr/io.h> #include <avr/iom8515.h> #include <avr/interrupt.h> #include <avr/signal.h> ISR(USART_RXC_vect) { PORTB=0xF0; register unsigned char akku; akku = UDR; while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = akku; // sende Zeichen } int main(void) { UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // UART TX,RX und INTRx einschalten UBRRH = 0; // Highbyte ist 0 UBRRL = 51; // Lowbyte ist 51 ( dezimal ) DDRB=0xFF; PORTB=0x0F; while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich UDR = '38'; // sende Zeichen sei(); while(1) { /*Endlosschleife*/ } }
"Build succeeded with 0 Warnings..." Ich denke mal das ist in Ordnung. Warum meinst du er solle meckern?
>UDR = '38';
Wie soll das gehen?
'' (Hochkommata) beschreiben einen Character (einzelnes Zeichen).
38 sind aber zwei Zeichen.
Wenn, dann müsste es
UDR = "38";
heissen.
Das wird aber auch nicht funktionieren, da man immer nur ein Zeichen
(acht bit / ein Byte) zur Zeit ins UDR schreiben kann.
Vielleicht meinst du ja UDR = 38; Damit wird dann die Dezimalzahl 38
ins UDR geschrieben. Das dürfte laut ASCII ein "&" sein.
Habe Dein Programm mit einem Mega16 getestet und es funktioniert einwandfrei. Eine Warnung gibt der Compiler bei UDR = '38'; , da nur ein Zeichen angegeben werden darf. Dafür müssen aber mit der Compileroption -Wall alle Warnungen ausgegeben werden. Besser UDR = 38; entspricht dem Zeichen '&'. Stimmen denn die Baudraten überein? Gruß Sven
Außerdem fügst Du die interrupt.h und signal.h ein, was auf eine ältere Compilerversion schließen lässt. Die Interruptfunktion implementierst Du aber mit ISR, was in der aktuelle Compilerversion benutzt werden muss. Die Implementierung der ISR muss natürlich der Version des angewendetetn Compilers entsprechen.
Ich kann 0x38 oder '38' schreiben und erhalte in meinem Terminalprogramm das gleiche Ergebnis. Steht das Terminal auf HEX-Anzeige erhalte ich jedesmal 38 und analog erhalte ich bei ASCII-Anzeige die 8. Aber das ist ja nicht mein Problem!!! Mein Problem ist, er springt nicht in die Interruptroutine ISR(USART_RXC_vect).
Mal ne blöde Frage: Welchen Compiler benutzt du und in welcher Form. Das von dir gepostete geht definitiv nicht ohne Warnings durch den Compiler. (Ach ja: welche variablen in Register abgelegt werden sollen, überlässt du besser dem Compiler. Streich am besten das Schlüsselwort 'register' aus deinem C-Sprachschatz. Im besten Fall ignoriert es der Compiler sowieso, im schlimmsten Fall bewirkt es das Gegenteil von dem was du erreichen möchtest.)
Ich benutze: AVR Studio 4.12.490 SP3 GUI Version 4,12,0,490 Baudrate auf 9600-8-N-1 gestellt Signal.h hatte ich nur implementiert, wegen test von SIGNAL(UART...). Habe ich schon wieder entfernt. >Die Implementierung der ISR muss natürlich der Version des angewendetetn Compilers entsprechen. Wie soll ich das verstehen. GCC ist Neuland für mich. Ich habe die ganze Zeit in Assembler entwickelt. Als Info nutze ich das Tutorial dieser Homepage.
UDR = '38' // '38' sind zwei Zeichen, nämmlich '3' und '8' #include <avr/iom8515.h> // brauchts Du nicht zu includen. Üblicherweise wird die CPU im makefile definiert, dann werden mit dem <avr/io.h> automatisch die richtigen CPU-Definitionen reingehohlt! Gruss von mir
Ich habe mir den WinAVR-20060421 installiert. Als µC nutze ich den ATMega16 mit einem 8MHz internen Takt
> ATMega16
Und warum includest du dann
#include <avr/iom8515.h>
Du hast keinen mega8515.
Sorry ich meinte Atmega8515, ich versuche gerade dass ganze auf einem Atmega16 zu testen, denn vielleicht ist der 8515 defekt. WinAVR-20060421 ist das nicht die aktuellste Version?
> WinAVR-20060421 ist das nicht die aktuellste Version? Doch ist sie. Wenn ich allerdings bei mir mega8515 einstelle, dann sagt mir der Compiler: > ../UART.c:6: warning: `USART_RXC_vect' appears to be a misspelled > signal handler Liest du eigentlich die Warnungen vom Compiler?
Und schmeiss den Include #include <avr/iom8515.h> raus. Der Prozessortyp wird im AVR-Studio unter 'Project' - 'Configuration Options' eingestellt. Wenn du ihn nachträglich änderst auch den Punkt 'Debug' - 'Select Platform and Device' nicht vergessen. Du inkludierst immer nur avr/io.h
Ich sehe jetzt diese Meldung auch. Das Fenster zeigt bei mir nur 5 Zeilen an und wenn die Meldung "Build succeeded with 0 Warnings..." angezeigt wird, gehe ich davon aus, dass keine Fehler vorhanden sind. Seltsam ist nur, wenn ich es ein zweites mal kompiliere erscheint diese Warnung nicht mehr. Habe die Schreibweise IST(USART_RXD_VECT) in ...vect) und es funktioniert. Danke an Alle die mir geholfen haben
Wenn ich aber interrupt.h entferne erhalte ich Fehler, wegen sei().
Du sollst auch <avr/signal.h> entfernen, nicht <avr/interrupt.h>.
Schon klar. Habe ich so auch gemacht. Anderes Problem: Kann ich in der Interruptroutine ein Funktion starten? In der Zeit sollen auch keine anderen Interrupts aktiviert werden.
Sicher kannst du. Eine Interrupt Funktion ist auch nur eine Funktion wie jede andere, nur dass sie halt 'von der Hardware aufgerufen wird' und nicht von deinem Program selbst. Ob du das machen sollst, ist eine andere Frage: Alte Grundregel: Interrupt Funktionen sollten so schnell wie möglich durchlaufen. D.h. wenn deine Funktion viel Arbeit zu erledigne hat, dann ist es keine gute Idee sie aufzurufen.
Kommt hinzu, dass der Compiler dann die worst-case-Annahme macht und alle Register, die von dieser Funktion laut ABI zerstört werden könnten vorher retten muss. Ausnahme: die Funktion ist static deklariert und ist so kurz (oder "static inline"), dass sie vom Compiler gleich inline erweitert wird.
@Daniel: Jo sorry, sehe jetzt auch das es keinen anderen Sinn macht was ich schrieb. Ich hatte die eine Klammer falsch interpretiert und sie eigentlich nur rausgenommen wobei die ja nur im Kommentar stand (*an den kopf hau*) Aber wieso sendet er bei dir verschiedene Zeichen? Du schreibst doch dein empfangenes Zeichen in die Variable Zeichen und schreibst sie danach wieder ins UDR. D.h. er sendet das was du ihm vorher schickst oder nich?
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.