PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie einen Ringbuffer in Bascom programmieren?



AlterBursch
20.10.2006, 15:35
Hallo Bascom und C Experten,

ich will mit GCC als auch in einem Bascom Programm einen Ringbuffer für serielle 3 Byte Befehle per RS232 anlegen. Hat jemand ein bisschen Code oder gar eine Lösung für mich? Meine Versuche sind alle kläglich gescheitert weil es immer irgendwo Hänger gab.


Euer junger Hirsch
Alterbursch

PicNick
20.10.2006, 15:56
Naja, Althirsch, weiß nicht, wo du da hängenbleibst ?


const bufsize = nn
DIM buffer(bufsize] as byte
DIM Wrindex AS BYTE
DIM Rdindex AS BYTE

Wrindex = 1
Rdindex = 1





reinschreiben:
buffer(Wrindex) = 1.byte
gosub Incr_wrindex
buffer(Wrindex) = 2.byte
gosub Incr_wrindex
buffer(Wrindex) = 3.byte
gosub Incr_wrindex
return




Incr_wrindex:
incr Wrindex
if Wrindex > bufsize then
wrindex = 1
end if
return


rauslesen:
if Rdindex = Wrindex then
is_nix_da
else
1.byte = buffer(Rdindex)
gosub Incr_rdindex
2.byte = buffer(Rdindex)
gosub Incr_rdindex
3.byte = buffer(Rdindex)
gosub Incr_rdindex
end if
return




Incr_rdindex:
incr rdindex
if rdindex > bufsize then
rdindex = 1
end if
return


Ist die Grundform. wenn "bufsize" ein vielfaches von 3 ist, kann man auch ein bißchen sparen
Zu klären ist beim reinschreiben, ob überhaupt Platz ist und beim lesen, was is, wenn nix da ist.

Kommt auf die Anwendung an.

In C ist das genauso, nur daß Wrindex und Rdindex von 0 beginnen.


Für C gibts beispiele in unserer Wiki
https://www.roboternetz.de/wissen/index.php/FIFO_mit_avr-gcc

AlterBursch
23.10.2006, 14:07
Hallo Picnick
Ich bleibe nicht hängen, das Programm bleibt hängen :-) Erst dann hängen wir beide.

Das Problem besteht vermutlich darin das Daten auch dann eingehen wenn ich gerade Daten entnehme. Treten diese Konflikte bei dir nicht auf wenn Daten schnell fortlaufend eingehen?

Euer junger Hirsch
Alterbursch

PicNick
23.10.2006, 15:09
Typische Anwendung ist ja sowas wie "serialin=buffered", d.h. im Interrput kommen Daten rein, und von außen werden sie ausgelesen.
Da der Schreiber und der Leser ja jeder nur seinen Pointer(Index) verwenden, vertragen sie sich im Prinzip ja.
Heikel ist nur der Vergleich der Pointer (ob was da ist). Bei Byte-Index, ist das kein Problem, aber (wenn) 16-Bit Words verwendet werden, isses geraten,
vor dem Vergleich ein "disable interrupts"
und nachher wieder ein "enable" zu machen.

Bei 3-Byte "Blöcken" ist die Sache etwas gemischter, denn eigentlich dar der "write pointer" erst verändert werden, wenn wirklich 3 Bytes da sind.

Ich mach das mit einem zusätzlichen "temp" Pointer. d.h. erst wird über den geschrieben, und erst wenn die Message komplett ist, wird der "write" pointer gesetzt.
d.h. Für den Leser sind entweder alle 3 byte da oder garnix.

Klingt wirr, isses auch

Ruppi
23.10.2006, 15:10
Hallo junger Hirsch!

Ich habe für eine Frässteuerung folgendes gemacht:


'Fehlercodes
Const Error = 0
Const Ok = 1
Const Overflow = 2

'einen Ringspeicher definieren
Const Arraymax = 30
Dim Cmd(arraymax) As Byte
Dim Pakt As Byte , Pend As Byte, I As Byte

'den Ringspeicher initialisieren
Pend = 1
Pakt = 1

Pakt ist sowas wie ein Zeiger auf die aktuelle Position und Pend enthält den Index der letzten Position (die ja immer eine andere sein kann).
Beim Hinzufügen von Daten schreibe ich folgendes:


I = Pend + 1
If I > Arraymax Then I = 1
If I = Pakt Then
Printbin Overflow ; 'Fehlercode senden (Überlauf des Stacks)
Else 'kein Überlauf
Pend = I 'letzter Satz ist i
Cmd(pend) = Udr_byte(1) 'Das Kommando übergeben
Printbin Ok ;
End If

Ich sende also jedesmal eine Bestätigung, ob ein Kommando abgelegt werden konnte oder nicht. Wenn ich kein weiteres Kommando ablegen kann, weil der Ringspeicher voll ist, versuche ich solange zu senden, bis das Senden mit Ok bestätigt wird, also eigentlich ganz einfach.
Wichtig ist noch, dass beim Abarbeiten eines Kommandos der Zeiger Pakt erhöht wird, also:


Incr Pakt 'Zeiger auf aktuellen Satz erhöhen
If Pakt > Arraymax Then Pakt = 1 'wenn Überlauf, dann erneut beginnen



Kannst Du damit was anfangen?
Ich gebe zu, PicNicks Lösung ist schöner...

Ruppi

AlterBursch
24.10.2006, 09:15
Die Lösung mit Temp-Zeiger könnte passen da es ja 3 Bytes sind, hast du dafür zufällig ein größeren Auszug deiner Ringverwaltung parat?

PicNick
24.10.2006, 09:42
naja, eigentlich jein. Ich hab das für das Network-Project durchgezogen,
die entsprechenden Bascom-libraries bzw. Sourcen kannst du gerne haben.
Aber dabei ist eben unser Level-0 binär-data protokoll (f. UART) implementiert,
https://www.roboternetz.de/wissen/index.php/Network_Controller/PC_Praxis
das mischt die Sache einigermassen auf und macht sie wohl schwer leserlich.
(die Messages sind variabel lang, also keine fixe Länge wie bei Dir)

AlterBursch
25.10.2006, 12:42
Schade. Na dann werde ich mich durchbeißen und noch mal etwas coden. Dein Networkprojekt blicke ich nicht so ganz, ist aber für meine Zwecke sicher auch zu überfrachtet. Ich will nur einen starken Getriebemotor vernünftig steuern.