/***************************************************************************** ** Copyright (C) WCH 2001-2025 ** ** Web: http://wch.cn ** ****************************************************************************** Abstract: 基于CH347/CH339W SPI接口函数操作FLASH应用示例,FLASH 型号识别、块读、块写、块擦除、FLASH内容读至文件、文件 写入FLASH、速度测试等操作函数。SPI传输速度可达2M字节/S Environment: user mode only,VC6.0 and later Notes: Copyright (c) 2025 Nanjing Qinheng Microelectronics Co., Ltd. Revision History: 4/3/2022: TECH30 --*/ #include "Main.h" #define DevID_Mode1_2 "USB\\VID_1A86&PID_55" extern HINSTANCE AfxMainIns; //进程实例 extern ULONG Flash_Sector_Count; // FLASH芯片扇区数 extern USHORT Flash_Sector_Size; // FLASH芯片扇区大小 extern HWND AfxActiveHwnd; extern BOOL g_isChinese; //全局变量 HWND FlashEepromDbgHwnd; //窗体句柄 BOOL FlashDevIsOpened; //设备是否打开 BOOL IsSpiInit; //SPI使用前需对SPI进行初化 ULONG DevIndex; mDeviceInforS FlashDevInfor[16] = {0}; //使能操作按钮,需先打开和配置,否则无法操作 VOID FlashDlg_EnableButtonEnable(); //FLASH型号识别 BOOL FlashIdentify() { double BT,UsedT; BOOL RetVal; if(!FlashDevIsOpened) { if (g_isChinese) DbgPrint("请先打开设备"); else DbgPrint("Please open the device first"); return FALSE; } if (g_isChinese) DbgPrint(">>FLASH芯片型号检测..."); else DbgPrint(">>Flash chip type detection..."); BT = GetCurrentTimerVal(); RetVal = FLASH_IC_Check(); UsedT = GetCurrentTimerVal()-BT; if (g_isChinese) DbgPrint(">>FLASH芯片型号检测...%s,用时:%.3fS",RetVal?"成功":"失败",UsedT); else DbgPrint(">>Flash chip type detection...% s.Time:% 3fS",RetVal?"Success":"failure",UsedT); return RetVal; } //初始化SPI控制器和片选设置 BOOL Flash_InitSpi() { BOOL RetVal = FALSE; mSpiCfgS SpiCfg = {0}; CH347SPI_GetCfg(DevIndex,&SpiCfg); //获取硬件SPI当前设置 SpiCfg.iMode = (UCHAR)SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_GETCURSEL,0,0); SpiCfg.iClock = (UCHAR)SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_GETCURSEL,0,0); SpiCfg.iByteOrder = 1; //MSB SpiCfg.iSpiOutDefaultData = 0xFF; RetVal = CH347SPI_Init(DevIndex,&SpiCfg); //设置SPI CH347SPI_SetChipSelect(DevIndex,0x0001,0,0,0,0); //使能并启用CS1作为片选信号 FlashIdentify(); //识别评估板上的W24Q64芯片型号 DbgPrint("Flash_Init %s",RetVal?"succ":"failure"); return RetVal; } //FLASH字节读 BOOL FlashBlockRead() { double BT,UseT; ULONG DataLen,FlashAddr=0,i; UCHAR DBuf[8192] = {0}; CHAR FmtStr[512] = "",FmtStr1[8*1024*3+16]=""; if(!FlashDevIsOpened) { if (g_isChinese) DbgPrint("请先打开设备"); else DbgPrint("Please open the device first"); return FALSE; } //获取FLASH读的起始地址 GetDlgItemText(FlashEepromDbgHwnd,IDC_FlashStartAddr,FmtStr,32); FlashAddr = mStrToHEX(FmtStr); //获取FLASH读的字节数,十六进制 GetDlgItemText(FlashEepromDbgHwnd,IDC_FlashDataSize,FmtStr,32); DataLen = mStrToHEX(FmtStr); if(DataLen<1) { if (g_isChinese) DbgPrint("请输入Flash数据操作长度"); else DbgPrint("Please enter the flash data operation length"); return FALSE; } else if(DataLen>(8*1024*3)) //显示限制 { if (g_isChinese) DbgPrint("请输入小于0x%X的Flash数据操作长度",8*1024); else DbgPrint("Please enter a flash data operation length less than 0x%x",8*1024); return FALSE; } BT = GetCurrentTimerVal(); DataLen = FLASH_RD_Block(FlashAddr,DBuf,DataLen); UseT = GetCurrentTimerVal()-BT; if(DataLen<1) { if (g_isChinese) DbgPrint(">>Flash读:从[%X]地址开始读入%d字节...失败.",FlashAddr,DataLen); else DbgPrint(">>FLASH read: read%d bytes from [%x] address fail.",FlashAddr,DataLen); } else { if (g_isChinese) DbgPrint(">>Flash读:从[%X]地址开始读入%d字节...成功.用时%.3fS",FlashAddr,DataLen,UseT/1000); else DbgPrint(">>FLASH read: read%d bytes from [%x] address success. Time%.3fS",FlashAddr,DataLen,UseT/1000); {//显示FLASH数据,16进制显示 for(i=0;i>Flash写:从[%X]地址开始写入%d字节...失败",FlashAddr,DataLen); else DbgPrint(">>Flash write: write%d bytes from [%x] address fail",FlashAddr,DataLen); } else { if (g_isChinese) DbgPrint(">>Flash写:从[%X]地址开始写入%d字节...成功.用时%.3fS",FlashAddr,DataLen,UseT/1000); else DbgPrint(">>Flash write: write%d bytes from [%x] address success. Time% 3fS",FlashAddr,DataLen,UseT/1000); } return TRUE; } //FLASH块擦除 BOOL FlashBlockErase() { ULONG DataLen,FlashAddr=0; CHAR FmtStr[128] = ""; double BT,UseT; BOOL RetVal; //获取擦除FLASH的起始地址,十六进制 GetDlgItemText(FlashEepromDbgHwnd,IDC_FlashStartAddr,FmtStr,32); FlashAddr = mStrToHEX(FmtStr); //获取擦除FLASH的字节数,十六进制 GetDlgItemText(FlashEepromDbgHwnd,IDC_FlashDataSize,FmtStr,32); DataLen = mStrToHEX(FmtStr); BT = GetCurrentTimerVal(); RetVal = FLASH_Erase_Sector(FlashAddr); UseT = GetCurrentTimerVal()-BT; if (g_isChinese) { if( !RetVal ) DbgPrint(">>FLASH擦除:[%X]...失败",FlashAddr); else DbgPrint(">>FLASH擦除:[%X]...成功,用时%.3fS",FlashAddr,UseT/1000); } else { if( !RetVal ) DbgPrint(">>Flash erase: [%x] fail",FlashAddr); else DbgPrint(">>Flash erase: [%x] Success, time%.3fS",FlashAddr,UseT/1000); } return TRUE; } //显示检验数据出错内容 VOID DumpDataBuf(ULONG Addr,PUCHAR Buf1,PUCHAR SampBuf2,ULONG DataLen1,ULONG ErrLoca) { CHAR FmtStr1[8192*3] = "",FmtStr2[8192*3] = ""; ULONG i; memset(FmtStr1,0,sizeof(FmtStr1)); memset(FmtStr2,0,sizeof(FmtStr2)); //16进制显示 for(i=0;i0) ) { AddStrToEdit(FlashEepromDbgHwnd,IDC_InforShow,"Data[%08X]:%s\n",i-16+Addr,FmtStr1); AddStrToEdit(FlashEepromDbgHwnd,IDC_InforShow,"Samp[%08X]:%s\n",i-16+Addr,FmtStr2); memset(FmtStr1,0,16*4); memset(FmtStr2,0,16*4); if(ErrLoca==i) { sprintf(&FmtStr1[strlen(FmtStr1)],"[%02X] ",Buf1[i]); sprintf(&FmtStr2[strlen(FmtStr2)],"[%02X] ",SampBuf2[i]); } else { sprintf(&FmtStr1[strlen(FmtStr1)],"%02X ",Buf1[i]); sprintf(&FmtStr2[strlen(FmtStr2)],"%02X ",SampBuf2[i]); } } else { if(ErrLoca==i) { sprintf(&FmtStr1[strlen(FmtStr1)],"[%02X] ",Buf1[i]); sprintf(&FmtStr2[strlen(FmtStr2)],"[%02X] ",SampBuf2[i]); } else { sprintf(&FmtStr1[strlen(FmtStr1)],"%02X ",Buf1[i]); sprintf(&FmtStr2[strlen(FmtStr2)],"%02X ",SampBuf2[i]); } } } AddStrToEdit(FlashEepromDbgHwnd,IDC_InforShow,"Data[%08X]:%s\r\n",(i%16)?(i-i%16+Addr):(i-16+Addr),FmtStr1); AddStrToEdit(FlashEepromDbgHwnd,IDC_InforShow,"Samp[%08X]:%s\r\n",(i%16)?(i-i%16+Addr):(i-16+Addr),FmtStr2); } //FLASH测试,先擦除、写、读、检验 DWORD WINAPI FlashRWSpeedTest(LPVOID lpParameter) { ULONG FlashAddr = 0,TC,TestLen,i,k,BlockSize=0; double BT = 0; BOOL RetVal = FALSE; CHAR FileName[MAX_PATH]=""; HANDLE hFile=INVALID_HANDLE_VALUE; PUCHAR FileBuf=NULL,RBuf=NULL; ULONG FileSize,RLen,UnitSize,Addr,WLen; double UsedT = 0; ULONG Timeout,PrintLen,ErrLoca; UCHAR temp; OPENFILENAME mOpenFile={0}; EnableWindow(FlashEepromDbgHwnd,FALSE); // Fill in the OPENFILENAME structure to support a template and hook. mOpenFile.lStructSize = sizeof(OPENFILENAME); mOpenFile.hwndOwner = FlashEepromDbgHwnd; mOpenFile.hInstance = AfxMainIns; mOpenFile.lpstrFilter = "*.*\x0\x0"; mOpenFile.lpstrCustomFilter = NULL; mOpenFile.nMaxCustFilter = 0; mOpenFile.nFilterIndex = 0; mOpenFile.lpstrFile = FileName; mOpenFile.nMaxFile = sizeof(FileName); mOpenFile.lpstrFileTitle = NULL; mOpenFile.nMaxFileTitle = 0; mOpenFile.lpstrInitialDir = NULL; if (g_isChinese) mOpenFile.lpstrTitle = "选择待写入FLASH的数据文件"; else mOpenFile.lpstrTitle = "Select the data file to be written to FLASH"; mOpenFile.nFileOffset = 0; mOpenFile.nFileExtension = 0; mOpenFile.lpstrDefExt = NULL; mOpenFile.lCustData = 0; mOpenFile.lpfnHook = NULL; mOpenFile.lpTemplateName = NULL; mOpenFile.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_READONLY | OFN_FILEMUSTEXIST; if (GetOpenFileName(&mOpenFile)) DbgPrint("Write data to flash from:%s",FileName); else goto Exit; if(strlen(FileName) < 1) { if (g_isChinese) DbgPrint("测试文件无效,请重新选择"); else DbgPrint("The test file is invalid, please select again"); goto Exit; } hFile = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//打开文件 if(hFile == INVALID_HANDLE_VALUE) { ShowLastError("CreateFile"); goto Exit; } FileSize = GetFileSize(hFile,NULL); if(FileSize<128) { if (g_isChinese) DbgPrint("测试文件%d字节太小,请重新选择",FileSize); else DbgPrint("Test file%d bytes is too small, please re select",FileSize); goto Exit; } if( FileSize > (Flash_Sector_Size * Flash_Sector_Count) ) TestLen = Flash_Sector_Size * Flash_Sector_Count; else TestLen = FileSize; FileBuf = (PUCHAR)malloc(FileSize); if(FileBuf==NULL) { if (g_isChinese) DbgPrint("申请文件内存%dB失败",FileSize); else DbgPrint("failed to apply for file memory %dB", FileSize); goto Exit; } RBuf = (PUCHAR)malloc(FileSize+128); if(RBuf==NULL) { if (g_isChinese) DbgPrint("申请文件内存%dB失败",FileSize); else DbgPrint("failed to apply for file memory %dB", FileSize); goto Exit; } RLen = FileSize; if( !ReadFile(hFile,FileBuf,RLen,&RLen,NULL) ) { if (g_isChinese) DbgPrint("从文件中读取测试数据失败",FileSize); else DbgPrint("Failed to read the test data from file", FileSize); goto Exit; } DbgPrint("\r\n"); if (g_isChinese) { DbgPrint("****开始速度测试,测试数据长度为 %dB",FileSize); DbgPrint("*>>*1.Flash擦除速度测试"); } else { DbgPrint("****Start the speed test, and the test data length is %dB",FileSize); DbgPrint("*>>*1. Flash erase speed test"); } TestLen = FileSize; BT = GetCurrentTimerVal(); RetVal = FLASH_Erase_Full(); UsedT = (GetCurrentTimerVal()-BT)/1000; if (g_isChinese) { DbgPrint("*<<*擦除全部%s,平均速度:%.2fKB/S,累计用时%.3fS",RetVal?"成功":"失败",TestLen/UsedT/1000,UsedT); DbgPrint("*>>*2.Flash块写速度测试"); } else { DbgPrint("*<<*Erase all%s, average speed:%.2fkb/s, accumulated time%.3fS",RetVal?" Success ":" failed",TestLen/UsedT/1000,UsedT); DbgPrint("*>>*2. Flash block write speed test"); } BlockSize = 0x100; TestLen = FileSize; TC = (FileSize+BlockSize-1)/BlockSize; BT = GetCurrentTimerVal(); for(i=0;(i> 16 ); RBuf[2] = (UINT8)( Addr >> 8 ); RBuf[3] = (UINT8)Addr&0xFF; RLen += 4; memcpy(&RBuf[4],FileBuf+Addr,RLen); RetVal = CH347SPI_Write(DevIndex,0x80,RLen,BlockSize+4,RBuf); //SPI批量写 if(!RetVal) { if (g_isChinese) DbgPrint("写FLASH[0x%X][0x%X]失败",Addr,RLen); else DbgPrint("Write flash[0x%X][0x%X] failed",Addr,RLen); break; } Timeout = 0; do//等待写结束 { temp = FLASH_ReadStatusReg(); if( (temp & 0x01)<1) break; Sleep(0); Timeout += 1; if(Timeout > FLASH_OP_TIMEOUT*20) { DbgPrint(" [0x%X][0x%X]>FLASH_Read timeout",Addr,RLen); RetVal= FALSE; break; //退出写 } }while( temp & 0x01 ); } UsedT = (GetCurrentTimerVal()-BT)/1000; if (g_isChinese) { DbgPrint("*<<*块写%d字节 %s.平均速度:%.3fKB/S,累计用时%.3fS",TestLen,RetVal?"成功":"失败",TestLen/UsedT/1000,UsedT); DbgPrint("*>>*3.Flash块读速度测试"); }else { DbgPrint("*<<*Block write%d bytes%s. average speed:%.3fkb/s, accumulated time%.3fS",TestLen,RetVal?" Success ":" Failed",TestLen/UsedT/1000,UsedT); DbgPrint("*>>*3. Flash block reading speed test"); } TestLen = FileSize; //先发送读地址 Addr = 0; RBuf[0] = CMD_FLASH_READ; RBuf[1] = (UINT8)( Addr >> 16 ); RBuf[2] = (UINT8)( Addr >> 8 ); RBuf[3] = (UINT8)( Addr ); WLen = 4; //快速读取SPI FLASH RLen = TestLen;//一次读完 BT = GetCurrentTimerVal(); RetVal = CH347SPI_Read(DevIndex,0x80,WLen,&RLen,RBuf);//SPI批量读,先发命令 UsedT = (GetCurrentTimerVal()-BT)/1000; if( !RetVal ) { if (g_isChinese) DbgPrint("从FLASH起始地址读%dB数据失败",TestLen); else DbgPrint("Failed to read %dB data from flash start address",TestLen); } if(RLen != TestLen) { if (g_isChinese) DbgPrint("读取数据不完整(0x%X-0x%X)",RLen,TestLen); else DbgPrint("Incomplete read data (0x%X-0x%X)",RLen,TestLen); } if (g_isChinese) DbgPrint("*<<*块读%d字节 %s.平均速度:%.3fKB/S,累计用时%.3fS",TestLen,RetVal?"成功":"失败",TestLen/UsedT/1000,UsedT); else DbgPrint("*<<*Block read%d bytes%s. average speed:%.3fKB/s, accumulated time%.3fS",TestLen,RetVal?" Success ":" failed",TestLen/UsedT/1000,UsedT); if( !RetVal ) goto Exit; if (g_isChinese) DbgPrint("*>>*4.Flash写读内容检查"); else DbgPrint("*>>*4.Flash write/read content check"); TestLen = FileSize; TC = (TestLen+8192-1)/8192; for(i=0;iFileSize) PrintLen = FileSize - ((Addr+k)&0xFFF0+16); else PrintLen = 16; ErrLoca = (Addr+k)%16; if (g_isChinese) DbgPrint("[%04X]:%02X-%02X:写入和读出的数据不匹配",k+Addr,FileBuf[Addr+k],RBuf[Addr+k]); else DbgPrint("[%04X]:%02X-%02X: data written and read do not match",k+Addr,FileBuf[Addr+k],RBuf[Addr+k]); DumpDataBuf((Addr+k)&0xFFF0,RBuf+((Addr+k)&0xFFF0),FileBuf+((Addr+k)&0xFFF0),PrintLen,ErrLoca); goto Exit; } } } if (g_isChinese) DbgPrint("*<<*检查Flash写和读共计%dB,全部匹配",TestLen); else DbgPrint("*<<*Check the flash write and read for a total of %dB, all matching",TestLen); DbgPrint("Test Result: P A S S"); Exit: if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if(FileBuf!=NULL) free(FileBuf); EnableWindow(FlashEepromDbgHwnd,TRUE); return RetVal; } //读FLASH内容至文件 DWORD WINAPI WriteFlashFromFile(LPVOID lpParameter) { CHAR FileName[MAX_PATH] = "",FmtStr[64]=""; OPENFILENAME mOpenFile={0}; ULONG TestLen,RLen,Addr,TC,i,Timeout,temp,BlockSize=0; PUCHAR FileBuf=NULL; double BT,UsedT; BOOL RetVal = FALSE; HANDLE hFile=INVALID_HANDLE_VALUE; UCHAR RBuf[4096] = ""; // Fill in the OPENFILENAME structure to support a template and hook. mOpenFile.lStructSize = sizeof(OPENFILENAME); mOpenFile.hwndOwner = FlashEepromDbgHwnd; mOpenFile.hInstance = AfxMainIns; mOpenFile.lpstrFilter = "*.*\x0\x0"; mOpenFile.lpstrCustomFilter = NULL; mOpenFile.nMaxCustFilter = 0; mOpenFile.nFilterIndex = 0; mOpenFile.lpstrFile = FileName; mOpenFile.nMaxFile = sizeof(FileName); mOpenFile.lpstrFileTitle = NULL; mOpenFile.nMaxFileTitle = 0; mOpenFile.lpstrInitialDir = NULL; if (g_isChinese) mOpenFile.lpstrTitle = "选择待写入FLASH的数据文件"; else mOpenFile.lpstrTitle = "Select the data file to be written to FLASH"; mOpenFile.nFileOffset = 0; mOpenFile.nFileExtension = 0; mOpenFile.lpstrDefExt = NULL; mOpenFile.lCustData = 0; mOpenFile.lpfnHook = NULL; mOpenFile.lpTemplateName = NULL; mOpenFile.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_READONLY | OFN_FILEMUSTEXIST; if (GetOpenFileName(&mOpenFile)) DbgPrint("Write data to flash from:%s",FileName); else goto Exit; hFile = CreateFile(FileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,NULL); if(hFile==INVALID_HANDLE_VALUE) { if (g_isChinese) ShowLastError("WriteFlashFromFile.打开保存文件"); else ShowLastError("WriteFlashFromFile.Open save file"); goto Exit; } TestLen = GetFileSize(hFile,NULL); if(TestLen<1) { if (g_isChinese) DbgPrint("WriteFlashFromFile.写入FLASH数据文件为空,请重选"); else DbgPrint("WriteFlashFromFile. Write FLASH data file is empty, please reselect"); goto Exit; } if( TestLen > (Flash_Sector_Size * Flash_Sector_Count) ) //Flash容量 TestLen = Flash_Sector_Size * Flash_Sector_Count; if (g_isChinese) DbgPrint("*>>*WriteFlashFromFile.Flash写%d字节",TestLen); else DbgPrint("*>>*WriteFlashFromFile. Flash writes%d bytes",TestLen); FileBuf = (PUCHAR)malloc(TestLen+64); if(FileBuf==NULL) { if (g_isChinese) DbgPrint("WriteFlashFromFile.申请内存失败"); else DbgPrint("WriteFlashFromFile.Failed to request memory"); goto Exit; } memset(FileBuf,0,TestLen+64); RLen = TestLen; if( !ReadFile(hFile,FileBuf,RLen,&RLen,NULL) ) { ShowLastError("WriteFlashFromFile.Read file"); goto Exit; } if(RLen!=TestLen) { DbgPrint("WriteFlashFromFile.ReadFlashFile len err(%d-%d)",RLen,TestLen); goto Exit; } if (g_isChinese) DbgPrint("*>>*1.WriteFlashFromFile.擦除"); else DbgPrint("*>>*1.writeflashfromfile.erase"); Addr=0; TC = (TestLen+Flash_Sector_Size-1)/Flash_Sector_Size; //page BT = GetCurrentTimerVal(); for(i=0;i>*2.WriteFlashFromFile.Flash块写"); }else { DbgPrint("*<<*WriteFlashFromFile.Erase%d blocks(%dB) %s,Average speed:%.2fKB/S,Average speed%.3fS", TC,TC*32768,RetVal?"Success":"Failed", TestLen/UsedT/1000,UsedT); DbgPrint("*>>*2.WriteFlashFromFile.Flash blocks write"); } BlockSize = 0x100; TC = (TestLen+BlockSize-1)/BlockSize; BT = GetCurrentTimerVal(); for(i=0;(i> 16 ); RBuf[2] = (UINT8)( Addr >> 8 ); RBuf[3] = (UINT8)Addr; RLen += 4; memcpy(&RBuf[4],FileBuf+Addr,RLen); RetVal = CH347SPI_Write(DevIndex,0x80,RLen,BlockSize+4,RBuf); if(!RetVal) DbgPrint("WriteFlashFromFile.Write FLASH[0x%X][0x%X] Failed",Addr,RLen); } else break; Timeout = 0; do { temp = FLASH_ReadStatusReg(); if( (temp & 0x01)<1) break; Sleep(0); Timeout += 1; if(Timeout > FLASH_OP_TIMEOUT) { DbgPrint(" [0x%X][0x%X]>FLASH_Read timeout",Addr,RLen); RetVal= FALSE; break; //退出写 } }while( temp & 0x01 ); } UsedT = (GetCurrentTimerVal()-BT)/1000; if (g_isChinese) DbgPrint("*<<*WriteFlashFromFile.块写%d字节 %s.平均速度:%.3fKB/S,累计用时%.3fS",TestLen,RetVal?"成功":"失败",TestLen/UsedT/1000,UsedT); else DbgPrint("*<<*WriteFlashFromFile.Block write%d bytes %s.Average speed:%.3fKB/S,Accumulated time%.3fS",TestLen,RetVal?"Success":"Failed",TestLen/UsedT/1000,UsedT); Exit: if(FileBuf!=NULL) free(FileBuf); if(hFile!=INVALID_HANDLE_VALUE) CloseHandle(hFile); return RetVal; } //检验FLASH内容 DWORD WINAPI FlashVerifyWithFile(LPVOID lpParameter) { ULONG FlashAddr = 0,TC,TestLen,i,k; double BT = 0; BOOL RetVal = FALSE; CHAR FileName[MAX_PATH]=""; HANDLE hFile=INVALID_HANDLE_VALUE; PUCHAR FileBuf=NULL,RBuf=NULL; ULONG FileSize,RLen,UnitSize,Addr,WLen; double UsedT = 0; ULONG PrintLen,ErrLoca; OPENFILENAME mOpenFile={0}; if (g_isChinese) DbgPrint("*>>*开始验证FLASH内容"); else DbgPrint("*>>*Start verifying flash content"); // Fill in the OPENFILENAME structure to support a template and hook. mOpenFile.lStructSize = sizeof(OPENFILENAME); mOpenFile.hwndOwner = FlashEepromDbgHwnd; mOpenFile.hInstance = AfxMainIns; mOpenFile.lpstrFilter = "*.*\x0\x0"; mOpenFile.lpstrCustomFilter = NULL; mOpenFile.nMaxCustFilter = 0; mOpenFile.nFilterIndex = 0; mOpenFile.lpstrFile = FileName; mOpenFile.nMaxFile = sizeof(FileName); mOpenFile.lpstrFileTitle = NULL; mOpenFile.nMaxFileTitle = 0; mOpenFile.lpstrInitialDir = NULL; if (g_isChinese) mOpenFile.lpstrTitle = "选择待写入Flash的数据文件"; else mOpenFile.lpstrTitle = "Select the data file to be written to flash"; mOpenFile.nFileOffset = 0; mOpenFile.nFileExtension = 0; mOpenFile.lpstrDefExt = NULL; mOpenFile.lCustData = 0; mOpenFile.lpfnHook = NULL; mOpenFile.lpTemplateName = NULL; mOpenFile.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_READONLY | OFN_FILEMUSTEXIST; if (GetOpenFileName(&mOpenFile)) { DbgPrint("Verify flash with file:%s",FileName); } else goto Exit; if(strlen(FileName) < 1) { if (g_isChinese) DbgPrint("文件无效,请重新选择"); else DbgPrint("Invalid file, please reselect"); goto Exit; } hFile = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//打开文件 if(hFile == INVALID_HANDLE_VALUE) { ShowLastError("CreateFile"); goto Exit; } FileSize = GetFileSize(hFile,NULL); if(FileSize<128) { if (g_isChinese) DbgPrint("用于比对的文件%d字节太小,请重新选择",FileSize); else DbgPrint("The file used for comparison%d bytes is too small, please reselect", FileSize); goto Exit; } if( FileSize > (Flash_Sector_Size * Flash_Sector_Count) ) { TestLen = Flash_Sector_Size * Flash_Sector_Count; } else TestLen = FileSize; FileBuf = (PUCHAR)malloc(FileSize); if(FileBuf==NULL) { if (g_isChinese) DbgPrint("申请文件内存%dB失败",FileSize); else DbgPrint("failed to apply for file memory%dB", FileSize); goto Exit; } RBuf = (PUCHAR)malloc(FileSize+128); if(RBuf==NULL) { if (g_isChinese) DbgPrint("申请文件内存%dB失败",FileSize); else DbgPrint("failed to apply for file memory%dB", FileSize); goto Exit; } RLen = TestLen; if( !ReadFile(hFile,FileBuf,RLen,&RLen,NULL) ) { if (g_isChinese) DbgPrint("从文件中读取数据失败",FileSize); else DbgPrint("Failed to read data from file", FileSize); goto Exit; } //先发送读地址 Addr = 0; RBuf[0] = CMD_FLASH_READ; RBuf[1] = (UINT8)( Addr >> 16 ); RBuf[2] = (UINT8)( Addr >> 8 ); RBuf[3] = (UINT8)( Addr ); WLen = 4; //快速读取SPI FLASH RLen = TestLen;//一次读完 BT = GetCurrentTimerVal(); RetVal = CH347SPI_Read(DevIndex,0x80,WLen,&RLen,RBuf);//读 if( !RetVal ) { if (g_isChinese) DbgPrint("从FLASH起始地址读%dB数据失败",TestLen); else DbgPrint("Failed to read %dB data from FLASH starting address", TestLen); } if(RLen != TestLen) { if (g_isChinese) DbgPrint("读取数据不完整(0x%X-0x%X)",RLen,TestLen); else DbgPrint("Read data incomplete (0x%x-0x%x)",RLen,TestLen); } if( !RetVal ) goto Exit; TestLen = FileSize; TC = (TestLen+8192-1)/8192; for(i=0;iFileSize) PrintLen = FileSize - ((Addr+k)&0xFFF0+16); else PrintLen = 16; ErrLoca = (Addr+k)%16; if (g_isChinese) DbgPrint("[%04X]:%02X-%02X:写入和读出的数据不匹配",k+Addr,FileBuf[Addr+k],RBuf[Addr+k]); else DbgPrint("[%04x]:%02x-%02x: the data written and read do not match", k+Addr,FileBuf[Addr+k],RBuf[Addr+k]); DumpDataBuf((Addr+k)&0xFFF0,RBuf+((Addr+k)&0xFFF0),FileBuf+((Addr+k)&0xFFF0),PrintLen,ErrLoca); goto Exit; } } } RetVal = TRUE; UsedT = (GetCurrentTimerVal()-BT)/1000; if (g_isChinese) DbgPrint("*<<*验证FLASH内容%dB,与文件内容匹配,平均速度:%.3fKB/S,累计用时%.3fS",TestLen,TestLen/UsedT/1000,UsedT); else DbgPrint("*<<*Verify FLASH content %dB, match the file content, average speed:%.3fkb/s, cumulative time%.3fs",TestLen,TestLen/UsedT/1000,UsedT); Exit: if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if(FileBuf!=NULL) free(FileBuf); if(RBuf!=NULL) free(RBuf); if (g_isChinese) DbgPrint("*>>*FLASH验证%s",RetVal?"完成":"失败"); else DbgPrint("*>>*FLASH verifies%s",RetVal?"success":"failed"); DbgPrint("\r\n"); return RetVal; } //读FLASH内容至文件 DWORD WINAPI ReadFlashToFile(LPVOID lpParameter) { // 获取将要发送的文件名 CHAR FileName[MAX_PATH] = "",FmtStr[64]=""; OPENFILENAME mOpenFile={0}; ULONG TestLen,RLen,Addr; PUCHAR RBuf=NULL; double BT,UsedT; BOOL RetVal = FALSE; HANDLE hFile=INVALID_HANDLE_VALUE; // Fill in the OPENFILENAME structure to support a template and hook. mOpenFile.lStructSize = sizeof(OPENFILENAME); mOpenFile.hwndOwner = FlashEepromDbgHwnd; mOpenFile.hInstance = AfxMainIns; mOpenFile.lpstrFilter = "*.*\x0\x0"; mOpenFile.lpstrCustomFilter = NULL; mOpenFile.nMaxCustFilter = 0; mOpenFile.nFilterIndex = 0; mOpenFile.lpstrFile = FileName; mOpenFile.nMaxFile = sizeof(FileName); mOpenFile.lpstrFileTitle = NULL; mOpenFile.nMaxFileTitle = 0; mOpenFile.lpstrInitialDir = NULL; if (g_isChinese) mOpenFile.lpstrTitle = "选择FLASH数据保存文件"; else mOpenFile.lpstrTitle = "Select FLASH data save file"; mOpenFile.nFileOffset = 0; mOpenFile.nFileExtension = 0; mOpenFile.lpstrDefExt = NULL; mOpenFile.lCustData = 0; mOpenFile.lpfnHook = NULL; mOpenFile.lpTemplateName = NULL; mOpenFile.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_READONLY | OFN_FILEMUSTEXIST; if (GetSaveFileName(&mOpenFile)) DbgPrint("FlashData will save to:%s",FileName); else goto Exit; TestLen = Flash_Sector_Size * Flash_Sector_Count; //Flash容量 if (g_isChinese) DbgPrint("*>>*ReadFlashToFile.Flash读%d字节至文件",TestLen); else DbgPrint("*>>*ReadFlashToFile. Flash reads%d bytes to file",TestLen); hFile = CreateFile(FileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,NULL); if(hFile==INVALID_HANDLE_VALUE) { if (g_isChinese) ShowLastError("ReadFlashToFile.打开保存文件"); else ShowLastError("ReadFlashToFile.open save file"); goto Exit; } RBuf = (PUCHAR)malloc(TestLen+64); if(RBuf==NULL) { if (g_isChinese) DbgPrint("ReadFlashToFile.申请内存失败"); else DbgPrint("ReadFlashToFile.Failed to request memory"); goto Exit; } //发送读地址 Addr = 0; RBuf[0] = CMD_FLASH_READ; RBuf[1] = (UINT8)( Addr >> 16 ); RBuf[2] = (UINT8)( Addr >> 8 ); RBuf[3] = (UINT8)( Addr ); BT = GetCurrentTimerVal(); //快速读取SPI FLASH RLen = TestLen;//待读长度 RetVal = CH347SPI_Read(DevIndex,0x80,4,&RLen,RBuf); if( !RetVal ) { if (g_isChinese) DbgPrint("ReadFlashToFile.从FLASH起始地址读%dB数据失败",RLen); else DbgPrint("ReadFlashToFile.Failed to read%dB data from flash start address",RLen); } if(RLen != TestLen) { if (g_isChinese) DbgPrint("ReadFlashToFile.读取数据不完整(0x%X-0x%X)",RLen,TestLen); else DbgPrint("ReadFlashToFile.Incomplete read data(0x%X-0x%X)",RLen,TestLen); } UsedT = (GetCurrentTimerVal()-BT)/1000; if (g_isChinese) DbgPrint("*<<*ReadFlashToFile.块读%d字节 %s.平均速度:%.3fKB/S,累计用时%.3fS",TestLen,RetVal?"成功":"失败",TestLen/UsedT/1000,UsedT); else DbgPrint("*<<*ReadFlashToFile. block read%d bytes%s. average speed:%.3fkb/s, cumulative time%.3fs", TestLen,RetVal? "Success": "failure",TestLen/UsedT/1000,UsedT); if( !WriteFile(hFile,RBuf,RLen,&RLen,NULL) ) { if (g_isChinese) ShowLastError("ReadFlashToFile.数据写入文件:"); else ShowLastError("ReadFlashToFile.Data write file:"); goto Exit; } if(RLen!=TestLen) { if (g_isChinese) DbgPrint("ReadFlashToFile写入不完整"); else DbgPrint("ReadFlashToFile Incomplete writing"); goto Exit; } RetVal = TRUE; Exit: if(RBuf!=NULL) free(RBuf); if(hFile!=INVALID_HANDLE_VALUE) CloseHandle(hFile); return RetVal; } //打开设备 BOOL FlashSpi_OpenDevice() { //获取设备序号 DevIndex = SendDlgItemMessage(FlashEepromDbgHwnd,IDC_ObjList,CB_GETCURSEL,0,0); if(DevIndex==CB_ERR) { if (g_isChinese) DbgPrint("请先打开设备"); else DbgPrint("Please open the device first"); goto Exit; //退出 } FlashDevIsOpened = (CH347OpenDevice(DevIndex) != INVALID_HANDLE_VALUE); if (g_isChinese) DbgPrint(">>%d#设备打开...%s",DevIndex,FlashDevIsOpened?"成功":"失败"); else DbgPrint(">>%d#Open Device...%s",DevIndex,FlashDevIsOpened?"Success":"Failed"); Exit: FlashDlg_EnableButtonEnable(); return FlashDevIsOpened; } //关闭设备 BOOL FlashSpi_CloseDevice() { CH347CloseDevice(DevIndex); FlashDevIsOpened = FALSE; if (g_isChinese) DbgPrint(">>设备已关闭"); else DbgPrint(">>The Devices is closed"); DevIndex = CB_ERR; FlashDlg_EnableButtonEnable(); return TRUE; } //显示设备信息 BOOL FlashDlg_ShowDevInfor() { ULONG ObjSel; CHAR FmtStr[128]=""; ObjSel = SendDlgItemMessage(FlashEepromDbgHwnd,IDC_ObjList,CB_GETCURSEL,0,0); if(ObjSel!=CB_ERR) { sprintf(FmtStr,"**ChipMode:%d,%s,Ver:%02X,DevID:%s",FlashDevInfor[ObjSel].ChipMode,FlashDevInfor[ObjSel].UsbSpeedType?"HS":"FS",FlashDevInfor[ObjSel].FirewareVer,FlashDevInfor[ObjSel].DeviceID); SetDlgItemText(FlashEepromDbgHwnd,IDC_DevInfor,FmtStr); } return (ObjSel!=CB_ERR); } //枚举设备 ULONG FlashDlg_EnumDevice() { ULONG i,oLen,DevCnt = 0; USB_DEVICE_DESCRIPTOR DevDesc = {0}; CHAR tem[256] = ""; mDeviceInforS DevInfor = {0}; SendDlgItemMessage(FlashEepromDbgHwnd,IDC_ObjList,CB_RESETCONTENT,0,0); for(i=0;i<16;i++) { if(CH347OpenDevice(i) != INVALID_HANDLE_VALUE) { oLen = sizeof(USB_DEVICE_DESCRIPTOR); CH347GetDeviceInfor(i,&DevInfor); if(DevInfor.ChipMode == 3) //模式3此接口为JTAG/I2C continue; sprintf(tem,"%d# %s",i,DevInfor.FuncDescStr); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_ObjList,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)tem); memcpy(&FlashDevInfor[DevCnt],&DevInfor,sizeof(DevInfor)); DevCnt++; } CH347CloseDevice(i); } if(DevCnt) { SendDlgItemMessage(FlashEepromDbgHwnd,IDC_ObjList,CB_SETCURSEL,0,0); SetFocus(GetDlgItem(FlashEepromDbgHwnd,IDC_ObjList)); } return DevCnt; } //使能操作按钮,需先打开和配置,否则无法操作 VOID FlashDlg_EnableButtonEnable() { if(!FlashDevIsOpened) IsSpiInit = FALSE; EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_CMD_InitSPI),FlashDevIsOpened); //更新打开/关闭设备按钮状态 EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_OpenDevice),!FlashDevIsOpened); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_CloseDevice),FlashDevIsOpened); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_ObjList),!FlashDevIsOpened); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_RefreshObjList),!FlashDevIsOpened); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashVerify),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashRWSpeedTest),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashIdentify),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashRead),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashWrite),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashErase),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_ReadToFile),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_WriteFormFile),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashVerify),IsSpiInit); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_FlashRWSpeedTest),IsSpiInit); } //初始化窗体 VOID FlashDlg_InitWindows() { //查找并显示设备列表 SendDlgItemMessage(FlashEepromDbgHwnd,IDC_RefreshObjList,BM_CLICK,0,0); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_OpenDevice),!FlashDevIsOpened); EnableWindow(GetDlgItem(FlashEepromDbgHwnd,IDC_CloseDevice),FlashDevIsOpened); //Flash地址斌初值 SetDlgItemText(FlashEepromDbgHwnd,IDC_FlashStartAddr,"0"); //Flash操作数斌初值 SetDlgItemText(FlashEepromDbgHwnd,IDC_FlashDataSize,"100"); //清空Flash数据模式 SetDlgItemText(FlashEepromDbgHwnd,IDC_FlashData,""); //输出框设置显示的最大字符数 SendDlgItemMessage(FlashEepromDbgHwnd,IDC_InforShow,EM_LIMITTEXT,0xFFFFFFFF,0); { SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"Mode0"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"Mode1"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"Mode2"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"Mode3"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Mode,CB_SETCURSEL,3,0); } {//0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz, 4=3.75MHz, 5=1.875MHz, 6=937.5KHz,7=468.75KHz SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"60MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"30MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"15MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"7.5MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"3.75MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"1.875MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"937.5KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"468.75KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_SpiCfg_Clock,CB_SETCURSEL,1,0); } //I2C的时钟配置 { SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"20KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"100KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"400KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"750KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"50KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"200KHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_ADDSTRING,0,(LPARAM) (LPCTSTR)"1MHz"); SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_SETCURSEL,0,3); } SetDlgItemInt(FlashEepromDbgHwnd,IDC_TestLen,100,FALSE); SetEditlInputMode(FlashEepromDbgHwnd,IDC_FlashData,1); //设置edit为十六进制输入模式 return; } //主窗体进程 BOOL APIENTRY DlgProc_FlashEepromDbg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; ULONG ThreadID; UCHAR I2CClockSel; //I2C switch (message) { case WM_INITDIALOG: FlashEepromDbgHwnd = hWnd; AfxActiveHwnd = hWnd; FlashDevIsOpened = FALSE; CheckDlgButton(hWnd,IDC_EnablePnPAutoOpen_Flash,BST_CHECKED); FlashDlg_InitWindows(); //初始化窗体 FlashDlg_EnableButtonEnable(); InitWindows_Eeprom(); Eeprom_InitI2C(); //Uart_InitParam(); //为USB2.0JTAG设备设置插入和拔出的通知.插入后自动打开设备,拔出后关闭设备 // if(CH341SetDeviceNotify(0,DevID_Mode1_2, UsbDevPnpNotify) ) //设备插拔通知回调函数 // DbgPrint("已开启USB设备插拔监视"); // break; //case WM_USB20SpiDevArrive: //监测到设备插入 // DbgPrint("****发现CH347设备插入USB口,打开设备"); //先枚举USB设备 // SendDlgItemMessage(FlashEepromDbgHwnd,IDC_RefreshObjList,BM_CLICK,0,0); //打开设备 // SendDlgItemMessage(FlashEepromDbgHwnd,IDC_OpenDevice,BM_CLICK,0,0); // break; //case WM_USB20SpiDevRemove: //监测到设备拔出 // DbgPrint("****发现CH347已从USB口移除,关闭设备"); //关闭设备 // SendDlgItemMessage(FlashEepromDbgHwnd,IDC_CloseDevice,BM_CLICK,0,0); // break; case WM_NOTIFY: { if(((LPNMHDR)lParam)->code == PSN_SETACTIVE) AfxActiveHwnd = hWnd; } break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDC_RefreshObjList: FlashDlg_EnumDevice(); //枚举并显示设备 break; case IDC_ObjList: FlashDlg_ShowDevInfor(); break; case IDC_OpenDevice://打开设备 FlashSpi_OpenDevice(); FlashDlg_EnableButtonEnable(); //更新按钮状态 break; case IDC_CloseDevice: FlashSpi_CloseDevice(); FlashDlg_EnableButtonEnable(); //更新按钮状态 break; case IDC_CMD_InitSPI: IsSpiInit = Flash_InitSpi(); FlashDlg_EnableButtonEnable(); break; case IDC_CMD_InitI2C: I2CClockSel = (UCHAR)SendDlgItemMessage(FlashEepromDbgHwnd,IDC_I2CCfg_Clock,CB_GETCURSEL,0,0); CH347I2C_Set(DevIndex,I2CClockSel); //配置I2C速度为快速750K break; case IDC_FlashIdentify: FlashIdentify(); break; case IDC_FlashRead: FlashBlockRead(); break; case IDC_FlashWrite://将IDC_FLASHDATA框内数据写入FLASH FlashBlockWrite(); break; case IDC_FlashErase: FlashBlockErase(); break; case IDC_FlashVerify: CloseHandle(CreateThread(NULL,0,FlashVerifyWithFile,NULL,0,&ThreadID)); break; case IDC_WriteFormFile: CloseHandle(CreateThread(NULL,0,WriteFlashFromFile,NULL,0,&ThreadID)); break; case IDC_ReadToFile: CloseHandle(CreateThread(NULL,0,ReadFlashToFile,NULL,0,&ThreadID)); break; case IDC_FlashRWSpeedTest://读写测速 CloseHandle(CreateThread(NULL,0,FlashRWSpeedTest,NULL,0,&ThreadID)); break; case IDC_EepromRead: EerpromRead(); break; case IDC_EepromWrite: EepromWrite(); break; case IDC_EepromVerify: CloseHandle(CreateThread(NULL,0,EepromVerifyWithFile,NULL,0,&ThreadID)); break; case IDC_WriteEepromFormFile: CloseHandle(CreateThread(NULL,0,WriteEepromFromFile,NULL,0,&ThreadID)); break; case IDC_ReadEepromToFile: CloseHandle(CreateThread(NULL,0,ReadEepromToFile,NULL,0,&ThreadID)); break; case IDC_EepromType: Eeprom_InitI2C(); break; case IDC_ClearInfor: SetDlgItemText(hWnd,IDC_InforShow,""); break; case WM_DESTROY: SendDlgItemMessage(hWnd,IDC_CloseDevice,BM_CLICK,0,0); //CH347SetDeviceNotify(DevIndex,DevID_Mode1_2,NULL); DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: PostQuitMessage(0); break; } return 0; }