線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3231
推到 Plurk!
推到 Facebook!

SDHC卡的讀寫問題

答題得分者是:wjhsu
poaivy
中階會員


發表:40
回覆:78
積分:53
註冊:2004-08-09

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-09-25 15:44:36 IP:140.117.xxx.xxx 訂閱
請問各位
使用下列方法對SD可以做讀的動作
hDevice = CreateFile("\\\\.\\K:", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

SetFilePointer( hDevice , addr*512, NULL, FILE_BEGIN); 移動到你所想要找的資料位址

ReadFile(hDevice, Buffer, 512, &dwBlockRead, 0); // ㄧ次讀一個BLOCK(512Byte)

WriteFile( hDevice , buffer, 512, &dwBytesRead, NULL); // ㄧ次寫一個BLOCK(512Byte)

CloseHandle(hDevice);
前提是.......... SD卡的容量 8G以下的 都適用 使用上都OK ^.^

直到最近買了片16G的.............
SetFilePointer( hDevice , addr*512, NULL, FILE_BEGIN); 移動到你所想像不到的資料位址
ReadFile(hDevice, Buffer, 512, &dwBlockRead, 0); // ㄧ次讀一個BLOCK(512Byte)???
這兩個函式已經失效
SD SPEC看了又看
會出問題的話早該在4跟8G的卡就會有問題了(都很正常).....
用了16G的卡後就不能對SECTOR的內容作讀寫動作了.......
想請問各位有使用過意見或者有別的方法可以處理嗎??
因為.......... WinHex....他 讀的到啊 >.<
編輯記錄
poaivy 重新編輯於 2008-09-25 15:45:06, 註解 無‧
wjhsu
初階會員


發表:9
回覆:32
積分:48
註冊:2004-06-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-09-25 23:49:08 IP:123.195.xxx.xxx 訂閱
請試試SetFilePointerEx()..它是用64-bit的LARGE_INTEGER,
poaivy
中階會員


發表:40
回覆:78
積分:53
註冊:2004-08-09

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-09-26 10:09:39 IP:140.117.xxx.xxx 訂閱
多謝  wjhsu  的回覆 試過使用
unsigned __int64 offset = 0;
SetFilePointerEx(hDevice, *(LARGE_INTEGER *)&offset ,0 ,FILE_BEGIN);
回傳為1
可是依舊讀不到資料 @@
他仍然不知指向何處> .<
poaivy
中階會員


發表:40
回覆:78
積分:53
註冊:2004-08-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-09-29 12:47:35 IP:140.117.xxx.xxx 訂閱
抱歉~ 我發現我的問題所在了
原因 是該卡我沒有將他的MBR區清掉
導致setfilepoint 無法指到我所認為的第一個SECTOR

但是我比較好奇的是......為何winhex這套軟體 他可以直接修改該區的內容

那他到底是使用哪種控制方式 ??
wjhsu
初階會員


發表:9
回覆:32
積分:48
註冊:2004-06-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-09-30 02:39:53 IP:123.195.xxx.xxx 訂閱
你是想讀寫MBR的資料嗎? 如果是的話, 應該要用CreateFile()開啟"實體磁碟機", 如果用CreateFile("\\\\.\\K:"...)的方式, 開啟的是邏輯磁碟機,
兩種方式用SetFilePointerEx()指向磁區0 所代表的意義不同, 前者表示MBR, 後者則是Boot Sector,
(不過, 對SD卡而言, 有時會沒有MBR, 所以用實體磁碟機開啟後, Sector 0, 也是Boot Sector)
底下是我的方式, 請參考..., 主要是用GetPhysicalDiskHandle()取得實體磁碟機的代號後, 其餘SetFilePointerEx & ReadFile用法就相同了...

p.s. MBR & BootSector 可以參考 http://home.educities.edu.tw/wanker742126/index.html ...

[code cpp]
//---------------------------------------------------------------------------
/**
找出邏輯磁碟機對應的實體磁碟機代號
傳入值:
DriveLetter: 邏輯磁碟機的符號, 如; C, D, E...
DiskNum : 傳回的實體磁碟機代號, 如果要進一步用CreateFile()開啟實體磁碟
機, 可用"\\\\.\\PHYSICALDRIVEn", 做為第一個參數, 其中n就是
DiskNum
傳回值:
成功傳回true, 實體磁碟機的代號放在DiskNum, 否則傳回false

Note:
1. 根據MSDN的說明, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS傳回的
VOLUME_DISK_EXTENTS結構裏 , NumberOfDiskExtents表示此邏輯磁碟機"分佈"
的實體磁碟機數量, 一般來說, 此值應該為1, 表示傳入的邏輯磁碟機的磁區均
位於同一顆實體磁碟中, 例如: 一顆硬碟分割成C,D,E三槽, 則用C,D,E傳入此
函式時, 得到的 DiskExtent.Extents[0].DiskNumber應該相同

2. 如果邏輯磁碟機的磁區分佈於不同的實體磁碟機, 則NumberOfDiskExtents的
值不為1, 而DeviceIoControl()失敗後, 呼叫 GetLastError()應該會傳回
ERROR_MORE_DATA, 此時要修正傳入 DeviceIoControl 的Output Buffer大小,

3. 此函式只處理第一種狀況, 第二種狀況就當做fail
*/
bool GetPhysicalDiskNum(char DriveLetter, DWORD &DiskNum)
{
VOLUME_DISK_EXTENTS DiskExtent;

HANDLE hDrive;
DWORD BytesRet;
BOOL Success;
char DriveStr[]="\\\\.\\X:";

DriveStr[4] = DriveLetter;

hDrive = ::CreateFile( DriveStr,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );

Success = FALSE;
DiskNum = -1;

if (hDrive != INVALID_HANDLE_VALUE)
{
Success = ::DeviceIoControl( hDrive, // handle to device
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
&DiskExtent, // output buffer
sizeof(DiskExtent), // size of output buffer
&BytesRet, // number of bytes returned
NULL); // OVERLAPPED structure
if (Success)
DiskNum = DiskExtent.Extents[0].DiskNumber;

::CloseHandle(hDrive);
}
return (bool)Success;
}
/**
取得邏輯磁碟機對應的實體磁碟機的Handle
*/
HANDLE GetPhysicalDiskHandle(char DriveLetter)
{
HANDLE hPhysical;
DWORD DiskNum;

AnsiString PhysStr = "\\\\.\\PHYSICALDRIVE";

if (!GetPhysicalDiskNum(DriveLetter, DiskNum))
hPhysical = INVALID_HANDLE_VALUE;
else
{
PhysStr = IntToStr(DiskNum);

hPhysical = CreateFile( PhysStr.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH,
NULL);
}
return hPhysical;
}
//---------------------------------------------------------------------------
#define SECTOR_SIZE 512
void __fastcall TForm1::Button2Click(TObject *Sender)
{
LARGE_INTEGER NewPtr;
LARGE_INTEGER Addr;
AnsiString Row;
HANDLE DiskHandle;
unsigned char Buf[SECTOR_SIZE];

DWORD Temp;
DWORD SectorId = 0; //Sector的LBA編號 0 = MBR

Addr.QuadPart = SectorId * SECTOR_SIZE;

DiskHandle = GetPhysicalDiskHandle('I');

if (DiskHandle != INVALID_HANDLE_VALUE)
{
if (SetFilePointerEx(DiskHandle, Addr, &NewPtr,FILE_BEGIN))
{
if (ReadFile(DiskHandle, Buf, SECTOR_SIZE, &Temp, NULL))
{
Row = "";
for (int i=0; i {
Row = (IntToHex(Buf[i],2) " ");
if (((i 1) % 16)==0)
{
Memo->Lines->Add(Row);
Row="";
}
}
}
}

CloseHandle(DiskHandle);
}
}
[/code]
系統時間:2017-10-19 11:29:26
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!