| |
Visual-Basic EinsteigerSektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 12.06.09 13:12 |
| Hallo zusammen,
Ich suche eine Möglichkeit mit VB6 gezielt Sektoren einer SD-Karte zu beschreiben. Diese möchte ich anschließend mit einem Microcontroller auslesen. Ich möchte damit Daten von meinem VB-Programm zu meiner Selbstbau-CNC-Fräse übertragen.
Ich bin dabei noch in der Entwicklung. Bisher habe ich die Möglichkeit gefunden einfach unter Windows eine Textdatei anzulegen mit einem eindeutigen Schlüsselwort am Anfang und dann den Daten. Dann musste der Microcontroller einen Sektor nach dem andern nach dem Schlüsselwort durchsuchen, damit er wusste wo die Daten liegen. Wenn ich die Daten gezielt in Sektoren schreiben könnte würde der µC entlastet.
Ich hoffe es kann mir jemand helfen!
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 13.06.09 00:28 |
| Hallo,
inzwischen bin ich ein kleines Stückchen weiter:
Ich habe hier ein PDF gefunden, das zumindesteinmal erklärt, wie man die einzelnen Sektoren aus VB heraus lesen kann. Um zu kontrollieren, ob er richtig liest habe ich hier ein Programm gefunden, das das auch kann (etwa bei 2/3 der Seite: SD_RAW.exe).
Hier mal mein Programm:
In einem Modul habe ich den Code aus dem PDF platziert.
Was dieser Code genau macht kapiere ich nicht wirklich
in der Form:
Dim buffer(512) As Byte
Dim akt_sektor As Integer
Private Sub Command1_Click()
GetDriveHandle "e:"
End Sub
Private Sub Command2_Click()
CloseDriveHandle
End
End Sub
Private Sub Command3_Click()
akt_sektor = akt_sektor + 1
List1.Clear
Dim i As Integer
ReadSectorFromDrive buffer()
sektor_anzeigen
End Sub
Private Sub Command4_Click()
Dim i As Integer
For i = 1 To 10
ReadSectorFromDrive buffer()
akt_sektor = akt_sektor + 1
Next i
sektor_anzeigen
End Sub
Private Sub Command5_Click()
Dim i As Integer
Dim j As Integer
For i = 0 To 1000
ReadSectorFromDrive buffer()
akt_sektor = akt_sektor + 1
If buffer(0) = 60 Then
sektor_anzeigen
Exit Sub
End If
Next i
End Sub
Sub sektor_anzeigen()
Dim i As Integer
List1.Clear
For i = 0 To 511
List1.AddItem (Hex(buffer(i)))
Next i
Text1.Text = akt_sektor
End Sub
Private Sub Form_Load()
akt_sektor = -1
End Sub Erklärungen:
Command1 stellt das Handle zum Laufwerk her.
Command2 löscht das Handle und beendet das Programm
Command3: bei jedem klick wird der nächste Sektor ausgelesen und angezeigt
Command4: bei jedem klick werden 10 Sektoren übersprungen
Command5 sucht die Sektoren ab, bis er am ersten Byte die Zahl 60 findet (erstes Zeichen meines Schlüsselwortes)
Das ganze funktioniert FAST. Er findet die Daten zwar und zeigt sie auch an, aber im falschen Sektor! In meinem Fall liegt das gesuchte zeichen in Sektor 771 (das sagt der µC un SD_RAW.exe). Jedoch findet mein Programm das im Sektor 520. Nach nochmaligem Formatieren und Datei neu anlegen findet der µC die Stelle in Sektor 8019 und mein Programm bei 7768. Also beide male 251 weniger. Wo könnten diese 251 herkommen???
Hat jemand eine Idee wie man das zum schreiben erweitern könnte. Dazu habe ich leider noch nichts gefunden
Ich hoffe ihr könnte mir helfen!!
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 14.06.09 00:20 |
| Ich bins nochmal....
Ich hab jetzt gemerkt, dass Sektor 0 meines Programms Sektor 251 des anderen Programms entspricht. Also liest er bei dem ersten Aufruf der Funktion "ReadSectorFromDrive" gleich Sektor 251 ein anstatt 0. Woran könnte das liegen?
Hier mal mein Code aus dem Modul:
'Windows-Variablen / Konstanten:
Private Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000003
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_DEVICE_FILE_SYSTEM = &H9
Private Const METHOD_BUFFERED = 0
Private Const FILE_READ_DATA = (&H1)
Private Const FILE_WRITE_DATA = (&H2)
'API-Deklarationen
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes _
As Long, _
ByVal hTemplateFile As Long) As Long
Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, _
lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
'Im Modul benötigt:
Dim lngFileHandle As Long 'Handle für Drive
Dim CreateFileError 'Fehler beim Erzeugen des Handles
Dim ReadFileError 'Fehler beim Lesen vom Laufwerk
Sub GetDriveHandle(Drivename$)
'muss zuerst aufgerufen werden um Zugang zum Drive zu bekommen
'Fehlervariablen zurücksetzen
CreateFileError = 0
ReadFileError = 0
FileName$ = "\\.\" & Drivename$
lngFileHandle = CreateFile(FileName$, GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ, ByVal 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0)
'Bei Fehlschlag aussteigen2
If (lngFileHandle = INVALID_HANDLE_VALUE) Then
MsgBox "Invalid handle!"
CreateFileError = 1
Exit Sub
Else
'MsgBox "File handle:" & Str$(lngFileHandle)
End If
End Sub
Sub ReadSectorFromDrive(buffer() As Byte)
'liest 512 Bytes (1 Sektor) in buffer() ein
If CreateFileError Then
ReadFileError = 1
Exit Sub
End If
retReadFile& = ReadFile(lngFileHandle, buffer(0), 512, BytesRead&, 0&)
If retReadFile& = 0 Then
MsgBox "Readfile returns " & Str$(retReadFile&) & vbCrLf & "Read Error!"
ReadFileError = 1
Exit Sub
End If
End Sub
Sub CloseDriveHandle()
CloseHandle lngFileHandle
End Sub Das Schreiben der Sektoren wäre mir eigentlich viel wichtiger. Das lesen bräuchte ich höchstens um das geschriebene zu überprüfen (falls Sektoren defekt sind). | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 14.06.09 22:38 |
| und nochmal ich
Ich hab jetzt im Modul folgendes Hinzugefügt:
Declare Function WriteFile Lib "kernel32.dll" (ByVal hFile As Long, ByRef _
lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, ByRef _
lpNumberOfBytesWritten As Long, ByRef lpOverlapped As Long) As Long
Sub WriteSectorToDrive(buffer() As Byte)
'schreibt 512 Bytes (1 Sektor) von buffer()
If CreateFileError Then
ReadFileError = 1
Exit Sub
End If
retwriteFile& = WriteFile(lngFileHandle, buffer(0), 512, BytesWrite&, 0&)
If retReadFile& = 0 Then
MsgBox "Readfile returns " & Str$(retReadFile&) & vbCrLf & "Read Error!"
ReadFileError = 1
Exit Sub
End If
End Sub Außerdem habe ich in der Funktion "GetDriveHandle" eine Zeile so geändert um auch Schreibzugriff zu haben:
lngFileHandle = CreateFile(FileName$, GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0, OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL, ByVal 0) Außerdem habe ich in der Form noch folgenden Code hinzugefügt um die neue Funktion zu testen:
Private Sub Command6_Click()
Dim i As Integer
For i = 0 To 254
puffer(i) = i
Next i
WriteSectorToDrive puffer()
End Sub Leider funktioniert es wieder nur FAST. Wenn ich Command6 drücke schmiert das Programm ab mit der Fehlermeldung: "Visual Basic hat ein Problem festgestellt und muss beendet werden." Wenn ich anschließend mit dem anderen Programm anschließend Sektor 251 anschaue steht dort alles richtig drin. Also hat die Funktion soweit eigentlich funktioniert.
Mit diesen Funktionen kann ich ja aber auch immer nur von vorne her die Sektoren der Reihe nach beschreiben. Gibt es auch eine Möglichkeit, dass ich z.B. sage "Schreibe buffer() in Sektor 1254"? Um die anderen Daten nicht zu löschen müsste ich ja sonst jeden Sektor einlesen und das eingelesene wieder schreiben um "voranzukommen".
Sektor 251 scheint übrigens etwas wichtiges zu sein, denn windows sagt jetzt wenn ich die SD-Karte öffnen will, dass diese nicht formatiert ist.
Gruß
marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 15.06.09 17:35 |
| Nachdem ich jetzt hier etwas gefunden habe wollte ich es mal mit der API SetFilePointer versuchen und hab folgendes hinzugefügt:
im Modul:
Private Const FILE_BEGIN = 0
Declare Function SetFilePointer Lib "kernel32.dll" (ByVal hFile As Long, ByVal _
lDistanceToMove As Long, ByRef lpDistanceToMoveHigh As Long, ByVal _
dwMoveMethod As Long) As Long
Sub SelectSector(adress As Long)
'Wählt den zu beschreibenden oder zu lesenden Sektor aus
adress = adress * 512
If CreateFileError Then
ReadFileError = 1
Exit Sub
End If
retReadFile& = SetFilePointer(lngFileHandle, adress, FILE_BEGIN, 0&)
If retReadFile& = 0 Then
MsgBox "Readfile returns " & Str$(retReadFile&) & vbCrLf & "Read Error!"
ReadFileError = 1
Exit Sub
End If
End Sub und in der Form:
Private Sub Command7_Click()
Dim adress As Long
adress = Text2.Text
SelectSector adress
End Sub Das funktioniert leider überhaupt nicht Er schreibt immernoch in Sektor 251 und die Fehlermeldung kommt auch noch. Kann das daran liegen, dass die geöffnete Datei keine größe hat (weil sie neu erstellt wird) und man den Zeiger nur innerhalb der Datei verschieben kann? Wenn ja, gibt es auch eine API, mit der man die Datei vergrößern kann ohne den Inhalt zu verändern, oder eine API mit der man direkt den Startpunkt der Datei festlegen kann?
Außerdem habe ich mir mal die API OpenFile angeschaut, werde dabei aber daraus nicht schlau:
Zitat: | | lpReOpenBuff Erwartet eine "OFSTRUCT"-Struktur die mit Informationen zu der geöffneten Datei gefüllt wird. | |
Kann das jemand Anfängergerecht erklären?
Vielen Dank im Voraus!
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 16.06.09 08:22 |
| Hi
Kann man vielleicht direkt beim Aufruf von CreateFile den Speicherort der Datei festlegen? Also bei
FileName$ = "\\.\" & Drivename$" irgendwie noch den Sektor mit angeben?
Geht das irgendwie?
Oder geht das ganz anders?
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 16.06.09 20:40 |
| irgendwie wird das eine One-Man-Show.
Könnte ich es evtl. so machen, dass ich eine Datei anlege, die die komplette Größe der SD-Karte einnimmt (bei mir 2Gb). Dann könnte ich darin rumschreiben wie ich möchte. Würde das irgendwie gehn? Wenn ja, wie? Hat da jemand einen Tip? | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Arne Elster | Datum: 16.06.09 22:00 |
| Wenn das Setzen der neuen Position geglückt ist,
gibt dir SetFilePointer die von dir gewünschte Position zurück,
in dem Fall den Wert deiner Variablen "adress".
Wenn SetFilePointer fehlschlägt, ist der Rückgabewert -1.
Zu dem Sektor 251 könnte ich mir vorstellen,
dass Windows dich nur auf die Partition auf der SD Karte zugreifen lässt,
weil du die diese öffnest mit \\.\X:
Und die fängt halt bei 251 an. Mal als Theorie.
OpenFile brauchst du dir nicht anzugucken,
die wurde von Microsoft als obsolet erklärt,
wird nicht mehr verwendet. CreateFile ist die neue.
Zurück zur 251:
Folgendes ist eine nicht geprüfte mögliche Lösung.
Ich hab das direkt hier ins Antwortfeld reingeschrieben und nicht getestet.
Zunächst mal brauchst du folgenden Code, kopier den in ein Modul:
Private Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Long, _
ByVal dwIoControlCode As Long, _
ByRef lpInBuffer As Any, _
ByVal nInBufferSize As Long, _
ByRef lpOutBuffer As Any, _
ByVal nOutBufferSize As Long, _
ByRef lpBytesReturned As Long, _
ByRef lpOverlapped As Any) As Long
Private Type STORAGE_DEVICE_NUMBER
DeviceType As Long
DeviceNumber As Long
PartitionNumber As Long
End Type
Private Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Long = &H2D1080
Public Function GetPhysDriveNumber(ByVal hDrv As Long) As Long
Dim udtSDN As STORAGE_DEVICE_NUMBER
Dim lngRet As Long
If DeviceIoControl(hDrv, IOCTL_STORAGE_GET_DEVICE_NUMBER, ByVal _
0&, 0&, udtSDN, Len(udtSDN), lngRet, ByVal 0&) Then
GetPhysDriveNumber = udtSDN.DeviceNumber
Else
GetPhysDriveNumber = -1
End If
End Function CreateFile gibt dir ja ein Handle auf die Partition zurück,
damit du mit Read/WriteFile darin rumwursteln kannst.
Windows erlaubt dir aber auch, auf ein Speichermedium komplett zuzugreifen,
wenn du als Dateiname für CreateFile "\\.\PHYSICALDRIVEX" angibst,
wobei X eine Nummer von 0 bis 9 ist.
Das Problem ist, wie man rausfindet, zu welcher Nummer Partition X gehört.
Zunächst öffnest du also X mit CreateFile über "\\.\X:".
Das Handle, das dir CreateFile zurückgibt, benutzt du, um GetPhysDriveNumber aufzurufen.
Wenn du das hast, schließt du das Handle mit CloseHandle,
um jetzt CreateFile mit "\\.\PHYSICALDRIVE" plus der von GetPhyDriveNumber zurückgegebenen Zahl ein weiteres mal anzufeuern.
Und mit dem Handle müsstest du dich nun frei auf der SD Karte bewegen können.
Hoffentlich klappts. | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Arne Elster | Datum: 16.06.09 22:30 |
| Aber versuch erstmal nur ReadFile mit dem neuen Handle zu benutzen,
um rauszufinden ob du auch wirklich von der SD Karte liest!
Ein schlechtes Zeichen wäre, wenn GetPhysDriveNumber 0 zurückgibt. | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 17.06.09 17:54 |
| Hi
Ich hab es jetzt mal so gemacht wie du gemeint hast. Ich bekomm aber immer -1 von der Funktion GetPhysDriveNumber zurück. Ich hab den obenstehenden Code in ein Modul gemacht und dann noch einen Button mit folgendem Code:
Private Sub Command8_Click()
GetDriveHandle "e:"
nummer$ = CStr(GetPhysDriveNumber(lngFileHandle))
CloseDriveHandle
GetDriveHandle2 nummer$
End Sub Außerdem noch diesen Code im alten Modul ergänzt:
Sub GetDriveHandle2(Drivenummer$)
CreateFileError = 0
ReadFileError = 0
FileName$ = "\\.\PHYSICALDRIVE" & Drivenummer$
lngFileHandle = CreateFile(FileName$, GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0, OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL, ByVal 0)
'Bei Fehlschlag aussteigen2
If (lngFileHandle = INVALID_HANDLE_VALUE) Then
MsgBox "Invalid handle!"
CreateFileError = 1
Exit Sub
Else
MsgBox "File handle:" & Str$(lngFileHandle)
End If
End Sub Ich habe auch hier ein Projekt gefunden, das auch auf Sektoren zugreifen kann. Damit funktioniert es auch. Zumindest das anzeigen. Auch weiß ich jetzt wieso gerade Sektor 251 bei mir als 0 angezeigt wird und warum er am Anfang immer bei Sektor 771 angefangen hat zu schreiben. Das Programm zeigt mir nämlich unter anderem folgende DriveInfos an:
Zitat: | |
Hidden Sectors: 251
Number of FAT copies: 2 (Was heißt das??)
Sectors per FAT: 242
FAT copy(1) starts at 4 (Absolut gesehen dann also 255)
FAT copy(2) starts at 246 (entspricht dann 497)
Rootdirectory starts at 488 (entspricht 739)
RootDirectoryLength: 31 (Endet also bei 770)
| |
also kann ich bei 771 anfangen Daten zu schreiben. Er springt auch zu Sektor 520 (also 771 absolut), wenn ich den Datenbereich anzeigen lasse. Damit wäre also das schoneinmal geklärt. Wenn ich den MBR anzeigen lasse zeigt er mir also Sektor 251 an. Könnte es daran liegen, dass ich den MBR überschreibe, dass VB immer einen Fehler produziert wenn ich meine Funktion WriteSectorToDrive aufrufe?
ich habe versucht das Programm zu verstehen, aber das ist mir viel zu komplex. ich kapier das nicht. Ich möchte nur einen String an eine Definierte Position auf der SD-Karte schreiben (und evtl. das geschriebene überprüfen) Eigentlich würde es mir sogar genügen, wenn die Schreibfunktion wenigstens ab Sektor 251 funktionieren würde. Das wäre ja dann eine definierte Position. Funktioniert ja aber leider nicht | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 18.06.09 08:16 |
| Hi,
Ich hab jetzt mal versucht das Programm zu verstehen.
Diese zwei Funktionen sind wohl die wichtigsten für meinen Fall:
Private Function DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As _
Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
Dim hDevice As Long
Dim abBuff() As Byte
Dim abResult() As Byte
Dim nSectors As Long
Dim nRead As Long
nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
hDevice = CreateFile("\\.\" & UCase(Left(sDrive, 1)) & ":", GENERIC_READ Or _
GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, _
0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
ReDim abResult(cBytes - 1)
ReDim abBuff(nSectors * BytesPerSector - 1)
Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
CloseHandle hDevice
CopyMemory abResult(0), abBuff(iOffset), cBytes
DirectReadDriveNT = abResult
End Function
Private Function DirectWriteDriveNT(ByVal sDrive As String, ByVal iStartSec As _
Long, ByVal iOffset As Long, ByVal sWrite As String) As Boolean
Dim hDevice As Long
Dim abBuff() As Byte
Dim ab() As Byte
Dim nRead As Long
Dim nSectors As Long
nSectors = Int((iOffset + Len(sWrite) - 1) / BytesPerSector) + 1
hDevice = CreateFile("\\.\" & UCase(Left(sDrive, 1)) & ":", GENERIC_READ Or _
GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, _
0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
abBuff = DirectReadDriveNT(sDrive, iStartSec, 0, nSectors * BytesPerSector)
ab = StrConv(sWrite, vbFromUnicode)
CopyMemory abBuff(iOffset), ab(0), Len(sWrite)
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
Call LockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec _
* BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * _
BytesPerSector))
DirectWriteDriveNT = WriteFile(hDevice, abBuff(0), UBound(abBuff) + 1, _
nRead, 0&)
Call FlushFileBuffers(hDevice)
Call UnlockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord( _
iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord( _
nSectors * BytesPerSector))
CloseHandle hDevice
End Function Eigentlich sogar nur die Untere ("DirectWriteDriveNT")
Wenn ich es richtig verstanden habe macht die folgendees:
- Ein Handle erzeugen mit in meinem Fall "\\.\e:" (ist genau so wie ich es hatte)
- in abBuff den Sektor (oder die Sektoren) der geschrieben werden soll einlesen (mittels der Funktion darüber)
- Was das hier "ab = StrConv(sWrite, vbFromUnicode)" macht hab ich nicht kapiert, aber glaube nicht dass das so wichtig ist
- Dann wird der zu schreibende String in das vorher ausgelesene an der richtigen Prosition eingefügt.
- Der Filepointer wird auf die Stelle gesetzt an der geschrieben werden soll (hab ich genauso gemacht)
- LockFile wird aufgerufen (hierzu finde ich keine richtige Beschreibung was die API macht. Auf der Seite die ich oben angegeben habe wird die API zwar erwähnt, aber es fehlt jede Beschreibung)
- WriteFile wird ausgeführt (Wie ich es auch gemacht habe)
- FlushFileBuffers(hDevice): damit wird wahrscheinlich der Zwischenpuffer gelehrt (was bringt das??)
- Dann wird die Datei wieder "ungelockt" (auch hierzu hab ich keine Infos gefunden )
- Am Ende wird das Handle wieder geschossen.
Zusammenfassend kann man sagen:
bis auf diese Zeilen:
Call LockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec _
* BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * _
BytesPerSector))
[....]
Call FlushFileBuffers(hDevice)
Call UnlockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord( _
iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord( _
nSectors * BytesPerSector)) ist alles genau so wie ich es hatte. Was bewirken diese 3 Zeilen? Ich hatte gestern abend keine Zeit mehr zu probieren was passiert wenn ich diese Zeilen einfüge und jetzt bin ich bei der Arbeit. Falls es dann funktioniert wüsste ich aber auch gerne wieso.
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 18.06.09 21:20 |
| Hi
Ich habe jetzt diese 2 Funktionen in ein Neues Projekt kopiert (In ein Modul) und eine Miniform mit folgemdem Code erstellt:
Private Sub Command1_Click()
Dim Res As Integer
Res = DirectWriteDriveNT(Drive1.Drive, Text1.Text, Text2.Text, Text3.Text)
MsgBox Res
End Sub Text1 enthält den Zielsektor
Text2 Enthält den Offset (wie viele Zeichen am Beginn des Sektors frei bleiben sollen)
Text3 enthält den zu schreibenden Text
UND ES FUNKTIONIERT!!!
Nur hat es einen kleinen Schönheitsfehler: Ich lasse ja den Rückgabewert anzeigen, und der ist "-1". Heißt ja eigentlich, dass es nicht funktioniert hat. Wenn ich es aber mit dem anderen Programm überprüfe hat es doch funktioniert.... Der Text steht genau da wo er stehen soll...
Es funktioniert, aber ich kapiers nicht. Besser als andersrum | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Agrypnie | Datum: 21.06.09 08:08 |
| Hallo Majuz !
Dein Projekt ähnelt meinem fertiggestellten.
Bei mir müssen Bilddaten in Byteform auf der SD-Karte gespeichert werden um sie später mit dem Microcontroller auszulesen und die Bilder auf einem Display darzustellen.
Da mein Zeug nun fertig ist, kannst du dir den Quellcode hier runterladen:
http://funkamateur.de/download/down3.htm
dort lädst du „Grafischer Tageskalender mit DCF77-Funkuhr“ runter
in dem ZIP ist meine EXE und das VB6 Projekt enthalten. Vielleicht hilft es dir etwas.
Wichtig wäre in meinem Projekt für dich der Sub „Write Pic“
Irgendwie sieht das bei mir etwas weniger aus als bei dir.... obwohl bei den ganzen Posts hier blicke ich nun auch nicht soo durch
Gruß: Thomas | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: Majuz | Datum: 21.06.09 10:47 |
| hi
Danke, aber ich habs jetzt auch hinbekommen Bist ein paar Tage zu spät dran
Ich habs jetzt mit diesen beiden Funktionen:
Private Function DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As _
Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
Dim hDevice As Long
Dim abBuff() As Byte
Dim abResult() As Byte
Dim nSectors As Long
Dim nRead As Long
nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
hDevice = CreateFile("\\.\" & UCase(Left(sDrive, 1)) & ":", GENERIC_READ Or _
GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, _
0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
ReDim abResult(cBytes - 1)
ReDim abBuff(nSectors * BytesPerSector - 1)
Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
CloseHandle hDevice
CopyMemory abResult(0), abBuff(iOffset), cBytes
DirectReadDriveNT = abResult
End Function
Private Function DirectWriteDriveNT(ByVal sDrive As String, ByVal iStartSec As _
Long, ByVal iOffset As Long, ByVal sWrite As String) As Boolean
Dim hDevice As Long
Dim abBuff() As Byte
Dim ab() As Byte
Dim nRead As Long
Dim nSectors As Long
nSectors = Int((iOffset + Len(sWrite) - 1) / BytesPerSector) + 1
hDevice = CreateFile("\\.\" & UCase(Left(sDrive, 1)) & ":", GENERIC_READ Or _
GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, _
0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
abBuff = DirectReadDriveNT(sDrive, iStartSec, 0, nSectors * BytesPerSector)
ab = StrConv(sWrite, vbFromUnicode)
CopyMemory abBuff(iOffset), ab(0), Len(sWrite)
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
Call LockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec _
* BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * _
BytesPerSector))
DirectWriteDriveNT = WriteFile(hDevice, abBuff(0), UBound(abBuff) + 1, _
nRead, 0&)
Call FlushFileBuffers(hDevice)
Call UnlockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord( _
iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord( _
nSectors * BytesPerSector))
CloseHandle hDevice
End Function Diese sind sehr allgemein gefasst. Es ist z.B. ein Offset eingebaut und es funktioniert auch für alle Datenlängen. Außerdem wird zuerst gelesen was in diesen Sektoren Liegt die beschrieben werden sollen und dann nur die Teile ersetzt in denen Was geschrieben werden soll, der Rest bleibt so wie es war.
So wie du es hast hatte ich es am Anfang auch, aber es hat nicht funktioniert mit den Filepointer zu verändern. Mir fällt aber gerade auf, dass das CreateFile anders hast als ich. Ich hatte da:
CreateFile(FileName$, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or _
FILE_SHARE_WRITE, ByVal 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0) evtl. liegt es daran, dass ich den Filepointer nicht verändern konnte. Wäre ein Versuch wert. Komm allerdings frühestens heut abend dazu.
Gruß
Marius | |
Re: Sektoren einer SD-Karte beschreiben (ohne Dateisystem) | | | Autor: NormBot | Datum: 05.03.13 22:48 |
| das Thema iss zwar nun schon in die Jahre gekommen, leider ist es schwer etwas zu dem Thema in Google in Deutscher Sprache zu finden.
Die Schreib Funktion für SD Karten hab ich verstanden und Funzt auch Problemfrei, leider klappt es bei mir mit der Lesefunktion nicht da kommt kein Wert zurück
was hat es den mit diesem Offset aufsich ???
wäre um Antworten dankbar !!
vielleicht auch ein Anwendungsbeispiel wie der Lesecode anzuwenden ist
Der hier geht leider nicht
Text1.text = DirectReadDriveNT("\\?\P:", 1, 0, 1)
ich dachte das er in das Feld Text1 den Wert von Sektor 1 an Byte Stelle 1 übernimmt ??!!
DENKFEHLER ??
Gruß Normen | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
vb@rchiv CD Vol.6 vb@rchiv Vol.6
Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
Online-Update-Funktion Entwickler-Vollversionen u.v.m.Jetzt zugreifen Tipp des Monats Neu! sevCoolbar 3.0
Professionelle Toolbars im modernen Design!
Mit sevCoolbar erstellen Sie in wenigen Minuten ansprechende und moderne Toolbars und passen diese optimal an das Layout Ihrer Anwendung an (inkl. große Symbolbibliothek) - für VB und MS-Access Weitere Infos
|