Forum: Mikrocontroller und Digitale Elektronik EEPROM Daten lesen Problem


von Elbegucker (Gast)


Angehängte Dateien:

Lesenswert?

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.  */
}

von Elbegucker (Gast)


Lesenswert?

HILFE!!!!

von tastendrücker (Gast)


Lesenswert?

>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?

von Elbegucker (Gast)


Lesenswert?

Also ich bin der Meinung, dass bei Ausführung eines Interrupts alle 
weiteren Interrupts gesperrt werden. Oder etwa nicht?

von Sven P. (Gast)


Lesenswert?

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 :-)

von tastendrücker (Gast)


Lesenswert?

>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...

von elbegucker (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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

von Elbegucker (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.