Archiv verlassen und diese Seite im Standarddesign anzeigen : Serialin Buffer
Guten Morgen
Ich hab da mal eine Frage bezüglich des Buffers.
Gibt es eine möglichkeit den Serialen Buffer zuvergrößern?
Beim mitlesen einer Schnittstelle kommt es bei mir zu komplikationen da der größte Frame 260 Byte groß ist und keine CTS oder RTS benutzt werden.
Da das Programm noch anderweitig beschäftigt ist kann es passieren das nicht alle Daten gelesen werden.
Also kann man den Buffer vergrößern oder hat jemand eine Lösung?
Nur so neben bei. Wieso kann ich den dritten Serialen Buffer z.B eines Atmega2560 nur auf 254 Byte setzen. Normal müssten doch 255Byte gehen oder nicht?
MfG
Bascom verwendet nur Bytes als Pointer für den ringbuffer. dadurch fällt mal alles darüber aus.
wegen den 254 muss ich annehmen, dass er bei seinen berechnungen sonst Probleme kriegt, das müßt' ich analysieren. Aber das eine Byte hülfe dir ja eh nix.
Ich fürchte, den RIngbuffer auf größer mußt du zu Fuß machen. Kommst du damit zurecht ?
Das eine Byte hilft mir nicht da hast du recht. Mich interessierte es bloß weil er beim serialin und beim serialin3 aktzeptiert er die size von 255. Nur beim serialin1 und 2 meckert Bascom beim kompilieren.
Den Ringbuffer zu Fuß. :-k Da könnte ich einen anstoß gerbrauchen, arbeite noch nicht lange mit Bascom und meine Programmierwissen ist ein wenig eingerostet.
Ein Anstoss:
Dim Base As Word
Dim Top As Word
Dim Wrpnt As Word
Dim Rdpnt As Word
Dim One_w As Byte
Dim One_r As Byte
Dim Buffer(260) As Byte
Buf_init:
Base = Varptr(buffer(1)) 'mem-adr von Buffer-base
Top = Base + 260 'mem adr von bufer top
Wrpnt = Base 'write pointer
Rdpnt = Base 'read pointer
Return
Buf_write:
One_w = Udr ' byte from UART
Out Wrpnt , One_w ' into buffer
Incr Wrpnt ' pointer + 1
If Wrpnt >= Top Then Wrpnt = Base ' wrap around
Return
Buf_read:
interrupts disable
If Rdpnt = Wrpnt Then
interrupts enable
One_r = 0 ' no data
Else
interrupts enable
One_r = Inp(rdpnt) ' read from pointer
Incr Rdpnt ' pointer + 1
If Rdpnt >= Top Then Rdpnt = Base ' wrap around
End If
Return
"Buf-write" passiert eigentlich in der Interrupt-routine
"Udr" wird bei dir anders heissen
Cool danke.
Wenn ich das richtig verstanden habe müsste das in etwa wie folgt aussehen.
$regfile = "m2560def.dat"
$crystal = 14745600
$baud = 921600
Config Com3 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Enable Interrupts
Enable Urxc2
On Urxc2 Buf_write
Dim Base As Word
Dim Top As Word
Dim Wrpnt As Word
Dim Rdpnt As Word
Dim One_w As Byte
Dim One_r As Byte
Dim Buffer(260) As Byte
Buf_init:
Base = Varptr(buffer(1)) 'mem-adr von Buffer-base
Top = Base + 260 'mem adr von bufer top
Wrpnt = Base 'write pointer
Rdpnt = Base 'read pointer
Return
Do
'Main Programm
Loop
Buf_write:
One_w = Udr2 ' byte from UART
Out Wrpnt , One_w ' into buffer
Incr Wrpnt ' pointer + 1
If Wrpnt >= Top Then Wrpnt = Base ' wrap around
Return
Buf_read:
Disable Urxc2
If Rdpnt = Wrpnt Then
Enable Urxc2
One_r = 0 ' no data
Else
Enable Urxc2
One_r = Inp(rdpnt) ' read from pointer
Incr Rdpnt ' pointer + 1
If Rdpnt >= Top Then Rdpnt = Base ' wrap around
End If
Return
Mir schwebt grad noch eine Funktion in form des Ischarwaiting vor (bzw. ein FlagBit). Das sollte allerdings kein Problem sein.
Danke nochmal für deine Hilfe.
MfG
Dem "Ischarwaiting" entspricht dieser Vergleich:
If Rdpnt = Wrpnt Then ..
Das interrupt-disablen ist, weil bei eine 2-byte vergleich ein Durcheinander rauskommen kann. Aber ich glaub, das wußtest du eh.
Btw: Wenn deine Frames ein definiertes Ende haben, würde ich den Check, ob das Frame komplett ist, in die ISR legen und dann einen speziellen Flag für das HauptProgramm setzen. Das wäre effizienter
Ja stimmt das entspricht dem "Ischarwaiting".
Allerdings kann man im Hauptprogramm so noch nicht erkennen ob Daten vorliegen. Mir fehlte da einfach ein Flag. Bin ich gestern aber nicht so schnell drauf gekommen. Ausgeschlafen ging das einfach schnell.
Das mit den Interrupts war mir nicht ganz klar und ist es auch noch nicht ganz. Kurzer verweis oder erklärungen wären hilfreich.
Leider haben die Frames eine variable länge. Je nach Information.
Ersten beiden Bytes beinhalten die Länge letztes die CRC.
Habe dafür bisher eine eigene Routine geschrieben.
Muss mir halt noch überlegen ob man beides verbinden kann.
MfG
Wenn er ein Word mit zwei Bytes vergleicht, vergleicht er ja erst das eine und dann das andere. Wenn aber genau da ein Interrupt dazwischen fährt und die ISR den "WrPnt" verändert, ist der Vergleich nicht koscher. Daher wird während des Vergleichs der interrupt disabled und gleich danach wieder aufgedreht.
Die ISR hat Zustände
1 Warten auf frame-start
2 lesen frame-länge
3 lesen daten
(4) Frame-crc OK ->Frame ready (oder nicht)
je nachdem läuft es etwas anders ab, den CRC rechnest du gleich mit, und wenn die Daten alle gelesen sind, muss ja dein nachberechneter CRC grad genau den Startwert haben.
? Ist das ein bekanntes frame-format ?
? welche art crc
Ist es nicht etwas ungeschickt den "Frametest" in der ISR zu machen?
Man soll doch ISR kurz halten oder nicht?
Ich könnte mir vorstellen das wenn der Test zu lange dauert ein paar bytes verloren gehen. Oder die ISR neu Startet.
Meiner meinung nach würde der Frametest besser in den Buf_read passen.
Lasse mich gerne überzeugen das es auch im ISR geht. Vllt. denke ich einfach zu "langsam".
Den Test mache ich bereits in der Reihenfolge in einer eigenen Routine.
Das soll allerdings später noch besser zusammen gefasst werden.
Ob es ein bekanntes Format ist weiß ich nicht. Kenne mich da zu wenig aus.
Der Frame besteht aus Länge, einer Komplement der Länge, NxInformation und CRC
CRC = summe Informationsbytes modulo 256
MfG
Naja, in epischer Breite soll eine ISR nicht sein. aber sooooo viel sind die paar checks ja auch nicht
Aber da will ich dir nix einreden.
Hi
Den "Frametest" in der ISR probiere ich noch aus.
Hab aber immer noch probleme beim lesen der Uart.
Es lief schon mal wesentlich besser als ich den Buffer mit einer Uart ausprobiert hatte.
Nachdem ich ein paar änderungen und erweiterungen eingebracht habe läufts nicht mehr rund und ich finde den Grund einfach nicht.
Entweder ist es ein simpler fehler und ich hab Tomaten auf den Augen oder schlimmstenfalls ein Timing Problem.
Im Anhang mal ein Bild von einem Daten log.
Links original Daten. Rechts ausgabe aus dem Mikroproz.
An der markierten Stelle sieht man das Problem. Er überliest ein paar "0" bytes.
Hier noch der Code.
$regfile = "m2560def.dat"
$crystal = 14745600
$baud = 921600
$lib "i2c_TWI.LBX"
Config Timer1 = Timer , Prescale = 1024
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Com2 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Com3 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Com4 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
'Config Serialin = Buffered , Size = 255
'Config Serialin1 = Buffered , Size = 40
'Config Serialin2 = Buffered , Size = 254
Config Serialin3 = Buffered , Size = 255
'Config Serialout = Buffered , Size = 40
'Config Serialout1 = Buffered , Size = 40
'Config Serialout2 = Buffered , Size = 40
Config Serialout3 = Buffered , Size = 40
Open "com1:" For Binary As #1
Open "Com2:" For Binary As #2
Open "Com3:" For Binary As #3
Open "Com4:" For Binary As #4
Declare Sub Frametest(bufin As Byte , Bufin_old As Byte)
'DECLARE FUNCTION Buf_read (ioport As Byte) As byte
Gosub Buf_init
Enable Interrupts
Enable Timer1
Enable Urxc
Enable Urxc2
On Urxc Buf1_write
On Urxc2 Buf3_write
'*****************************
'* Variablen deklaration *
'*****************************
Dim Lauf1 As Word 'Laufvariable beim schreiben der Uart
Dim Lauf2 As Word
Dim Lauf3 As Word
Dim Lauf(3) As Word 'Laufvariablen beim einlesen der Uart
Dim Kons As Bit 'Konsole auf TR1 (=0) TR2 (=1)
Dim Ioport As Byte 'Uarts einlesen durch eine Sub
Dim Base(3)as Word 'Basisadresse der Buffer (Anfang)
Dim Top(3) As Word 'Topadresse der Buffers (Ende)
Dim Wrpnt(3) As Word 'Pointer auf die Adressen des Buffers beim einlesen der Uart
Dim Rdpnt(3) As Word 'Pointer aud die Adressen des Buffers beim auslesen des Buffers
Dim Buf_size(3) As Word 'Menge der Daten im Buffer
Dim One_w(3) As Byte 'Zwischenspeicher beim einlesen der Uart
Dim One_r(3) As Byte 'Zwischenspeicher beim auslesen des Buffers
Dim Buf_wait(3) As Byte 'Flag Byte Daten im Buffer vorhanden
Dim Buffer1(300) As Byte 'Buffer der Uartdaten
Dim Buffer2(300) As Byte
Dim Buffer3(300) As Byte
Dim Compl As Byte 'Einer Komplement der Länge
Dim Framesize(3) As Word 'Länge des Datenrahmen
Dim Anfangflag(3) As Byte 'Zeichen das ein gültiger Frameanfang gefunden wurde
Dim Crc(3) As Byte 'enthält das Checksumergebnis zur überprüfung
Dim Dataflag(3) As Byte 'Zeichen dafür das gültige Daten im Uartarrygespeichert wurden 1=gültige Daten liegen vor 0=keine gültigen Daten vorhanden
Dim Buf As Byte , Buf_old As Byte 'Buffervariablen der eingelesenen Uart Bytes
Dim Uart1(300) As Byte 'zwischenspeicher Uartdaten
Dim Uart2(300) As Byte
Dim Uart3(300) As Byte
Dim Datapnt(3) As Word 'Pointer auf die Adresse eines Bytes von UartX(n) in der die Daten gespeichert werden sollen
Dim Database(3) As Word 'Adresse von UartX(1)
Dim K As Word 'Laufvariable CRC Schleife
Dim I As Word 'Laufvariable für For_Schleifen
'*****************************
'* Initialisierung *
'*****************************
Kons = 1
Database(1) = Varptr(uart1(1))
Database(2) = Varptr(uart2(1))
Database(3) = Varptr(uart3(1))
For K = 1 To 3
Dataflag(k) = 0
Anfangflag(k) = 0
Datapnt(k) = Database(k)
Crc(k) = 0
Next
I = 0
Shdn_max1 = 0 'ausgeschaltet Fehler im aufbau?
Shdn_max2 = 1
Shdn_max3 = 1
En_max1 = 0
En_max2 = 0
En_max3 = 0
'*****************************
'* Main *
'*****************************
Main:
Do
Ioport = 1
Gosub Uart_lesen
If Dataflag(ioport) = &HFF Then
Gosub Ctxd_schreiben
End If
Ioport = 3
Gosub Uart_lesen
If Kons = 1 And Dataflag(ioport) = &HFF Then
Gosub Crxdtr2_schreiben
End If
Loop
End
'*****************************
'* Uart lesen *
'*****************************
Uart_lesen: 'Daten der Konsole werden ausgeleden
Disable Interrupts
If Buf_size(ioport) <> 0 Then 'nur wenn Daten im Buffer vorhanden sind
Do
Enable Interrupts
Gosub Buf_read 'liest Byte aus Uartbuffer in One_r
'Call Buf_read(ioport)
Buf_old = Buf
'Buf= Buf_read(ioport)
Buf = One_r(ioport)
Call Frametest(buf , Buf_old) 'Prüfen auf gültigen Frame
Loop Until Dataflag(ioport) = &HFF Or Buf_size(ioport) = 0 'solange bis Buffer leer oder Frame gefunden
End If
Enable Interrupts
Return
'*****************************
'* Uart ausgabe *
'*****************************
Ctxd_schreiben:
Select Case Kons
Case 0 : 'Daten an Tr1
For Lauf1 = 1 To Framesize(ioport)
Put #2 , Uart1(lauf1)
Next
Case 1 : 'Daten an Tr2
For Lauf1 = 1 To Framesize(ioport)
Put #3 , Uart1(lauf1)
Next
End Select
Dataflag(ioport) = 0
Return
Crxdtr1_schreiben:
For Lauf2 = 1 To Framesize(ioport)
Put #1 , Uart2(lauf2)
Next
Dataflag(ioport) = 0
Return
Crxdtr2_schreiben:
For Lauf3 = 1 To Framesize(ioport)
Put #1 , Uart3(lauf3)
Next
Dataflag(ioport) = 0
Return
'*****************************
'* Frametest *
'*****************************
Sub Frametest(bufin As Byte , Bufin_old As Byte)
Compl = &HFF - Bufin_old
If Bufin = Compl And Anfangflag(ioport) = 0 And Bufin_old > &H01 Then
Anfangflag(ioport) = &HFF 'gültiger Anfang gefunden
Lauf(ioport) = 3 'Initialisierung
Crc(ioport) = 0
Out Datapnt(ioport) , Bufin_old 'Anfangsbyte (=Länge) an Arrayanfang schreiben
Incr Datapnt(ioport)
Out Datapnt(ioport) , Bufin '[Einerkomplement der Länge]
Incr Datapnt(ioport)
Framesize(ioport) = Inp(database(ioport)) 'Längen zwischenspeicher
Framesize(ioport) = Framesize(ioport) + 3 'Rahmensync.(2xLänge,CRC) gehört nicht zur länge -> +3
Elseif Anfangflag(ioport) = &HFF Then 'wenn anfang gefunden weiter einlesen bis Frameende
Out Datapnt(ioport) , Bufin
Incr Datapnt(ioport)
Disable Interrupts
If Lauf(ioport) = Framesize(ioport) Then 'Ende des Frames erreicht?
Enable Interrupts
If Bufin = Crc(ioport) Then 'gültige CRC?
Dataflag(ioport) = &HFF 'ja Flag für gültige Daten setzen (kein "Bitarray" möglich)
Anfangflag(ioport) = 0
Datapnt(ioport) = Database(ioport)
Else
'nein neuen Anfang suchen
Anfangflag(ioport) = 0
Datapnt(ioport) = Database(ioport)
End If
Else 'noch nicht am Ende des Frames dann
Enable Interrupts
Crc(ioport) = Crc(ioport) + Bufin 'Crc berechnen (CRC as Byte)
'CRC= Sum(Informationsbytes) mod 256
End If
Lauf(ioport) = Lauf(ioport) + 1 'Zähler um Ende zu finden
End If
End Sub
'*****************************
'* Buf_Init *
'*****************************
Buf_init:
'mem-adr von Buffer-base
Base(1) = Varptr(buffer1(1))
Base(2) = Varptr(buffer2(1))
Base(3) = Varptr(buffer3(1))
'mem adr von bufer top
Top(1) = Base(1) + 300
Top(2) = Base(2) + 300
Top(3) = Base(3) + 300
'write pointer
Wrpnt(1) = Base(1)
Wrpnt(2) = Base(2)
Wrpnt(3) = Base(3)
'read pointer
Rdpnt(1) = Base(1)
Rdpnt(2) = Base(2)
Rdpnt(3) = Base(3)
'Anzahl der Bytes im Buffer
Buf_size(1) = 0
Buf_size(2) = 0
Buf_size(3) = 0
Buf_wait(1) = 0
Buf_wait(2) = 0
Buf_wait(3) = 0
Return
'*****************************
'* Buf_read *
'*****************************
Buf_read:
'FUNCTION Buf_read (ioport As Byte) As byte
Disable Interrupts
If Rdpnt(ioport) = Wrpnt(ioport) Then
Enable Interrupts
Reset Buf_wait(ioport)
One_r(ioport) = 0 ' no data
Else
Enable Interrupts
One_r(ioport) = Inp(rdpnt(ioport)) ' read from pointer
'buf_read = One_r(ioport)
Incr Rdpnt(ioport) ' pointer + 1
Decr Buf_size(ioport)
End If
Disable Interrupts
If Rdpnt(ioport) >= Top(ioport) Then
Enable Interrupts
Rdpnt(ioport) = Base(ioport) ' wrap around
End If
Enable Interrupts
'End function
Return
'*****************************
'* Buf_write *
'*****************************
Buf1_write:
One_w(1) = Udr0 ' byte from UART
Out Wrpnt(1) , One_w(1) ' into buffer
Incr Wrpnt(1)
Incr Buf_size(1) ' pointer + 1
Buf_wait(1) = &HFF
If Wrpnt(1) >= Top(1) Then
Wrpnt(1) = Base(1) ' wrap around
End If
Return
Buf2_write:
One_w(2) = Udr1 ' byte from UART
Out Wrpnt(2) , One_w(2) ' into buffer
Incr Wrpnt(2)
Incr Buf_size(2) ' pointer + 1
Buf_wait(2) = &HFF
If Wrpnt(2) >= Top(2) Then
Wrpnt(2) = Base(2) ' wrap around
End If
Return
Buf3_write:
One_w(3) = Udr2 ' byte from UART
Out Wrpnt(3) , One_w(3) ' into buffer
Incr Wrpnt(3)
Incr Buf_size(3) ' pointer + 1
Buf_wait(3) = &HFF
If Wrpnt(3) >= Top(3) Then
Wrpnt(3) = Base(3) ' wrap around
End If
Return
Hoffe jemand kann mir helfen.
MfG
Nun, ich beschäftige mich grad mit dem Programm.
Rückfrage:
Bei unserem "long Ringbuffer"-Port darfst du kein "config serialin" angeben, da sind wir uns ja einig ?
Von welchem Gerät kommt das Frame ? ich glaub' , ich hab das Format noch nicht ganz kapiert, vielleicht kann ich wo nachsehen
Ja da sind wir uns einig. Die "config serialin" sind auskommentiert.
Hab mal ein Auszug der Spezi. im Anhang für das Format eingefügt. Sollte helfen das zu verstehen.
Prinzipiell ganz einfach.
MfG
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.