Forum: Mikrocontroller und Digitale Elektronik UART_ Werte empfangen???


von Christian (Gast)


Lesenswert?

Hallo Forum Freunde

Ich habe mir ein kleines Terminal Programm in VBA geschrieben mit dem
ich einzelne Werte über der Serielle Schnittstelle COM1 zu meinem
Controller senden kann.

So weit so gut.

Jetzt möchte ich diese Zeichen mit meinem Controller AT89S8252
empfangen und auswerten.

Das Problem liegt jetzt darin ich kann ein Zeichen empfangen, sende ich
aber ein zweites passiert gar nichts. Woran liegt das mache ich noch
ein Fehler im Code?

Muss ich irgent einen Puffer nach dem Empfangen wieder leeren oder
setzten???

Mit freundlichen Grüßen
Christian


Auszug aus meinem Quellcode

void main()
{
   unsigned char speicher_1;

   LCD_INI();
   LCD_text(0x80,"EMPFANGEN");
   LCD_kursor(2);
   COM_INI();

   while(1)
   {
  zeit();
  while(RI==0);
  speicher_1 = SBUF;
  LCD_variable(0x97,speicher_1);
   }
}

von ispodvala (Gast)


Lesenswert?

weiß nicht, ob deine C-Routinen das machen, aber RI muß per Software
gelöscht werden.

von Christian (Gast)


Lesenswert?

Sieht das dann wohl so aus??

void main()
{
   unsigned char speicher_1;

   LCD_INI();
   LCD_text(0x80,"EMPFANGEN");
   LCD_kursor(2);
   COM_INI();

   while(1)
   {
      zeit();
      RI = 0;
      speicher_1 = SBUF;
      LCD_variable(0x97,speicher_1);
   }
}

von crazy horse (Gast)


Lesenswert?

wofür ist zeit() gut? Warte lieber, bis ein Zeichen da

{while (!RXC);  //USR.7
 xxx=SBUF;      //das lesen von SBUF löscht automatisch das RXC-Flag
}

Wenn du sowieso nicht mit receiver-interrupt arbeitest, brauchst du
auch das Int-flag nicht

von Christian (Gast)


Lesenswert?

Hallo Crazy horse

das ist auf jeden Fall eine bessere Lösung. Kannst du mir noch sagen
was RXC ist. Das kenne ich nicht..

Wie würdest du denn so ein Problem angehen?? Gibt es insgesamt eine
bessere Lösung.

Christian

von crazy horse (Gast)


Lesenswert?

"das ist auf jeden Fall eine bessere Lösung. Kannst du mir noch sagen
was RXC ist. "
steht doch extra dabei, Bit7 des USR-Registers. Wird immer gesetzt,
wenn ein Zeichen empfangen wurde - lies dir mal das Kapitel über die
UART des AVR durch.

"Wie würdest du denn so ein Problem angehen?? Gibt es insgesamt eine
bessere Lösung."

die beste Lösung ist immer die, die mit minimalem Aufwand das leistet,
was man will. Ich persönlich kann Programme nicht leiden, die zur Not
ewig auf ein event warten - und wenn das nicht kommt, steht alles. Wenn
das Programm aber sowieso nichts anderes macht, als empfangene Zeichen
aufs Display zu schreiben, ist das allerdings egal - kommt nichts, wird
nichts geschrieben, der Effekt ist der Gleiche.
Ich betreibe die serielle Schnittstelle eigentlich immer im Interrupt
mit Empfangsbuffer, ankommende Zeichen werden in einen Buffer
geschrieben, das Hauptprogramm kann prüfen, ob was angekommen ist und
die Daten lesen, wenn nichts da ist - eben nicht.

Christian

von Christian (Gast)


Lesenswert?

Ok vielen Danke für die gute Info.

Ich glaube ich muss mich jetzt mit den Interrupt beschäftigen.
Genau das was du da beschreibst brauche ich.

"Interrupt mit Empfangsbuffer"

Hast du vieleicht ein paar Allgemeine Infos oder ein Quellcode Beispiel
in C.

Christian

von ispodvala (Gast)


Lesenswert?

ich dachte eigentlich an so etwas:

void main()
{
   unsigned char speicher_1;

   LCD_INI();
   LCD_text(0x80,"EMPFANGEN");
   LCD_kursor(2);
   COM_INI();

   while(1)
   {
  zeit();
  while(RI==0);
  speicher_1 = SBUF;
  RI=0;
  LCD_variable(0x97,speicher_1);
   }
}

Was RXC ist, weiß ich auch nicht. Übrigens auch nicht, was ein
AT89S8252 mit AVR gemeinsam hat, außer dem Hersteller.

von Christian (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ispodvala
danke für deine Antwort. Es funktioniert !!

Kannst du mir etwas zu "Interrupt mit Empfangsbuffer" sagen?
oder hast du vieleicht einen guten LINK oder Quellcode für mich.

Christian

von ispodvala (Gast)


Lesenswert?

Hmm..

du mußt eine ISR (Interrupt Service Routine) schreiben, in der daß
empfangene Byte unter der Speicherstelle, auf die global definierter
Zeiger zeigt abgelegt wird und der Zeiger für das nächste Byte
inkrementiert wird (RI=0 setzen nicht vergessen :). Das Hauptprogramm
überprüft, ob der Zeiger sich vom Initialwert(Konstante) unterscheidet.
Und wenn es so ist, den Puffer ausliest und den Zeiger zurücksetzt.
Wie du dem Compiler sagst, daß es eine ISR ist, steht in der Doku.

Viel Erfolg.

von Christian (Gast)


Lesenswert?

Danke ispodvala

Das ist Neuland für mich...
Aber ich werde das schon hin bekommen.

Christian

von crazy horse (Gast)


Lesenswert?

bisschen kompizierter ist es schon.
Am einfachsten arbeitet es sich mit einem Ringbuffer, sagen wir mal 8
byte gross.
Zur Verwaltung benutzt man 3 Register, einen Schreibpointer, einen
Lesepointer und ein Zählregister (Anzahl der empfangenen Bytes).
-Zeichen wird empfangen -> Rx-Int wird ausgelöst
-das byte wird an der durch den Schreibpointer addressierten
Speicherzelle abgelegt
-der Schreibpointer wird erhöht und geprüft, ob dabei die max.Adresse
überschritten wurde, wenn ja, auf die Anfangsadresse zurücksetzen
-byte-Zähler erhöhen fertig.

Gelesen wird, wenn Zeit dafür ist. Zuerst prüfen, ob der Counter > 0
wenn ja:
-ein byte aus der durch den Lesepointer adressierten Speicher holen
-Lesepointer erhöhen, wenn > max_Adresse zurücksetzen
-byte-Zähler erniedrigen

Wenn man es ganz gut machen will, kann man noch ein Flag für den
Bufferoverrun (mehr Zeichen empfangen, als der der Buffer aufnehmen
kann) programmieren, damit man erkennen kann, dass etwas verloren
wurde.

von Christian (Gast)


Lesenswert?

Hallo crazy horse

Ich kann es nur noch mal wiederholen vielen Dank für die super
Anleitung. Ich glaube das hilft mir auf jeden Fall sehr weiter.

Ich ärger mich gerade mit meinem Handy herum.
Ich sende meinem Handy den Befehl "AT ccr" und möchte nun das OK
empfangen. Es kommt aber leider gar nichts...

Meine Aufgabe ist es eine SMS mit dem Controller auszuwerten..
Senden ist kein Problem nur das Empfangen..
Ich weiß nicht warum.

Grüße Christian

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.