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