Ich verwende einen ATMega32 und das EEPROM AT24C512B sowie den Parallel Port. Nun sollen die über den Parallel Port geschickten Daten vom Mikrocontroller auf ein EEPROM geschrieben werden. Diese sollen später bei Knopfdruck über Usart ausgeben werden. Werden Daten gedruckt wird ein Interrupt ausgelöst und die Daten auf das EEPROM gespeichert. Nun habe ich bei genauerem Hinsehen festgestellt, dass die Daten bei Knopdruck nicht korrekt ausgegeben werden. Buchstabe werden verschluckt, andere doppelt geschrieben. Die "Knopf-" Ausgabe-Routine ist angehängt. Die falsche Ausgabe kann ja mehrere Gründe haben: 1.) Es gibt Probleme mit dem Intterrupt 2.) Die richtigen Daten liegen noch nicht an, wenn bereits aufs EEPROM geschrieben wird. (Was eigentlich nicht der Fall sein sollte, da der Interrupt erst ausgelöst werden soll, nachdem die richtigen Daten anliegen. So ist es jedenfalls für den Parallel Port beschrieben.) 3.) Es gibt an sich Probleme beim Schreibvorgang aufs EEPROM 3.) Uart-Probleme Nun habe ich mal folgendes ausprobiert: Ich lasse die Daten nicht auf EEPROM schreiben, sondern gebe sie direkt auf dem Uart aus. Zunächst einmal es werden keine Buchstaben doppelt geschrieben oder verschluckt. Aber komischerweise wird mein Dokument entweder ganz oder nur teilweise über den Uart ausgeben. Liegt es nun an der Uart-Schnittstelle? Weiß jemand Rat? Wie kann ich das oben besagte Problem eingrenzen? Auszug aus dem Quelltext: ISR (INT2_vect){ // STROBE impulse PRINTER_PORT |= (1<<BUSY); // set BUSY send_to_usart(DATA); PRINTER_PORT &= ~(1<<BUSY); } // ISR end void send_to_usart(unsigned char data) { while (!(UCSRA & (1<<UDRE))); // wait until sending is possible // --> UART Data Register Empty UDRE=1; UDR = data; /* The Uart Data Register is empty, the previous assignment was completed. Writes the sign "data" on the interface. */ }
>ISR (INT2_vect){ // STROBE impulse > PRINTER_PORT |= (1<<BUSY); // set BUSY > send_to_usart(DATA); > PRINTER_PORT &= ~(1<<BUSY); >} // ISR end >void send_to_usart(unsigned char data) { > while (!(UCSRA & (1<<UDRE))); // wait until sending is possible > // --> UART Data Register Empty UDRE=1; > UDR = data; >/* The Uart Data Register is empty, the previous assignment was >completed. Writes the sign "data" on the interface. */ >} Ganz schlecht! In der ISR keine langwierigen Sachen wie 'send_to_usart...' mit integrierter Warteroutine machen. Soetwas gehöhrt da nicht rein. Sonst kann es passieren, dass während eines 'sent_to_usart' ein/mehrere weitere(r) Interrupts auftreten, die dann nicht berücksichtigt werden. Besser: In der ISR ein Flag setzen und im Hauptprogramm dieses Flag prüfen und - nachdem das Nötige gemacht wurde - Flag löschen. Oder kannst du mit 100%iger Sicherheit sagen, das während eines 'send_to_usart' kein weiterer Interrupt auftreten kann?
Also ich bin der Meinung, dass bei Ausführung eines Interrupts alle weiteren Interrupts gesperrt werden. Oder etwa nicht?
tastendrücker wrote: > Oder kannst du mit 100%iger Sicherheit sagen, das während eines > 'send_to_usart' kein weiterer Interrupt auftreten kann? Ja, kann er schon, wenn er nämlich kein NONBLOCK angibt :-)
>Also ich bin der Meinung, dass bei Ausführung eines Interrupts alle >weiteren Interrupts gesperrt werden. Oder etwa nicht? Ja, die Interrupts sind gesperrt, aber die Ereignisse, die den Interrupt auslösen nicht. Das ist ja das Problem, das Ereignis tritt auf, aber ein Interrupt wird nicht ausgelöst, weil der vorige noch bearbeitet wird. Beispiel: Ein Timer läuft jede Sekunde über und das erzeugt einen Interrupt. In der ISR wird eine Variable 'Sekunde' hochgezält, die Uhrzeit neu berechnet und auf einem Display ausgegeben. Was passiert wohl, wenn die Berechnung und die Ausgabe der Uhrzeit länger als eine Sekunde dauert? Richtig, der Timer läuft zwar über, das erzeugt aber keinen Interrupt (weil der ja noch gesperrt ist) und die Uhr geht schon mal eine Sekunde nach...
hi habe immer noch Probleme mit meinem EEPROM. Es werden immer noch Buchstaben verschluckt bzw. doppelt geschrieben. Zunächst einmal hatte ich noch einen Fehler in der Timer-Einstellung (falscher Vorteiler). Dies habe ich behoben und nun sind weniger Fehler erkennbar. Weiterhin denke ich, dass es nicht an der Uart-Schnittstelle und dem sequentiellen Lesen des EEPROM liegt. Habe mal das EEPROM an nur einer Stelle ausgelesen (dort wo der Fehler war). Der Fehler war immer noch da. Also wird es wohl nicht am EEPROM lesen und Uart liegen. Folglich muss es wohl mit dem Schreiben zusammenliegen oder auch am Strobe-Signal. Habe die wichtigen Quelltexte angehängt. Vielleicht könnt ihr nen Blick draufwerfen? Ach ja: Die ISR2 ist zwar lang, aber es wird neben dem Timer0 Overflow Interrupt kein weiter genutzt. Der ISR2 gibt die Aktionen vom Timer0_Over frei.
Welchen Oszillator benutzt du? Internen RC-Oszillator oder Quarz-Oszillator? Der interne RC-Oszillator ist sehr ungenau (stark spannungs- und temperaturabhängig) -> Unkorrekte Baudrate beim UART -> fehlerhafte Datenübertragung
Ich verwende einen externen Quarz mit 11MHz, Fuse gesetzt. Baudrate ist auf 115200 8D,1S,0P eingestellt. Auch beim Mikrocontroller. Es ändert auch nix wenn ich die Baudrate ändere, die Fehler bleiben trotzdem. void uart_init(void) { // define baud rate #ifndef F_CPU #define F_CPU 11059000L //system clock in Hz #endif #define BAUD 115200L //baud rate // Berechnungen #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) //baud rate UBRRH = UBRR_VAL >> 8; UBRRL = UBRR_VAL & 0xFF; UCSRA &=~(1<<U2X); UCSRB |= (1<<RXEN); //Receiver enable UCSRB |= (1<<TXEN); //Transmitter enable //frame format: 8 Bit UCSRC &=~(1<<UMSEL); //Asynchron UCSRC &=~(1<<UPM1)|(1<<UPM0); //Parity Mode disabled UCSRC &=~(1<<USBS); //1 Stopbit UCSRB &=~(1<<UCSZ2); UCSRC|=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8 Datenbits }
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.