Forum: Mikrocontroller und Digitale Elektronik Zeichen einem String hinzufügen


von C. H. (hedie)


Lesenswert?

Hallo

Ich möchte solch einem String
1
.db "Tes",0

ein zeichen hinzufügen (ans ende)


jemand ne idee wie ich das tun könnte...

Un zugleich wie ich solch einen String löschen kann?


liebe grüsse
Claudio

von Johannes M. (johnny-m)


Lesenswert?

AVR? Zur Laufzeit? Wo liegen die Daten? Wenn im Flash, dann nur über den 
Bootloader. Wenn im EEPROM, dann ganz normal über einen EEPROM-Zugriff.

von C. H. (hedie)


Lesenswert?

AVR AtMega8

Sie liegen im EEPROM

Alles in ASM

Ich weiss dennoch nicht wie ein zeichen hinzufügen....

von Winne (Gast)


Lesenswert?

Was du haben möchtest gab es früher bei einigen Basicinterpretern eine 
dynamische Stringverwaltung (z.B. http://www.berkhan.com/atari/feat5.htm 
). Dies ist bei C meines Wissens nicht üblich obgleich AVR ähnliches gut 
gebrauchen könnten.
Aber vielleicht hilft dir dieser Link weiter (http://www.glglgl.de/pub/)

von C. H. (hedie)


Lesenswert?

Nun ist mein Projekt in Assembler

Gibts den dort auch was???

Danke für eure antworten

von Johannes M. (johnny-m)


Lesenswert?

Ein "String" der Form
1
.db "Tes", 0
ist identisch mit
1
.db 'T', 'e', 's', 0
Wenn der String jetzt nicht "Tes" sondern "Test" heißen soll, dann füge 
einfach das zusätzliche 't' hinten an. Zusätzlich muss dann noch der 
neue Nullterminator dahintergesetzt werden, damit die Software das 
String-Ende auch findet.

Wie man ins EEPROM ein Zeichen schreibt, steht in der Dokumentation bzw. 
im Tutorial.

von C. H. (hedie)


Lesenswert?

Und wie mach ich das in Software form?

add String1, 'H' ?

wohl kaum oder?

von Johannes M. (johnny-m)


Lesenswert?

Wenn Du ein Programm geschrieben hast, das den angegebenen String 
verwendet, dann hast Du doch wohl irgendwo eine Funktion, um diesen 
String aus dem EEPROM auszulesen, oder? Und so ähnlich wie das Lesen 
geht auch das Schreiben, nur dass dabei noch ein paar zusätzliche Dinge 
in Sachen Timing beachtet werden müssen.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher#EEPROM_2

von Winne (Gast)


Lesenswert?

In ASM hast du doch volle Gewalt über den gesamten SRAM Speicher und das 
EEPROM zur Laufzeit.

Der ASM bestimmt lediglich was im Flash dauerhaft angelegt wird. Sowie 
die Ausgangsposition in EEPROM und SRAM wenn du letztere dynamisch 
verwalten willst solltest, du die Prinzipien der dynamischen 
Speicherverwaltung studieren.

Und entsprechende Routinen in dein Programm intergrieren. Vielleicht hat 
sich ja schon mal jemand damit rumgeschlagen. eigentlich ist es relativ 
einfach ein zeiger zeigt auf die erste Variable. dort finden sich 
Status, Länge, Name,und Wert der Variablen sowie ein Zeiger zur nächsten 
Variablen. Enthält dieser eine Null so ist der folgende Speicher frei. 
Tja das Löschen von Variablen ist Leicht. Statusbit löschen... Speicher 
freigeben ist schwieriger. Zur Laufzeit müstest du Quasie den Speicher 
defragmentieren.

Naja ich wünsche Dir viel Spass damit.

von C. H. (hedie)


Lesenswert?

Hmmm....

Also ich glaube wir reden hier aneinader vorbei...

Ich möchte einem string (unabhängig ob er sich im EEPRROM oder sonst wo 
befindet) ein zeichen anhängen

Genauer gesagt... was über den uart hinein kommt.
Aber um den EEPROM zu schonen, wollte ich erstmal quasi einen flüchtigen 
Virtuellen string anlegen und wenn der text fertig ist, den dann in das 
EEProm schreiben....

Ich hoffe ich wisst was ich meine....

von Johannes M. (johnny-m)


Lesenswert?

Mit .db kann man nur konstante Daten im Flash oder im EEPROM anlegen. 
Wenn Du einen String im SRAM verwursten willst, musst Du ihn vor der 
Benutzung aus dem Flash oder dem EEPROM dorthin kopieren. In dem Falle 
gilt aber ähnliches wie oben gesagt: Ein ASCII-String besteht aus einer 
Reihe von Zeichen und dem abschließenden Nullterminator. Wenn Du ein 
Zeichen hinzufügen willst, schreibst Du es an die aktuelle Position des 
Nullterminators und schreibst dahinter einen neuen Nullterminator.

von C. H. (hedie)


Lesenswert?

Aber dieses "schreiben" meinst du ja von hand....

aber ich will das die Software das Empfangene zeichen (über uart) dem 
string hinzufügt....

von Johannes M. (johnny-m)


Lesenswert?

Claudio H. wrote:
> Aber dieses "schreiben" meinst du ja von hand....
Hä? Hat der µC eine Hand?

> aber ich will das die Software das Empfangene zeichen (über uart) dem
> string hinzufügt....
Das musst Du dem µC aber auch sagen. Und deshalb musst Du ein Programm 
schreiben, dass ein Zeichen über UART empfängt und an den bestehenden 
String anhängt...

von GSP (Gast)


Lesenswert?

Das schwierigste an strings anhaengen ist den Speicherplatz zu bekommen. 
Am einfachsten wenn der schon mal frei ist. Dann isses nur noch 
anhaengen und die laenge, resp terminierung anpassen. Da gibt es zwei 
moeglichkeiten. Bei den unpraktischen C- strings ist hinten eine Null. 
Die muss man dann auch neu schreiben. Bei den bequemeren Pascal strings 
ist das nullte byte die Laenge. Dann passt man die an.

von Johannes M. (johnny-m)


Lesenswert?

@GSP:
Es geht hier um Assembler. Bring den OP nicht noch mehr durcheinander 
(v.a. mit Pascal usw.).

In Assembler hat man selbst die Kontrolle über seinen Speicher. Und die 
Strings in AVR-Assembler sind NICHT nullterminiert. Deshalb muss man 
da ja auch noch die Null explizit dranhängen.

von C. H. (hedie)


Lesenswert?

Mir ist klar das ich ein programm schreiben muss....

Das will ich ja auch aber ich will wissen was ich schreiben muss, das er 
einem string ein zeichen anhängt....

Kann niemand ein beispiel machen, welches zb dem string1 den buchstaben 
h hinzufügt?

von Zyniker (Gast)


Lesenswert?

Ich auch!!!

Kann mir bitte jemand zeigen, wie ich zu einer gegebenen Zahl eine 
andere Zahl addieren kann - am besten mit einem kleinen 
Beispielprogramm!

Ich komm da einfach nicht weiter. Auch mit Google findet man da gar 
nichts.

von Johannes M. (johnny-m)


Lesenswert?

Claudio H. wrote:
> Mir ist klar das ich ein programm schreiben muss....
>
> Das will ich ja auch aber ich will wissen was ich schreiben muss, das er
> einem string ein zeichen anhängt....
>
> Kann niemand ein beispiel machen, welches zb dem string1 den buchstaben
> h hinzufügt?
Lies Dir das AVR-Tutorial sowie das, was ich oben schon geschrieben 
habe, durch und denk ein bisschen nach. Das musst Du mit den gegebenen 
Informationen hinbekommen.

von Karl H. (kbuchegg)


Lesenswert?

Claudio H. wrote:
> Mir ist klar das ich ein programm schreiben muss....
>
> Das will ich ja auch aber ich will wissen was ich schreiben muss, das er
> einem string ein zeichen anhängt....
>
> Kann niemand ein beispiel machen, welches zb dem string1 den buchstaben
> h hinzufügt?


In Assembler gibt es keine Strings.
Aber:
Du kannst dir im SRAM einen Speicherbereich reservieren lassen.
Und in diesen Speicherbereich werden dann die einzelnen Zeichen
gesammelt.

ZB. lässt du dir einen Speicherbereich für 20 Zeichen reservieren.
In einer anderen 'Variablen' im SRAM hast du zusätzlich noch
stehen, wieviele Bytes von diesen 20 Bytes tatsächlich für
deinen Text benutzt werden.
Wenn nun über die UAR ein neues Zeichen kommt, dann  musst du machen

* Zunächst mal den Zähler aus dem SRAM holen

* vergleichen ob der schon bei 20 steht
  wenn ja, dann passt logischerweise kein Zeichen mehr in deine
  20 reservierten Bytes hinein

* angenommen der Zähler ist noch nicht bei 20, dann

**  holst du dir die Startadresse des Speicherbereichs

**  zählst den Zähler dazu und kriegst somit
    die Adresse im Speicher, an der du das neue Zeichen ablegen kannst

**  da du jetzt die Speicheradresse hast, speicherst du das Zeichen
    von der UART ganz einfach dort ab

**  erhöhst den Zähler um 1

**  und speicherst den neuen Zählerstand wieder an seine Adresse
    im SRAM zurück

Und damit ist dein 'String' im SRAM um 1 Zeichen länger geworden.

von Gast (Gast)


Lesenswert?

char text[100] = "Tes";

text[3] = 't';
text[4] = 0;

schon ist text = "Test"

von Gast (Gast)


Lesenswert?

Es sollte dann kein Problem sein, dies in ASM zu übersetzen.

von GSP (Gast)


Lesenswert?

Leider ist das ein C Beispiel. In ASM geht das anders. Ich mach's mal 
mit meinen Pascal Strings.

.DSEG

mystring:    .byte 20   ;reserviere 20 bytes

.CSEG

    SetYPtr  mystring   ; ein makro : ylo=lo(mystring) yhi=hi(mystring)
    ldi      R16,Y+     ; die laenge ueberspringen
    ldi      R17,'T'
    st       Y+,R17
    ldi      R17,'e'
    st       Y+,R17
    ldi      R17,'s'
    st       Y+,R17
    ldi      R17,'t'
    st       Y+,R17
    SetYPtr  mystring   ; laenge anpassen
    ldi      R17,4
    st       Y,R17

Das war fuer das RAM. Fuer's EEPROM muss man das EEPROM ansprechen.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger wrote:

> ZB. lässt du dir einen Speicherbereich für 20 Zeichen reservieren.
> In einer anderen 'Variablen' im SRAM hast du zusätzlich noch
> stehen, wieviele Bytes von diesen 20 Bytes tatsächlich für
> deinen Text benutzt werden.

Ich möchte noch hinzufügen, dass das eine Möglichkeit ist
wie man Strings im Speicher halten kann.

Eine andere Möglichkeit besteht darin, dass man ein spezielles
Zeichen benutzt um das Ende des Strings zu markieren (C benutzt
zb. dieses Verfahren).

In diesem Fall gibt es den Zähler nicht mehr, dafür muss man
allerdings beim anfügen eines Zeichens vom Start des Speicher-
bereichs beginnend nach diesem Zeichen suchen um die Stelle
zu finden, wo das neue Zeichen gespeichert werden muss.
Dahinter kommt dann wieder dieses spezielle Zeichen um
das neue Ende des nun erweiterten Strings zu markieren.

von C. H. (hedie)


Lesenswert?

danke für eure antworten....

Mit diesen tipps werd ichs bestimmt hinkriegen...

grüsschen
Claudio

von Karl H. (kbuchegg)


Lesenswert?

Studier das mal
1
.include "m8def.inc"
2
3
.def   zero = r1            ; R1 wird immer eine 0 enthalten
4
.def   temp = r16
5
.def   temp1 = r17
6
7
.org 0x0000
8
            rjmp    main
9
 
10
main:
11
           ldi     temp, LOW(RAMEND)
12
           out     SPL, temp
13
           ldi     temp, HIGH(RAMEND)
14
           out     SPH, temp
15
16
   ;
17
   ; den String initialisieren, indem der Zeichenzaehler auf 0 gesetzt wird
18
   ;
19
           ldi     temp, 0
20
           mov     zero, temp
21
           sts     Str1Count, zero
22
23
           ldi     temp, 'T'
24
           rcall   addChar
25
26
           ldi     temp, 'e'
27
           rcall   addChar
28
29
           ldi     temp, 's'
30
           rcall   addChar
31
32
           ldi     temp, 't'
33
           rcall   addChar
34
35
finish:    rjmp    finish
36
37
;
38
; Fügt ein Zeichen zum String Str1 (Str1Count, Str1Bytes) hinzu
39
addChar:
40
           lds     temp1, Str1Count       ; Zeichenzaehler holen
41
           cpi     temp1, 20              ; passt noch was rein?
42
           brne    addChar1               ; ja!
43
           ret                            ; nein!
44
45
addChar1:  ldi     ZL, LOW( Str1Bytes )   ; Startadresse des 'Strings'
46
           ldi     ZH, HIGH( Str1Bytes )
47
48
           add     ZL, temp1              ; Zaehler dazuzaehlen ->
49
           adc     ZH, zero               ; dort muss das neue Zeichen
50
                                          ; gespeichert werden
51
52
           st      Z, temp                ; das Zeichen jetzt speichern
53
54
           inc     temp1                  ; den Zaehler erhöhen
55
56
           sts     Str1Count, temp1       ; und den Zaehler wieder abspeichern
57
           ret
58
59
60
           .DSEG
61
Str1Count: .BYTE  1
62
Str1Bytes: .BYTE  20

von GSP (Gast)


Lesenswert?

Wenn man schon ein extra byte rauswerfen muss, um einen String zu 
verwalten sollte man die aussagekraefigere Methode nehmen. Eine Laenge 
sagt nun mal mehr als eine nichtssagende Null.

von Karl H. (kbuchegg)


Lesenswert?

GSP wrote:
> Wenn man schon ein extra byte rauswerfen muss, um einen String zu
> verwalten sollte man die aussagekraefigere Methode nehmen. Eine Laenge
> sagt nun mal mehr als eine nichtssagende Null.

Du spielst auf die C Methode mit der abschliessenden 0 an?

Bin ich nicht ganz einverstanden. Mit Ausnahme des Falls, dass
an einen String etwas angehängt werden muss, ergibt die Terminierungs
0 meist deutlich einfacheren Code.
Des weiteren kann mit der Terminierungs-0 ein String praktisch
beliebig lang werden. Mit einem Länge Byte bist du auf 255 Zeichen
beschränkt (ok: nimmt man halt 2 Bytes und kommt damit lange aus)

von Gast (Gast)


Lesenswert?

> Wenn man schon ein extra byte rauswerfen muss, um einen String zu
> verwalten sollte man die aussagekraefigere Methode nehmen. Eine Laenge
> sagt nun mal mehr als eine nichtssagende Null.

Wie Karl schon sagte, beide Methoden haben ihre Vor- und Nachteile. Das 
ich sowohl im Delphi (Pascal) als auch mit C programmiere, muss ich 
sagen, das mir persönlich die C-Version im allgemeinen besser gefällt.

von GSP (Gast)


Lesenswert?

Ja, das sit richtig, dass der Delphi Shortstring mit der Lanege als 
nulltes Byte auf 255 Bytes beschraenkt ist. Hat aber dafuer den Vorteil, 
eine Null als Character enthalten zu koennen. Damit kann ich mit 
Binaerdaten, meist im Zusammenhang mit Kommunikation, auf die 
Funktionalitaet einer Stringklasse zurueckgreifen. Delphi behandelt die 
von selbst inplizit als Referenz. Ich weiss, die C Leute sind Stolz auf 
ihre Stern * Schreibweisen. In einem Controller ist ein String von sagen 
wir mal groesser 64, oder ein Buffer wie ich sie gebrauche, eh 
undenkbar. 255 ist sehr weit weg. In Controllern braucht man wirkliche 
Strings ja eh nur um sie auf einen LCD zu klatschen, oder um einem PC 
GUI die Caption eines Controls mitzuteilen. Beides ist sehr begrent in 
der Laenge.

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.