- Labornetzteil AliExpress         
Ergebnis 1 bis 6 von 6

Thema: INSTR() nur bis 254?

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    22.05.2006
    Ort
    Baden
    Alter
    41
    Beiträge
    102

    INSTR() nur bis 254?

    Anzeige

    Powerstation Test
    Hallo zusammen,

    Ich schreibe momentan ein Programm mit dem ich eine SD-Karte mit einem Mega32 auslese. Das ganze mache ich OHNE dateisystem. Ich lege in Windows auf einer mit FAT16 Formatierten SD-Karte eine Textdatei an die folgenden Inhalt hat: "<START>Datenbereich<ENDE>". Mit dem µC lese ich dann immer einen Sektor (512Bytes) in einen String ein und durchsuche den anschließend nach meinem Startstring. In meinem Fall "<START>". Anschließend Suche ich nach dem Endstring; in meinem Falll "<ENDE>".
    Dann kann ich genau sagen, wo die Daten auf der SD-Karte liegen.
    Das ganze funktioniert bisher FAST einwandfrei. "<START>" findet er immer in Sektor 771 an Stelle 1. Solange "<ENDE>" vor 254 ist funktioniert es auch, aber sobald das Ende nach 254 ist fehlt ihm 255 Aus Stelle 400 wird dann also z.b. 145. Die Variable ist vom Word-typ, aber er speichert wohl nur das untere byte ab

    Hier mal mein Quellcode (Falls wer verbesserungen weiß, immer her damit!):
    Code:
    $regfile = "m32def.dat"
    $crystal = 16000000
    $lib "mmc.lib"
    Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.7 , Rs = Portc.6
    Config Lcd = 16 * 4
    $include "config_mmc.bas"
    Dim Berror As Byte
    Dim Abuffer As String * 512                                 ' Hold Sector to and from CF-Card
    Dim Wsrampointer As Word                                    ' Address-Pointer for write
    Dim Lsectornumber As Long                                   ' Sector Number
    Dim Ende As Byte
    Dim S_position As Word
    Dim E_position As Word
    Dim S_sektor As Long
    Dim E_sektor As Long
    Dim Datenmenge As Word
    Dim Temp As Word
    
    Ende = 0
    Lsectornumber = 0
    Cls
    If Gbdriveerror = 0 Then
       Cls
       Do
         Wsrampointer = Varptr(abuffer)
         Berror = Drivereadsector(wsrampointer , Lsectornumber)
         If S_position = 0 Then
           S_position = Instr(1 , Abuffer , "<START>")
           S_sektor = Lsectornumber
         End If
         If S_position <> 0 Then
           E_position = Instr(1 , Abuffer , "<ENDE>")
           If E_position <> 0 Then
             E_sektor = Lsectornumber
             Ende = 1
           End If
         End If
         Incr Lsectornumber
       Loop Until Ende = 1
    Else
       Lcd "Fehler :-("
    End If
    If S_sektor = E_sektor Then
       Datenmenge = S_position + 7
       Datenmenge = E_position - Datenmenge
    Else
       Datenmenge = S_position + 6
       Datenmenge = 512 - Datenmenge
       Temp = E_sektor - S_sektor
       Temp = Temp - 1
       Temp = Temp * 512
       Datenmenge = Datenmenge + Temp
       Datenmenge = Datenmenge + E_position
       Datenmenge = Datenmenge - 1
    End If
    If Gbdriveerror = 0 Then
       Cls
       Lcd S_sektor ; ":" ; S_position ; "-" ; E_sektor ; ":" ; E_position
       Locate 2 , 1
       Lcd "Menge: " ; Datenmenge ; " Bytes"
    End If
    End                                                         'end program
    Falls das wirklich nur bis 254 geht muss ich wohl selbst was stricken. Dann lese ich es in ein Array anstatt einen String ein und muss mir dann selbst eine Suchfunktion basteln. Falls dafür jemand einen Tipp hat wäre ich sehr verbunden!

    Gruß
    Marius

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.11.2006
    Ort
    olargues
    Beiträge
    776
    hi

    hier ein auszug aus der Bascom hilfe für die definition von STRING:

    · String (up to 254 bytes). Strings are stored as bytes and are terminated with a 0-byte. A string dimensioned with a length of 10 bytes will occupy 11 bytes.


    das erklärt es dir dann.

    klaus

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    22.05.2006
    Ort
    Baden
    Alter
    41
    Beiträge
    102
    Hm... stimmt, das erklärt einiges.

    Was ich dann aber nicht verstehe:
    Wieso funktioniert es dann überhaupt? Er liest ja die kompletten 512Bytes ein und er findet auch die Endposition, also muss er auch alles durchsuchen. Einzig und allein der Rückgabewert müsste als Word anstatt Byte sein, dann würde es funktionieren. Andernfalls käme er ja nie zu der Zeile "Ende = 1" und käme nie aus der Schleife raus. Daher bin ich auch nicht auf diese Lösung gekommen...

    Also muss ich jetzt mal versuchen mir selbst eine Suchfunktion zu basteln.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    22.05.2006
    Ort
    Baden
    Alter
    41
    Beiträge
    102

    Neue Lösung

    Hi

    Ich hab das jetzt etwas anders gelöst.

    Code:
    $regfile = "m32def.dat"
    $crystal = 16000000
    $lib "mmc.lib"
    Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.7 , Rs = Portc.6
    Config Lcd = 16 * 4
    Dim Abuffer As String * 512 At $60                          ' Hold Sector to and from CF-Card
    Dim String1 As String * 254 At $60 Overlay
    Dim String2 As String * 254 At $10a Overlay
    Dim String3 As String * 171 At $1b4 Overlay
    $include "config_mmc.bas"
    Dim Berror As Byte
    Dim Wsrampointer As Word                                    ' Address-Pointer for write
    Dim Lsectornumber As Long                                   ' Sector Number
    Dim Ende As Byte
    Dim S_position As Word
    Dim S_position2 As Byte
    Dim S_position3 As Byte
    Dim E_position As Word
    Dim E_position2 As Byte
    Dim E_position3 As Byte
    Dim S_sektor As Long
    Dim E_sektor As Long
    Dim Datenmenge As Word
    Dim Temp As Word
    
    Ende = 0
    Lsectornumber = 0
    Cls
    If Gbdriveerror = 0 Then
       Cls
       Do
         Wsrampointer = Varptr(abuffer)
         Berror = Drivereadsector(wsrampointer , Lsectornumber)
         If S_position = 0 Then
           S_position = Instr(1 , String1 , "<START>")
           S_position2 = Instr(1 , String2 , "<START>")
           S_position3 = Instr(1 , String3 , "<START>")
           If S_position2 <> 0 Then
              S_position = S_position2 + 170
           End If
           If S_position3 <> 0 Then
              S_position = S_position3 + 340
           End If
           S_sektor = Lsectornumber
         End If
         If S_position <> 0 Then
           E_position = Instr(1 , String1 , "<ENDE>")
           E_position2 = Instr(1 , String2 , "<ENDE>")
           E_position3 = Instr(1 , String3 , "<ENDE>")
           If E_position2 <> 0 Then
              E_position = E_position2 + 170
           End If
           If E_position3 <> 0 Then
              E_position = E_position3 + 340
           End If
           If E_position <> 0 Then
             E_sektor = Lsectornumber
             Ende = 1
           End If
         End If
         Incr Lsectornumber
       Loop Until Ende = 1
    Else
       Lcd "Fehler :-("
    End If
    If S_sektor = E_sektor Then
       Datenmenge = S_position + 7
       Datenmenge = E_position - Datenmenge
    Else
       Datenmenge = S_position + 6
       Datenmenge = 512 - Datenmenge
       Temp = E_sektor - S_sektor
       Temp = Temp - 1
       Temp = Temp * 512
       Datenmenge = Datenmenge + Temp
       Datenmenge = Datenmenge + E_position
       Datenmenge = Datenmenge - 1
    End If
    If Gbdriveerror = 0 Then
       Cls
       Lcd S_sektor ; ":" ; S_position ; "-" ; E_sektor ; ":" ; E_position
       'Lcd E_position ; "--" ; E_position2
       Locate 2 , 1
       Lcd "Menge: " ; Datenmenge ; " Bytes"
       Thirdline
       Lcd "Text"
    End If
    End                                                         'end program                                                       'end program
    So funktioniert es jetzt einwandfrei. ich hab extra 3 Strings genommen, die sich überschneiden, damit er auch was findet, wenn z.B. "<ENDE>" genau an der Grenze der Strings steht.

    Nun muss ich aber noch den Sonderfall einbauen, dass der String "<START>" bzw. "<ENDE>" über eine Sektorgrenze geht. Das wird noch aufwändig

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.11.2006
    Ort
    olargues
    Beiträge
    776
    hallo majuz,

    als ich gestern abend nochmal so drüber nachdachte, kam mir auch so ein ähnliches konstruct mit hintereinanderliegenden strings und overlays in den sinn.

    so hast du es ja nun auch gelöst .

    alternativ dachte ich jedoch darüber nach, ob die string-lösung überhaupt so ideal ist.

    hast du mal drüber nachgedacht, statt string ein array of byte zu nehmen?
    du könntest zwei byte am anfang jeden blockes als längenangabe des datensatzes reservieren. ob du diese längenangabe nun alle 612 oder alle 256 byte setzt bleibt ja dir überlassen.

    so ein system scheint mir wesentlich einfacher zu verarbeiten. es erzeugt dann zwar ungenutze bereiche innerhalb der datenblöcke aber bei den grossen speicherkarten kann man sich das ja leisten.

    gruss klaus

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    22.05.2006
    Ort
    Baden
    Alter
    41
    Beiträge
    102
    Es müsste eigentlich kein String sein.
    Was es am Ende geben soll:
    Ich Bastle derzeit an der Steuerung einer Eigenbau-CNC-Fräse. Ich möchte die Daten (Wie genau die letztendlich aussehen weiß ich noch gar nicht ) mit dem PC auf eine SD-Karte schreiben und dann mit dem AVR auslesen. Dieses Teilprogramm um das es hier geht soll quasi "nur" faststellen, wo auf der SD-Karte die Daten liegen und wie viele Daten es sind. Wenn ich dann direkt hinter "<START>" 2 Bytes reserviere für die Menge der Daten kann ich mir immerhin das "<ENDE>" und die Rechnungen am Programmende sparen.
    Ein anderes Teilprogramm liest die Daten dann aus und verarbeitet sie (Schrittmotoren ansteuern).

    Am einfachsten wäre es natürlich, wenn das Programm am PC (schreibe ich in VB6) in einem vordefinierten Sektor anfängt zu schreiben. Dann müsste ich nur diesen Sektor auslesen und hätte in den ersten Bytes die Datenmenge stehen. Wie ich allerdings mit VB auf die Sektoren der SD-Karte schreibe konnte ich noch nicht finden

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests