Forum: Mikrocontroller und Digitale Elektronik [ASM]String von UART aufteilen


von pilo (Gast)


Lesenswert?

Hallo zusammen,

Ich glaube hier gibt es die richtigen Menschen, die mir bei meinem 
Problem helfen können :)

Problem ist folgendes:

Ein AVR (Mega8) soll vom PC per UART einen String nach dem Schema a/b/c 
gesendet bekommen.
Der AVR soll dies nun zerlegen und a -> R17 , b -> R18 und c -> R19 
speichern. Also treu nach der funktion split() in Bascom AVR.
Der Wertebereich: 0 =< a,b,c =< 255 (Also jeweils 1 Byte)

Meine Frage nun:
Wie genau läuft diese Splittung ab? Ich habe absolut keine Ahnung, wie 
ich das machen soll. Um Hilfe wäre ich sehr dankbar!

PS: Bin noch Neuling in ASM. Kenne mich zwar schon ein wenig aus, aber 
bitte nicht zu kompliziert :)

von Naja (Gast)


Lesenswert?

Es kommt für die Antwort auf Deine Frage an, ob Du selbst das 
Datenregister ausliest oder ob eine schon vorhandene Funktion die 
empfangenen Bytes in einem Buffer speichert. (Buffered IO)

Falls ersteres der Fall ist, dann würdest Du solange warten bis das 
Datenregister etwas enthält, also etwas empfangen wurde. Günstigerweise 
geschieht dies in einem Interrupt. In dem Interrupt lädst Du dann den 
Inhalt des Datenregisters erstmal irgendwohin. Damit der Interrupt immer 
das selbe machen kann, wird das empfangene Byte eben auch immer in das 
selbe Register geladen. Zusätzlich setzt Du ein weiteres (immer 
gleiches) Register. In der HAuptschleife fragst Du diese zweite Register 
ab und falls es gesetzt ist, speicherst Du das erste Register in das 
letztlich gewünschte R17, R18, R19. Zusätzlich brauchst Du also noch ein 
Register in dem Du die empfangenen Bytes zählst.

Im zweiten Fall, wird die Empfangsroutine auch irgendwie zu erkennen 
geben, das etwas empfangen wurde und es wird eine weitere Routine geben 
mit der das zuletzt empfangene Byte aus dem Buffer gelesen werden kann. 
Ab hier ist es dann wie im ersten Fall. Du zählst mit und speicherst je 
nach Zählerstand in R17, R18 oder R19.

von Naja (Gast)


Lesenswert?

Da Du sowieso noch am Anfang stehst, würde ich das Problem in zwei 
Schritten angehen.

1. Unabhängig davon, wieviele Bytes Du erwartest, erstmal einfach Bytes 
von der seriellen Schnittstelle lesen.
2. Dann erst anfangen mitzuzählen und in R17, R18 und R19 verteilen.

von oldmax (Gast)


Lesenswert?

Hi
Ich habe bisher meine UART_Routinen mit einem Buffer geschrieben. So 
erklärt bspw. Buffer:   .Byte 100 einen 100 Byte großen Adressraum. Das 
Z-Register (R26 / R27) wird zum Adressierregister erklärt.
1
LDI  ZL,LOW(Alarm_CTRL_B)  ; Z-Pointer auf Pufferadresse
2
LDI  ZH,HIGH(Alarm_CTRL_B)

Mit zwei Variablen
  Read_Pos: .Byte
  Write_Pos: .Byte
          hast du einen Offset auf die Pointeradresse.
1
   
2
IS_Was_Da:
3
   ;  Buffer lesen, wenn Read_Pos und Write_Pos unterschiedlich
4
   LDS Reg_1, Read_Pos ; Leseposition erhöhen
5
   INC Reg_1
6
   CPI Reg_1, 100  ; Grenze abfragen
7
   BRLO Store_RP ; Zeiger ablegen
8
   CLR Reg_1
9
Store_RP:
10
   STS Read_Pos, Reg_1
11
   ADD ZL, Reg_1    ; 
12
   ADC ZH, 0                 ; 16 Bit Addition für die Leseposition
13
   LD Reg_1, Z               ; Wert einlesen
14
   STD Work_Byte, Reg_1  ; und zur Verarbeitung ablegen
15
   .... ; oder weiter auswerten
16
  RET
Wie funktioniert’s? Eigentlich ganz einfach. Die beiden Variablen 
Read_pos und Write_pos sind zuerst gleich, daher wird im Main – Programm 
zyklisch auf Ungleichheit geprüft.
1
   LDS Reg_1, Read_Pos
2
   LDS Reg_2, Write_Pos
3
   CP Reg_1, Reg_2
4
   BREQ Is_Nix
5
   RCALL IS_Was_Da
6
Is_Nix:
7
   .....

Die Interrupt-Routine vom USART läuft in gleicher Weise wie die 
Leseroutine, nur das ein Wert in den Puffer geschrieben wird. Dabei 
verändert sich der Zeiger Write_Pos und das Hauptprogramm erkennt eine 
eingetroffene Information. Das erste Byte wird bearbeitet. Laufen 
weitere Bytes ein, wird die Differenz zwischen Read_pos und Write_Pos 
größer, kommen keine Daten mehr, findet irgendwann ein Ausgleich beider 
Zeiger statt.
Gruß oldmax

von pilo (Gast)


Lesenswert?

Hm..
Ich blicke durch diese ganzen Beispiele nicht ganz durch..
Der String, den der AVR bekommt ein String a'la "255/255/255" (Das ist 
maximum)

Nun möchte ich die bytes einzeln in Register speichern.
Täusche ich mich, oder sind die / auch Bytes? Dann wären es 5 Bytes, 
wobei die Slashes wegfallen sollen. Mich interessieren nur die Integers 
:)

Oder sollte ich da überhaupt keinen trenner einbauen?

von Karl H. (kbuchegg)


Lesenswert?

pilo schrieb:
> Hm..
> Ich blicke durch diese ganzen Beispiele nicht ganz durch..
> Der String, den der AVR bekommt ein String a'la "255/255/255" (Das ist
> maximum)

OK, also String Übertragung

> Nun möchte ich die bytes einzeln in Register speichern.
> Täusche ich mich, oder sind die / auch Bytes?

Klar.
Alles was du vom PC bekommst, jedes einzelne Zeichen, ist letztendlich 
ein Byte

> Dann wären es 5 Bytes,

Nein. Es sind 11
Das heißt: ohne das Trennzeichen, das du noch benötigst um das Triplet 
einwandfrei erkennen zu können

Für den Text  "255/255/255" bekommst du nacheinander die Bytes

0x32 0x32 0x35 0x2F 0x32 0x32 0x35 0x2F 0x32 0x32 0x35

geliefert. Einfach mal nach "ASCII Tabelle" googeln und du verstehst wie 
diese Bytes zustandekommen.

> wobei die Slashes wegfallen sollen. Mich interessieren nur die Integers
> :)
>
> Oder sollte ich da überhaupt keinen trenner einbauen?

Wie willst du dann im Text
   234512
die 3 Zahlen identifizieren. Ist das jetzt 234 51 2 oder 23 45 12 oder 
234 5 12 oder ....

Als allererstes musst du dir im klaren sein, wie du in Assembler einen 
String (also eine Abfolge von Zeichen) speichern willst. Damit fängt 
alles an.

von oldmax (Gast)


Lesenswert?

hi
Ich nehme an, Pilo redet von Bytes, die er überträgt, das wären dann 5, 
nur ist dies äußerst ungeschickt ausgedrückt. Also, entweder du 
überträgst Bytes oder ASCII, da solltest du dir schon klar drüber sein. 
Dem Controller ist's so ziemlich egal, was die USART- Routine bekommt, 
daher hab ich dir das Beispiel mit dem Puffer geschrieben. Wenn du es 
richtig machst, löst der USARt einen Interrupt aus, wenn er ein Byte 
erhalten hat. Dieses muß nun irgendwo gemerkt werden, um irgendwann 
einmal bewertet zu werden. Das kann man in einem Puffer machen. ( 
Ringpuffer) Wenn du ASCII überträgst, könnte es sein, das dein PC gar 
nicht erst etwas sendet, weil er Steuerzeichen oder sonstwas aus dem 
ASCII-Code liest. Da mußt du schon wissen, was du tust. Willst du 
wirklich die 255 als ASCII verschicken, dann sieht das oaus, wie vorher 
beschrieben
"2","5","5", Bytewert 32h,35h,35h oder binär 00110010b, 00110101b, 
00110101b doder oder oder....
Befaß dich erst mal mit den grundlegenden Begriffen, dann verstehst du 
auch, im Controller diese zu bewerten.
Gruß oldmax

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.