基本功能
在本设计中,数据的处理可以使用PC机的MATLAB等功能强大的软件,但是这类现有的数据处理软件并不能对特有的数据采集系统的下位机采集模块进行直接控制,因此需要针对特定的数据采集系统编写对应的上位机软件,上位机软件是针对上述目的而设计与编写的,是整个采集系统的控制前端和数据存储及处理中心。控制功能主要包括控制下位机采集的开始与终止,采集的频率等,数据处理功能主要包括绘制波形图,将数据显示于列表,将数据存储于文件,其中将数据存储于文件将便于使用现有的数据处理软件对数据进行一些数值算法处理,以达到科学研究,结论验证等目的。
开发环境
C++程序设计语言可以很好地实现面向对象的编程思想,采用C++编写上位机程序,可以将每一个功能模块封装成一个类,修改某个类的实现,增加类的功能不会影响整个程序的框架,这样就很容易维护和扩展功能;加之我们要实现的软件功能中需要调用大量的windows API函数库,所以采用VC++6.0作为上位机的开发环境。
程序功能模块划分
总的功能模块主要包括三个模块,即HID设备读写模块,数据采集模块,数据处理模块。
HID设备的查找与读写
(1)枚举
USB主机在检测到USB设备插入后,就要对设备进行枚举了。枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。
(2)HID
人机接口设备(HID)是指直接和人进行互动的设备,如鼠标、键盘等. 在Windows 中,具有相似属性和提供相似服务的设备被归为一种设备类型,一种类型的设备可以使用一个通用的设备驱动程序. 在运行Windows 98 或更高版本的PC 机上,应用程序可以使用操作系统内置的HID 类驱动程序与HID 通信. 这样使得符合HID 类的USB 设备很容易开发与运行.
(3)HID设备的查找
在Windows操作系统中内置很多与HID有关的API函数,调用这些函数,就可以开始对指定的HID设备进行查找,查找HID设备的最终目的是获得该设备的路径名,设备的存取容量等信息,为以后对该设备进行读写做好准备.
(4)HID设备的读写
在取得了HID设备的路径全面后,即可开始对HID设备进行读写,对设备的读写也是通过调用相应的函数来实现的。
控制下位机进行数据采集
上位机向下位机发送命令,控制下位机进行数据采集,并从下位机获取数据,在这个过程中,要处理好两个线程的同步的问题,即数据采集线程和数据处理线程能够协调工作,保正系统能正确稳定的工作。具体的解决方法是实现对某些数据访问的原子操作,即一个线程在对公共数据进行访问时,另一个线程不能打扰,直到操作线程操作完成,放弃对数据的使用权,另一个线程才能够访问数据。
下位机获取了关于采集的有关参数后,即可开始采集,每隔一定时间采集一个数据,当采集数据数目达到限制值个数后,本次采集完成,此时下位机才开始将采集数据发送给上位机。
上位机对采集的数据的处理
上位机在将数据采集命令发送给下位机后,所要做的就是等待下位机采集完成并接收数据,因此上位机将循环查询下位机工作状态,一旦检测到下位机采集结束的标志,上位机就开始对数据进行处理。
数据处理分为三种:
(1)绘制波形图
绘制波形图的要求有两点:第一是不能频繁闪烁,影响观察;二是波形图是动态的,因为绘制区域有限,而所采集的数据是源源不断增加的,因此要求波形图能够动态的更新。
(2)添加到列表显示
可直观地查看目前所采集的所有数据。
(3)保存到文件
运用功能强大的数据处理软件对数据进行更深的处理。
界面显示
采集单极性正弦波工作界面
代码:
1 HID设备通信模块实现代码/*hid.h头文件*/ 2 #ifndef HID_H 3 #define HID_H 4 #include <windows.h> 5 #include <setupapi.h> 6 #include <string> 7 #include "commonuse.h" 8 using std::string; 9 #pragma comment( lib, "setupapi.lib" ) 10 extern "C" { 11 #include "hidsdi.h" 12 } 13 #pragma comment( lib, "hid.lib" ) 14 15 16 class Hid 17 { 18 19 public: 20 Hid(const string &DeviceIdStr = MY_DEVICE_ID); 21 //Hid(DWORD Vid, DWORD Pid) {} 22 ~Hid() ; 23 BOOL Connect() ; 24 //BOOL ChangeDevice() {} 25 BOOL WriteHid(const BYTE * WriteBuff); 26 BOOL ReadHid(BYTE * ReadBuff); 27 BOOL IsWriteValid() const { return m_WriteValid ; } 28 BOOL IsReadValid() const { return m_ReadValid ; } 29 BOOL IsConnected() const { return m_IsConnected; } 30 const string & GetDeviceIDDesc() const { return m_DeviceIdStr ;} 31 private: 32 BOOL GetWRHandle() ; 33 private: 34 HANDLE m_WriteHandle; 35 HANDLE m_ReadHandle ; 36 string m_DeviceIdStr;//设备描述字符串 37 DWORD m_PID; 38 DWORD m_VID; 39 BOOL m_IsConnected ;//是否已连接上 40 BOOL m_ReadValid;//是否可进行读操作 41 BOOL m_WriteValid;//是否可进行写操作 42 BYTE m_RWBuff[USB_BUFF_SIZE+1] ;//读写缓冲 43 44 45 } ; 46 47 48 49 #endif 50 51 52 /*hic.cpp源文件*/ 53 54 #include "Hid.h" 55 56 Hid::Hid(const string &DeviceIdStr): 57 m_DeviceIdStr(DeviceIdStr) 58 { 59 60 m_WriteHandle = INVALID_HANDLE_VALUE ; 61 m_ReadHandle = INVALID_HANDLE_VALUE ; 62 m_PID = 0; 63 m_VID = 0; 64 m_IsConnected = FALSE ; 65 m_ReadValid = FALSE ; 66 m_WriteValid = FALSE; 67 strcpy((char *)m_RWBuff,"") ; 68 } 69 70 BOOL Hid::GetWRHandle() 71 { 72 GUID InterfaceClassGuid = \ 73 {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 74 HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE; 75 PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA; 76 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA; 77 SP_DEVINFO_DATA DevInfoData; 78 79 DWORD InterfaceIndex = 0; 80 DWORD StatusLastError = 0; 81 DWORD dwRegType; 82 DWORD dwRegSize; 83 DWORD StructureSize = 0; 84 PBYTE PropertyValueBuffer; 85 bool MatchFound = false; 86 DWORD ErrorStatus; 87 DeviceInfoTable = SetupDiGetClassDevs(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 88 while(true) 89 { 90 InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 91 if(SetupDiEnumDeviceInterfaces(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure)) 92 { 93 ErrorStatus = GetLastError(); 94 if(ERROR_NO_MORE_ITEMS == ErrorStatus) 95 { 96 SetupDiDestroyDeviceInfoList(DeviceInfoTable); 97 return FALSE; 98 } 99 } 100 else 101 { 102 103 ErrorStatus = GetLastError(); 104 SetupDiDestroyDeviceInfoList(DeviceInfoTable); 105 return FALSE; 106 } 107 108 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 109 SetupDiEnumDeviceInfo(DeviceInfoTable, InterfaceIndex, &DevInfoData); 110 111 SetupDiGetDeviceRegistryProperty(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize); 112 PropertyValueBuffer = (BYTE *) malloc (dwRegSize); 113 114 if(PropertyValueBuffer == NULL) 115 { 116 SetupDiDestroyDeviceInfoList(DeviceInfoTable); 117 return FALSE; 118 } 119 120 SetupDiGetDeviceRegistryProperty(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL); 121 MatchFound =( strcmp(m_DeviceIdStr.c_str(),(char *)PropertyValueBuffer) == 0 ); 122 free(PropertyValueBuffer); 123 124 //如果找到设备 125 if(MatchFound == true) 126 { 127 128 DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 129 SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL); 130 DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize)); 131 if(DetailedInterfaceDataStructure == NULL) 132 { 133 SetupDiDestroyDeviceInfoList(DeviceInfoTable); 134 return FALSE; 135 } 136 DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 137 SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 138 139 m_WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath),\ 140 GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0) ; 141 142 143 ErrorStatus = GetLastError(); 144 if(ErrorStatus != ERROR_SUCCESS) 145 { 146 return FALSE; 147 } 148 m_ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), \ 149 GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0) ; 150 ErrorStatus = GetLastError(); 151 if(ErrorStatus != ERROR_SUCCESS) 152 { 153 return FALSE ; 154 } 155 156 free(DetailedInterfaceDataStructure) ; 157 SetupDiDestroyDeviceInfoList(DeviceInfoTable); 158 return TRUE; 159 } 160 161 InterfaceIndex++; 162 } 163 } 164 BOOL Hid::Connect() 165 { 166 if(GetWRHandle()) 167 { 168 m_IsConnected = TRUE ; 169 m_WriteValid = m_WriteHandle == INVALID_HANDLE_VALUE ? FALSE:TRUE ; 170 m_ReadValid = m_ReadHandle == INVALID_HANDLE_VALUE ? FALSE:TRUE ; 171 return TRUE ; 172 } 173 return FALSE; 174 } 175 176 BOOL Hid::WriteHid(const BYTE * WriteBuff) 177 { 178 DWORD WriteNum = 0 ; 179 m_RWBuff[0] = 0x00 ; 180 memcpy(m_RWBuff + 1, WriteBuff, USB_BUFF_SIZE) ; 181 if(!WriteFile(m_WriteHandle,m_RWBuff, USB_BUFF_SIZE + 1, & WriteNum, NULL)) 182 { 183 return FALSE ; 184 } 185 return TRUE; 186 } 187 188 BOOL Hid::ReadHid(BYTE * ReadBuff) 189 { 190 DWORD ReadNum = 0 ; 191 if(!ReadFile(m_ReadHandle, m_RWBuff, USB_BUFF_SIZE + 1, &ReadNum, NULL)) 192 { 193 return FALSE ; 194 } 195 memcpy(ReadBuff, m_RWBuff + 1, USB_BUFF_SIZE ); 196 return TRUE ; 197 198 } 199 Hid::~Hid() 200 { 201 m_WriteHandle == INVALID_HANDLE_VALUE ? NULL : CloseHandle(m_WriteHandle); 202 m_ReadHandle == INVALID_HANDLE_VALUE ? NULL : CloseHandle(m_ReadHandle); 203 } 204 205 数据采集模块实现代码 206 /*datacollectthread.h*/ 207 #ifndef COLLECT_THREAD_H 208 #define COLLECT_THREAD_H 209 210 #include "commonuse.h" 211 #include "hid.h" 212 #include <process.h> 213 #include <math.h> 214 class DataCollectThread 215 { 216 public: 217 DataCollectThread() {}; 218 ~DataCollectThread() {}; 219 220 void StartThread(COLLECTED_DATA *p_collectedData) 221 { 222 p_collectedData->classPointer = (void *)this ; 223 _beginthread(BeginCollectTemp, 0 , p_collectedData) ; 224 } 225 static void BeginCollectTemp(void *p_collectedData) 226 { 227 DataCollectThread *thisPointer ; 228 thisPointer = ( (DataCollectThread *)(((COLLECTED_DATA *)p_collectedData)->classPointer) ) ; 229 thisPointer -> BeginCollect( (COLLECTED_DATA *) p_collectedData ); 230 } 231 //void EndThread() ; 232 private: 233 void BeginCollect(COLLECTED_DATA *p_collectedData) ; 234 private: 235 void GetData(COLLECTED_DATA *p_collectedData,collect_t *dataBuff, BYTE wantNum) ; 236 237 BOOL SendCommand(Hid *myHid, BYTE *commandBuff ) ; 238 BOOL GetPicState(Hid *myHid, BYTE *stateBuff ) ; 239 BOOL ReceiveData(Hid *myHid, BYTE *dataBuff ) ; 240 241 } ; 242 #endif 243 /*datacollectthread.cpp*/ 244 #include "datacollectthread.h" 245 246 void DataCollectThread::BeginCollect(COLLECTED_DATA * p_collectedData) 247 { 248 collect_t collectBuff[USB_BUFF_SIZE] = {0x00} ; 249 250 251 252 //等待公共数据缓冲区可写 253 while(1) 254 { 255 // ADD_STRING_TO_EDIT(p_collectedData->hWorkState, "采集线程尝试进入缓冲区...\n") ; 256 InitializeCriticalSection( &p_collectedData->criticalSection ) ; 257 EnterCriticalSection( &p_collectedData->criticalSection ); 258 259 // ADD_STRING_TO_EDIT(p_collectedData->hWorkState, "采集线程进入缓冲区...\n") ; 260 //放入数据 261 if(p_collectedData ->canBeWriting) 262 { 263 ADD_STRING_TO_EDIT(p_collectedData->hWorkState, "开始数据采集...\n") ; 264 //采集数据 265 GetData(p_collectedData, collectBuff, p_collectedData->picCollectNum) ; 266 ADD_STRING_TO_EDIT(p_collectedData->hWorkState, "数据采集结束,正在保存到公共缓冲区...\n") ; 267 memcpy(p_collectedData->data , collectBuff , p_collectedData->picCollectNum * 2 * sizeof(BYTE) ) ; 268 p_collectedData->canBeReading = TRUE ; 269 p_collectedData ->canBeWriting = FALSE ; 270 if(p_collectedData->collectMode == AUTO_COLLECT) 271 { 272 if(p_collectedData->endCollect) 273 { 274 p_collectedData->endCollect = FALSE ; 275 break ; 276 } 277 // goto NEXT ; 278 } 279 else 280 { 281 break ; 282 } 283 284 285 } 286 LeaveCriticalSection(&p_collectedData->criticalSection) ; 287 Sleep(300) ; 288 } 289 END: 290 ADD_STRING_TO_EDIT(p_collectedData->hWorkState, "采集线程退出...\n") ; 291 292 SendMessage(p_collectedData->hDlg, WM_END_COLLECT, 0, 0 ) ; 293 return ; 294 } 295 296 collect_t get_rand() 297 { 298 return 0x294 ; 299 } 300 301 void DataCollectThread::GetData(COLLECTED_DATA *p_collectedData,collect_t *dataBuff, BYTE wantNum) 302 { 303 304 BYTE COMMAND[USB_BUFF_SIZE] = {0x90,((p_collectedData->picCollectTimeGap) >> 24 ) & 0xff , 305 ((p_collectedData->picCollectTimeGap) >> 16 ) & 0xff , 306 ((p_collectedData->picCollectTimeGap) >> 8 ) & 0xff , 307 ((p_collectedData->picCollectTimeGap) ) & 0xff , 308 wantNum 309 310 } ; 311 BYTE stateBuff[USB_BUFF_SIZE] = {0} ; 312 313 #if 1 314 315 //发送命令,采集开始(1 BYTE)+采集时间间隔(4 BYTES)+采集数目(1 BYTE) 316 if(! SendCommand(p_collectedData->p_myHid, COMMAND) ) 317 { 318 319 } 320 //循环查询下位机是否采集结束,0x91为采集结束标志,其后跟着所采集数据 321 while( GetPicState(p_collectedData->p_myHid , stateBuff) , !(stateBuff[0] == 0x91 && stateBuff[1] == 0x91 ) ) 322 NULL ; 323 324 memcpy(dataBuff,stateBuff+2, (wantNum * 2 *sizeof(BYTE))) ; 325 326 #endif 327 328 329 #if 0 330 static double x = 0 ; 331 int i = 0; 332 WORD *tmpPtr = (WORD *)stateBuff ; 333 for(i = 0 ; i < wantNum; ++ i) 334 { 335 tmpPtr[i] = abs( 5.0*sin(x++) ); 336 // x+=0.1; 337 } 338 339 memcpy(dataBuff,stateBuff, (wantNum * 2 *sizeof(BYTE))) ; 340 341 #endif 342 343 } 344 345 BOOL DataCollectThread::SendCommand(Hid *myHid, BYTE *commandBuff ) 346 { 347 return myHid->WriteHid(commandBuff) ; 348 } 349 BOOL DataCollectThread::GetPicState(Hid *myHid, BYTE *statedBuff) 350 { 351 return myHid->ReadHid(statedBuff) ; 352 } 353 354 BOOL DataCollectThread::ReceiveData(Hid *myHid, BYTE *dataBuff ) 355 { 356 357 return myHid->ReadHid(dataBuff) ; 358 } 上位机数据处理模块实现代码 360 /**datadealthresd.h/ 361 #ifndef DRAW_THREAD 362 #define DRAW_THREAD 363 364 #include "commonuse.h" 365 #include "draw.h" 366 #include <windows.h> 367 #include <process.h> 368 #include <string> 369 #include <math.h> 370 #include <commctrl.h> 371 using std::string ; 372 373 374 #define TO_REAL_DATA(data) ( (double)((data)/(1023.0) * (5.0) ) ) 375 376 class DataDealThread//数据处理线程类 377 { 378 379 public: 380 DataDealThread() { } 381 ~DataDealThread() { DeleteDC(m_drawData.m_memDc) ; 382 DeleteDC(m_drawData.m_screenDc) ; 383 DeleteObject(m_drawData.m_hBitMap ) ; 384 } 385 386 void StartThread(DEAL_DATA *p_dealData) 387 { 388 p_dealData->dealClassPointer = (void *)this ; 389 _beginthread(StartDealTmp, 0, (void *)p_dealData) ; 390 } 391 void EndDealThread() ; 392 enum {MAX_BUFF_NUM = 100} ; 393 private: 394 static void StartDealTmp(void *p_dealData) 395 { 396 DataDealThread *thisPointer ; 397 DEAL_DATA *k = (DEAL_DATA *)p_dealData ; 398 399 thisPointer = (DataDealThread *) ( (DEAL_DATA *)p_dealData)->dealClassPointer ;//p_collectedData->classPointer ; 400 thisPointer->StartDeal((DEAL_DATA *)p_dealData) ; 401 } 402 private: 403 void StartDeal( DEAL_DATA *p_dealData) ; 404 private: 405 void DataInit(const DEAL_DATA *p_dealData) ; 406 void DrawInit() ; 407 void DrawByBuff() ;//对绘图缓冲区中的数据进行绘图 408 BOOL SaveToFile(collect_t data) ; 409 void AddToDataList(collect_t data) ; 410 411 private: 412 void DrawBackGround() ;//绘制背景 413 void DrawCodinate() ;//绘制坐标 414 415 void InsertDataToDrawBuff(collect_t) ;//将一个数据塞进缓冲区 416 417 void InitDrawData(const DEAL_DATA *p_dealData) ; 418 void InitListData(HWND hWnd) ; 419 void InitSavePath(string path ) ; 420 private: 421 typedef struct 422 { 423 int m_validDataNum ; 424 int temp_x ; 425 int temp_y ; 426 POINT coodinateBuff[MAX_BUFF_NUM] ; 427 }DRAW_BUFF ; 428 typedef struct 429 { 430 RECT m_drawRect ;//绘图区矩形 431 HWND m_hDraw ;//绘图区句柄 432 int m_timeGap ; 433 double m_aPiexValue ;//一个像素点对应电压值 434 double m_aPiexTime ;//一个像素点对应毫秒数 435 436 HDC m_memDc ; 437 HDC m_screenDc ; 438 439 HBITMAP m_hBitMap ; 440 DRAW_BUFF m_drawBuff ; 441 }DRAW_DATA ; 442 typedef struct 443 { 444 HWND m_hDataList ;//数据列表句柄 445 int dataNum ; 446 }LIST_DATA ; 447 DRAW_DATA m_drawData ; 448 LIST_DATA m_listData ; 449 string m_savePath ;//数据保存文件路径 450 } ; 451 452 #endif 453 454 /*datadealthread.cpp*/ 455 #include "dealthread.h" 456 //////////////////////////////////////////////////////////////////////////////// 457 void DataDealThread::StartDeal( DEAL_DATA *p_dealData) 458 { 459 460 collect_t dealBuff[USB_BUFF_SIZE] = {0x00} ; 461 size_t collectedNum = 0 ; 462 int i = 0 ; 463 //必要的数据初始化 464 DataInit( p_dealData ) ; 465 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "数据处理开始\n") ; 466 467 468 while(!p_dealData->p_collectedData->endDeal) 469 { 470 InitializeCriticalSection( & p_dealData->p_collectedData->criticalSection ) ; 471 // ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "尝试进入关键段\n") ; 472 EnterCriticalSection( & p_dealData->p_collectedData->criticalSection ) ; 473 474 // ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "进入关键段\n") ; 475 //可读则 476 if(p_dealData->p_collectedData->canBeReading) 477 { 478 //拷贝数据到本地处理 479 p_dealData->p_collectedData->canBeWriting = FALSE ; 480 collectedNum = p_dealData->p_collectedData->picCollectNum ; 481 memcpy(dealBuff, p_dealData->p_collectedData->data, collectedNum * 2 * sizeof(BYTE)) ; 482 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "数据采集线程获取所采集数据\n") ; 483 p_dealData->p_collectedData->canBeReading = FALSE ; 484 p_dealData->p_collectedData->canBeWriting = TRUE ; 485 486 //开始处理 487 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "开始处理\n") ; 488 for(i = 0 ; i < collectedNum ; ++ i) 489 { 490 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "开正在处理0x%4x\n-- %f\n", dealBuff[i], TO_REAL_DATA(dealBuff[i])) ; 491 492 InsertDataToDrawBuff( dealBuff[i] ) ; 493 DrawByBuff() ; 494 //数据加入显示列表 495 AddToDataList( dealBuff[i] ) ; 496 //保存到文件 497 SaveToFile(dealBuff[i]) ; 498 } 499 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "处理结束\n") ; 500 501 }//如果可读 502 //释放使用权 503 LeaveCriticalSection(& p_dealData->p_collectedData->criticalSection) ; 504 Sleep(300) ; 505 //检查是否有重绘通知 506 if(p_dealData->needRedraw) 507 { 508 //重绘 509 DrawByBuff() ; 510 //重绘完毕 511 p_dealData->needRedraw = FALSE ; 512 } 513 } 514 515 p_dealData->p_collectedData->endDeal = FALSE ; 516 ADD_STRING_TO_EDIT(p_dealData->p_collectedData->hWorkState, "数据处理结束\n") ; 517 518 519 } 520 /////////////////////////////////////////////////////////////////// 521 522 523 524 525 526 void DataDealThread::InitListData(HWND hList) 527 { 528 m_listData.m_hDataList = hList ; 529 m_listData.dataNum = 0 ; 530 } 531 void DataDealThread::InitSavePath(string savePath) 532 { 533 m_savePath = savePath ; 534 } 535 536 void DataDealThread::InitDrawData(const DEAL_DATA * p_dealData) 537 { 538 m_drawData.m_hDraw = p_dealData->h_drawCntl ; 539 GetClientRect(m_drawData.m_hDraw, &m_drawData.m_drawRect) ; 540 #if 0 541 m_drawData.m_drawRect.bottom -= 20 ; 542 m_drawData.m_drawRect.left += 20 ; 543 m_drawData.m_drawRect.right += 20 ; 544 #endif 545 m_drawData.m_timeGap = p_dealData->p_collectedData->picCollectTimeGap ; 546 m_drawData.m_aPiexTime = m_drawData.m_timeGap / 10.0;//一个像素点代表几毫秒 547 m_drawData.m_aPiexValue = 0.03 ;//一个像素点代表几伏 548 m_drawData.m_screenDc = GetDC(m_drawData.m_hDraw) ; 549 m_drawData.m_memDc = CreateCompatibleDC(m_drawData.m_screenDc) ; 550 m_drawData.m_hBitMap = CreateCompatibleBitmap(m_drawData.m_screenDc, m_drawData.m_drawRect.right - m_drawData.m_drawRect.left, 551 m_drawData.m_drawRect.bottom - m_drawData.m_drawRect.top) ; 552 SelectObject(m_drawData.m_memDc, m_drawData.m_hBitMap ) ; 553 memset(m_drawData.m_drawBuff.coodinateBuff, 0x00, USB_BUFF_SIZE*sizeof(POINT)) ; 554 m_drawData.m_drawBuff.m_validDataNum = 0 ; 555 m_drawData.m_drawBuff.temp_x = m_drawData.m_drawRect.left; 556 m_drawData.m_drawBuff.temp_y = 0 ; 557 } 558 void DataDealThread::DataInit(const DEAL_DATA * p_dealData) 559 { 560 InitDrawData(p_dealData) ; 561 InitListData(p_dealData->h_listCntl) ; 562 InitSavePath(p_dealData->savePath) ; 563 } 564 void DataDealThread::DrawInit() 565 { 566 //绘制背景 567 DrawBackGround() ; 568 //绘制坐标 569 DrawCodinate() ; 570 } 571 //绘制背景 572 void DataDealThread::DrawBackGround() 573 { 574 HBRUSH brush = CreateSolidBrush(RGB(0,0,0)) ; 575 FillRect(m_drawData.m_memDc, &m_drawData.m_drawRect, brush) ; 576 } 577 //绘制坐标线 578 void DataDealThread::DrawCodinate() 579 { 580 HPEN hPen ; 581 /******************绘制y朝向坐标线******************/ 582 hPen = CreatePen(PS_SOLID, 1,RGB(0,50,0) ) ; 583 SelectObject(m_drawData.m_memDc,hPen) ; 584 for(int x = m_drawData.m_drawRect.left ; x < m_drawData.m_drawRect.right ; x += m_drawData.m_timeGap / m_drawData.m_aPiexTime) 585 { 586 MoveToEx(m_drawData.m_memDc,x, m_drawData.m_drawRect.bottom,NULL) ; 587 588 LineTo(m_drawData.m_memDc, x,0); 589 } 590 DeleteObject(hPen) ; 591 592 /*******************绘制x朝向坐标线**************************/ 593 hPen = CreatePen(PS_SOLID, 1,RGB(0,50,0) ) ; 594 SelectObject(m_drawData.m_memDc,hPen) ; 595 //绘制正向 596 for(int y = m_drawData.m_drawRect.bottom / 2 ; y > m_drawData.m_drawRect.top ; y -= 10 ) //(double)1 / m_drawData.m_aPiexValue) 597 { 598 MoveToEx(m_drawData.m_memDc,m_drawData.m_drawRect.left, y,NULL) ; 599 //TextOut( 600 LineTo(m_drawData.m_memDc, m_drawData.m_drawRect.right ,y); 601 } 602 //绘制负向 603 for( y = m_drawData.m_drawRect.bottom / 2 ; y < m_drawData.m_drawRect.bottom ; y += 10 )//(double)1 / m_drawData.m_aPiexValue) 604 { 605 MoveToEx(m_drawData.m_memDc,m_drawData.m_drawRect.left, y,NULL) ; 606 LineTo(m_drawData.m_memDc, m_drawData.m_drawRect.right ,y); 607 } 608 DeleteObject(hPen) ; 609 } 610 /* 611 *将两字节数据送入绘图坐标缓冲,将每次送入的数据转换为合理的坐标 612 */ 613 void DataDealThread::InsertDataToDrawBuff(WORD data) 614 { 615 int i = 0 ; 616 static int inc_x = m_drawData.m_timeGap / m_drawData.m_aPiexTime ; 617 static int middle_y = m_drawData.m_drawRect.bottom ; 618 m_drawData.m_drawBuff.temp_y = middle_y - ( TO_REAL_DATA(data) / m_drawData.m_aPiexValue) ; 619 620 if(m_drawData.m_drawBuff.temp_x >= m_drawData.m_drawRect.right ) 621 { 622 m_drawData.m_drawBuff.temp_x -= inc_x ; 623 //左移坐标缓冲 624 memmove(m_drawData.m_drawBuff.coodinateBuff, m_drawData.m_drawBuff.coodinateBuff+1, sizeof(POINT) * ( m_drawData.m_drawBuff.m_validDataNum - 1)) ; 625 --m_drawData.m_drawBuff.m_validDataNum ; 626 627 for(i = 0; i< m_drawData.m_drawBuff.m_validDataNum ; ++ i) 628 { 629 m_drawData.m_drawBuff.coodinateBuff[i].x -= inc_x ; 630 } 631 } 632 m_drawData.m_drawBuff.coodinateBuff[m_drawData.m_drawBuff.m_validDataNum].x = m_drawData.m_drawBuff.temp_x; 633 m_drawData.m_drawBuff.coodinateBuff[m_drawData.m_drawBuff.m_validDataNum].y = m_drawData.m_drawBuff.temp_y; 634 ++m_drawData.m_drawBuff.m_validDataNum ; 635 m_drawData.m_drawBuff.temp_x += inc_x ; 636 637 } 638 /* 639 根据坐标缓冲进行波形绘制 640 */ 641 void DataDealThread::DrawByBuff() 642 { 643 int i ; 644 HPEN hPen ; 645 646 this->DrawBackGround() ; 647 this->DrawCodinate() ; 648 for(i = 0; i < m_drawData.m_drawBuff.m_validDataNum; ++ i ) 649 { 650 hPen = CreatePen(PS_SOLID, 1,RGB(255,0,0) ) ; 651 SelectObject(m_drawData.m_memDc,hPen) ; 652 if(i == 0) 653 { 654 MoveToEx(m_drawData.m_memDc, m_drawData.m_drawBuff.coodinateBuff[i].x,m_drawData.m_drawBuff.coodinateBuff[i].y 655 ,NULL) ; 656 continue ; 657 } 658 659 LineTo(m_drawData.m_memDc, m_drawData.m_drawBuff.coodinateBuff[i].x,m_drawData.m_drawBuff.coodinateBuff[i].y ) ; 660 661 662 DeleteObject(hPen) ; 663 664 } 665 666 #if 1 667 668 BitBlt(m_drawData.m_screenDc, m_drawData.m_drawRect.left, m_drawData.m_drawRect.top, 669 m_drawData.m_drawRect.right - m_drawData.m_drawRect.left, 670 m_drawData.m_drawRect.bottom - m_drawData.m_drawRect.top, 671 672 m_drawData.m_memDc, m_drawData.m_drawRect.left, m_drawData.m_drawRect.top,SRCCOPY ) ; 673 #endif 674 } 675 676 void DataDealThread::AddToDataList(WORD data) 677 { 678 //static unsigned long index = 0 ; 679 char buff[50] = "" ; 680 static LVITEM lvItem ; 681 memset(&lvItem, 0x00, sizeof(LVITEM) ) ; 682 //data = 0x294 ; 683 float x = TO_REAL_DATA(data) ; 684 lvItem.mask = LVIF_TEXT ; 685 lvItem.iItem = ++m_listData.dataNum ; 686 lvItem.cchTextMax = MAX_PATH ; 687 lvItem.iSubItem = 0;//m_listData.dataNum ; 688 sprintf(buff, "%f V",TO_REAL_DATA(data)) ; 689 lvItem.pszText = buff ; 690 SendMessage(m_listData.m_hDataList, LVM_INSERTITEM, 0, (LPARAM)&lvItem) ; 691 692 } 693 BOOL DataDealThread::SaveToFile(collect_t data) 694 { 695 FILE *saveStream = fopen(m_savePath.c_str(), "at+") ; 696 if(saveStream == NULL) 697 return FALSE; 698 fprintf(saveStream,"%f\n",TO_REAL_DATA(data)); 699 fclose(saveStream); 700 return TRUE ; 701 } 上位机主控程序制模块代码 703 #include <windows.h> 704 #include "resource.h" 705 #include "maindlg.h" 706 707 708 MainDlg mainDlg;//主程序对话框 709 BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM) ;//主对话框消息处理 710 int APIENTRY WinMain(HINSTANCE hInstance, 711 HINSTANCE hPrevInstance, 712 LPSTR lpCmdLine, 713 int nCmdShow) 714 { 715 LoadLibrary(TEXT("RICHED32.DLL") ) ; 716 InitCommonControls() ; 717 LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); 718 DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_DATA_GET), NULL, DlgProc) ; 719 720 return 0; 721 } 722 723 724 BOOL CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 725 { 726 727 static int times = 1; 728 #if 0 729 730 HDC hdc ; 731 PAINTSTRUCT ps ; 732 RECT rect ; 733 734 #endif 735 736 737 738 switch(message) 739 { 740 741 case WM_COMMAND: 742 switch(LOWORD(wParam)) 743 { 744 case IDC_BUTTON_BEGIN_CONNECT: 745 if( mainDlg.BeginConnect() )//开始连接 746 {//连接成功 747 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_CONNECT, FALSE) ; 748 mainDlg.PrintConnectState() ;//显示连接状态 749 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, TRUE) ; //开始采集开关可用 750 } 751 else 752 {//连接失败 753 mainDlg.PrintErr(TEXT("连接失败")) ; 754 } 755 break; 756 case IDC_BUTTON_BEGIN_COLLECT://开始采集 757 if(!mainDlg.IsConnected()) 758 {//如果未连接上 759 mainDlg.PrintErr(TEXT("未连接上下位机,无法进行采集")) ; 760 } 761 else 762 {//已连接上 763 mainDlg.GetDataFromDialog() ;//从对话框读取数据 764 if(mainDlg.CheckParameter()) 765 {//正确参数检查 766 767 if(mainDlg.IsAutoCollect()) 768 {//自动采集 769 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, FALSE) ; 770 mainDlg.EnableAChildCntl(IDC_BUTTON_STOP_COLLECT, TRUE) ; 771 } 772 else if(mainDlg.IsHandCollect()) 773 {//手动采集 774 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, FALSE) ; 775 mainDlg.EnableAChildCntl(IDC_BUTTON_STOP_COLLECT, FALSE) ; 776 } 777 else 778 {//采集方式未设定 779 mainDlg.PrintErr(TEXT("未设定采集方式")) ; 780 } 781 782 if(times ++ == 1) 783 { 784 mainDlg.BeginDataDealThread() ;//启动数据处理线程 785 } 786 787 mainDlg.BeginCollectThread() ;//开始采集线程 788 789 } 790 } 791 break; 792 793 case IDC_BUTTON_STOP_COLLECT://停止采集 794 if(mainDlg.IsCollecting()) 795 {//正在采集 796 //结束采集线程 797 mainDlg.EndCollectThread() ; 798 // mainDlg.EndDataDealThread() ; 799 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, TRUE) ; 800 // mainDlg.EnableAChildCntl(IDC_BUTTON_STOP_COLLECT, FALSE) ; 801 } 802 break; 803 804 805 case IDC_BUTTON_GET_SAVEPATH: 806 807 mainDlg.GetSaveFileName() ; 808 809 break ; 810 case IDC_RADIO_HAND_COLLECT: 811 mainDlg.SetCollectMode_HAND() ; 812 break; 813 case IDC_RADIO_AUTO_COLLECT: 814 mainDlg.SetCollectMode_AUTO() ; 815 break ; 816 case IDCANCEL: 817 mainDlg.EndDataDealThread() ; 818 Sleep(300) ; 819 EndDialog(hWnd, 0) ; 820 break ; 821 822 } 823 return 0 ; 824 case WM_END_COLLECT://采集线程结束 825 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, TRUE) ; 826 mainDlg.EnableAChildCntl(IDC_BUTTON_STOP_COLLECT, FALSE) ; 827 return 0 ; 828 case WM_PAINT: 829 mainDlg.SendPaintMessageToDealThread() ; 830 return 0 ; 831 832 case WM_INITDIALOG: 833 mainDlg.InitDlgHwnd(hWnd) ; 834 mainDlg.PrintConnectState() ; 835 mainDlg.DoSomeCntlInt() ; 836 mainDlg.DoSomeDataInit() ; 837 mainDlg.EnableAChildCntl(IDC_BUTTON_BEGIN_COLLECT, FALSE) ; 838 mainDlg.EnableAChildCntl(IDC_BUTTON_STOP_COLLECT, FALSE) ; 839 return 0 ; 840 841 } 842 843 return 0 ; 844 845 }