UART-Emppfang zu Ende.

Gast #605
Lesenswert?

Folgendes Problem habe ich:

Der Hardware-UART des ATMega103 empfängt vom PC-Terminal-Programm eine 
Zeichenkette,
die danach über einen Port parallel Byteweise ausgegeben wird.
Zur Kontrolle lasse ich die Zeichenkette auch wieder zum PC zurück 
senden, was auch klappt.

Damit nicht nur ein Zeichen (Byte) übertragen wird, muß ich anschließend 
wieder in die
Empfangs-Schleife springen. Da kommt man offenbar nicht mehr raus, so 
das nachfolgende
Programm-Teile nicht mehr abgearbeitet werden. Das Einfachste wäre, auf 
ein bestimmtes
Zeichen zu reagieren, das mit einer Branch-Anweisung aus der EmpfLoop 
heraus geht.
Die Empfangs-Datei kann nun aber alle möglichen Zeichen enthalten. Auch 
die schon
von DOS her bekannte Datei-Ende Markierung (EOF) scheidet also aus.
Da mein ATMega 4KByte Arbeitsspeicher hat, kann ich aber auch nicht erst 
mal alles
reinholen und sehen, wenn nichts mehr kommt. (765968KByte).

Bliebe da noch die Möglichkeit, feste Datei-Größen zu vereinbaren und 
einen Byte-Zähler
mitlaufen zu lassen, der bei vorbestimmtem Überlauf das Verlassen der 
UART-Routine veranlasst.

Der UART muß auf jeden Fall erst mal auf das PC-Programm warten, bis 
etwas kommt.
Das Terminal-Programm selbst läßt sich nicht vom UART aus steuern, weil 
z.B.: nur
die Hin und Rück-Sende Leitungen nebst Masse benutzt werden können.
Das ist auf meinem Experimentier-Board schon vom Hersteller so 
vorgegeben.

Welche Möglichkeiten gibt es noch, so etwas zu realisieren, bzw. wo 
sollte man eingreifen und wie.

Feste Datei-Größen kann ich bereitstellen, bzw. sind in der vorgesehenen 
Anwendung auch nötig.

1.Programmteil:
xxxxx

EmpfLoop:
;xxxxx      ; Hier müßte man wohl eingreifen?
SBIS  USR,RXC   ; Teste RXC-bit auf vorliegendes Zeichen.
JMP  EmpfLoop   ; Kein Zeichen vorhanden, warte.
IN  c,UDR     ; Hole Zeichen vom UART ab.

Mov  sr20Inv,c  ; Register c darf wegen SendLoop nicht invertiert 
werden.
Com  sr20Inv    ; Zeichen Invertieren wegen LED's.
;Out  PortB,sr20Inv  ; Zeichen auf PortB-LED's anzeigen.
Out  PortC,sr20Inv  ; Zeichen auf PortC-LED's anzeigen.
Jmp  SendLoop

SendLoop:
SBIS  USR,UDRE   ; Warte bis Sender bereit.
JMP  SendLoop   ; Sender noch nicht frei.
OUT  UDR,c     ; Sende Zeichen wieder zurück.

JMP  EmpfLoop

3.Programmteil:
xxxxx

Vielleicht hat jemand eine brauchbare Idee.
Vielen Dank im Voraus.
Wolfgang.
Gast #607
Lesenswert?

Hi.
Ja, die Errata-Seite von ATMEL hält mich davon ab.
Man beschreibt dort Probleme in Zusammenhang mit
Interrrupts. Da ich noch nicht viel Programmier-
Erfahrung habe, wollte ich erst mal alles im Polling-
Betrieb realisieren. Was nützt es mir, wenn ich dann
mit Interrupt etliche Sprung-Befehle meiden muß.

Aber vielleicht muß man ja nicht unbedingt den Stack
benutzen und legt die Rückkehr-Adressen in reservierten
Registern ab. Mal sehen, ob das eventuell geht.

Wolfgang.
Gast #2576326
Lesenswert?

W.Meyer schrieb:
> Ja, die Errata-Seite von ATMEL hält mich davon ab.
> Man beschreibt dort Probleme in Zusammenhang mit
> Interrrupts.

Dann nimm einen Timer/Counter, der mit jedem empfangenen Zeichen 
resettet wird und beim Erreichen eines von Dir zu definierenden Timeouts 
ein Flag setzt, das Du in Deiner Warteschleife zusätzlich zum RCX-Bit 
abfragen kannst.
Gast #2576461
Lesenswert?

Hallo,

anstatt eine feste Paketgröße zu vereinbaren, kannst du auch für jede 
Übertragung zuerst die Anzahl der zu übertragenden Bytes senden. Mit 
dieser Information kannst du im AVR herunterzählen, bis du alle Daten 
empfangen hast. Die Anzahl der Bytes muss natürlich ein festes Format 
haben, z.B. die ersten 4 Bytes, MSB first:

[Anzahl 3] [Anzahl 2] [Anzahl 1] [ Anzahl 0 ] [   Daten   ]

Daraus machst du dir einen long int:
1
unsigned long int data = 0;
2
for(int i = 0; i < 4; i++)
3
{
4
  data <<= 8;
5
  data |= UDR;
6
}

Mit dieser Lösung musst du keine Füllbytes übertragen, falls dein 
Datenpaket kleiner ausfällt als die vereinbarte Paketgröße.

Meinst du diese Errata: "Skip Instruction with Interrupts"? Das ist von 
2001, avr-gcc kann bestimmt mittlerweile damit Umgehen. Da du Assembler 
benutzt, kannst du ja selbst darauf achten, keine Skip-Instruktionen bei 
aktivierten Interrupts zu verwenden.
Gast #2576467
Lesenswert?

W.Meyer schrieb:
> Da ich noch nicht viel Programmier-Erfahrung habe, wollte ich erst
> mal alles im Polling-Betrieb realisieren.

Wenn dein Prozessor noch etwas anderes tun soll, als den USART-Empfänger 
zu pollen, müssen die anderen Tätigkeiten auch in der Abfrageschleife 
drinstehen.
Aber du merkst schon: Ohne Interrupt wird das bald zu einem Problem, 
weil die anderen Tätigkeiten dann so kurz sein müssen, dass du beim 
USART nichts verpaßt. Mit einem Timeout-Zähler blockierst du bis zum 
Ablauf der maximalen Wartezeit ebenfalls den Prozessor.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren