📄 adthread.cpp
字号:
#include "stdAfx.h"
#include "Sys.h"
#include "ADThread.h"
#define FIFO_HALF_LENGTH 4096 // FIFO半满长度 中断使用
#define FIFO_FULL_LENGTH FIFO_HALF_LENGTH*2 // FIFO全满长度
extern SHORT ADBuffer[MAX_SEGMENT][16384]; // 缓冲队列
extern int ReadIndex; // AD数据采集线程当前缓冲区索引号
extern HANDLE hFileObject;
extern BOOL bNewSegmentData[MAX_SEGMENT]; // 用于确定当前段数据是否为最新数据
extern HANDLE hEvent; // 采集线程与绘制线程的同步信号
extern HANDLE hExitEvent;
extern PCI2006_PARA_AD ADPara;
extern BOOL bDeviceADRun;
extern BOOL bCheckOverflow;
extern BOOL bCreateDevice;
extern int nProcessMode;
extern ULONGLONG FileLenghtWords;
CWinThread* m_ReadThread;
//-------------------------------------------------------------------------------------------------------------------------------------
UINT ReadDataThread_NotEmpty(PVOID hWnd);//非空方式读取数据线程
BOOL StartDeviceAD_NotEmpty(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
m_ReadThread=AfxBeginThread(ReadDataThread_NotEmpty,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
m_ReadThread->m_bAutoDelete=false;
if(!PCI2006_InitDeviceProAD(hDevice, &ADPara))
{
AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
return FALSE;
}
bDeviceADRun=TRUE; // 告之采集线程可以工作了
m_ReadThread->ResumeThread(); // 启动采集线程ReadDataThread_NotEmpty
return TRUE;
}
UINT ReadDataThread_NotEmpty(PVOID hWnd) // 读数据线程
{
CSysApp *pApp=(CSysApp *)AfxGetApp();
CADDoc* pDoc=pApp->m_pADDoc;
// 在线程中取得视图指针
ULONG Wrote8KWCounter=0;
ULONG WroteMB=0;
BOOL bFirst=TRUE;
pDoc->m_Wrote8KWCounter=0;
pDoc->m_WroteMB=0;
// 复位段索引号
ReadIndex = 0;
int nChannelCount,nRemainder;
nChannelCount = ADPara.ChannelCount ;
nRemainder = 8192 % nChannelCount;
ReadSizeWords = 8192 - nRemainder;
for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
{
bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
}
CString str1;
ULONG ReadCount, dwErrorCode;
PCI2006_StartDeviceProAD(pApp->m_hDevice); // 初始化后,启动设备
while(bDeviceADRun) // 循环采集AD数据
{
ReadCount=PCI2006_ReadDeviceProAD_NotEmpty(pApp->m_hDevice, ADBuffer[ReadIndex], ReadSizeWords, bCheckOverflow);
if(ReadCount==ReadSizeWords) // 如果返回数据量等于请求量,则处理数据
{
/*
if(nProcessMode==3) // 数据存盘
{
if(WroteMB>=(pDoc->m_RemainMB-2))
{
AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
return FALSE;
}
PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadSizeWords*2); // 将8192*2个字的数据存放在硬盘上
FileLenghtWords+=ReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条
}*/
}
else // 如果返回数据量不等于请求量,则分析原因,再处理数据
{
dwErrorCode = GetLastError();
switch(dwErrorCode)
{
case 0xE1000000:
AfxMessageBox("FIFO溢出, 数据丢失,请注意溢出前返回的数据量...",MB_ICONERROR);
str1.Format("溢出前所返回的数据长度为 %d", ReadCount);
AfxMessageBox(str1,MB_ICONSTOP);
if(nProcessMode==3) // 数据存盘
{
PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadCount*2); // 将最后一次数据写入磁盘文件
}
goto ExitReadThread;
case 0xE2000000:
//AfxMessageBox("用户故意停止,请注意最一次读操作返回的数据点数...",MB_ICONSTOP);
//str1.Format("中断前所返回的数据长度为 %d", ReadCount);
//AfxMessageBox(str1,MB_ICONSTOP);
if(nProcessMode==3) // 数据存盘
{
PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadCount*2); // 将最后一次数据写入磁盘文件
}
goto ExitReadThread;
default:
AfxMessageBox("读数据未知错误...",MB_ICONERROR);
goto ExitReadThread;
}
goto ExitReadThread;
}
// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
if(bNewSegmentData[ReadIndex]==TRUE)
{
AfxMessageBox("缓冲区溢出...", MB_ICONERROR);
goto ExitReadThread;
}
bNewSegmentData[ReadIndex] = TRUE;
SetEvent(hEvent);
ReadIndex++;
if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
}// 线程循环取样
ExitReadThread:
SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
Beep(3000, 1); // 响铃通知用户,线程已终止
return TRUE;
}
BOOL StopDeviceAD_NotEmpty(HANDLE m_hDevice)
{
bCreateDevice = FALSE;
bDeviceADRun = FALSE;
if(m_ReadThread)
{
WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE); // 等待子线程停止
}
if(m_ReadThread)
{
m_ReadThread->ExitInstance();
m_ReadThread=NULL;
}
if(!PCI2006_ReleaseDeviceProAD(m_hDevice))
{
AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
}
return TRUE;
}
//-------------------------------------------------------------------------------------------------------------------------------------
UINT ReadDataThread_Half(PVOID hWnd);//半满方式读取数据线程
BOOL StartDeviceAD_Half(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
m_ReadThread=AfxBeginThread(ReadDataThread_Half,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
m_ReadThread->m_bAutoDelete=false;
if(!PCI2006_InitDeviceProAD(hDevice, &ADPara))
{
AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
return FALSE;
}
bDeviceADRun=TRUE; // 告之采集线程可以工作了
m_ReadThread->ResumeThread(); // 启动采集线程ReadThread
return TRUE;
}
UINT ReadDataThread_Half(PVOID hWnd) // 读数据线程
{
CSysApp *pApp=(CSysApp *)AfxGetApp();
CADDoc* pDoc=pApp->m_pADDoc;
// 在线程中取得视图指针
BOOL bFirst=TRUE;
ULONG Wrote8KWCounter=0;
ULONG WroteMB=0;
pDoc->m_Wrote8KWCounter=0;
pDoc->m_WroteMB=0;
// 复位段索引号
ReadIndex = 0;
int nChannelCount,nRemainder;
nChannelCount = ADPara.ChannelCount ;
nRemainder = FIFO_HALF_LENGTH % nChannelCount;
ReadSizeWords = FIFO_HALF_LENGTH - nRemainder;//计算读取点数 半满读取 一次读取最佳点数位 FIFO/2 个点
for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
{
bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
}
CString str1;
ULONG ReadCount;
PCI2006_StartDeviceProAD(pApp->m_hDevice); // 初始化后,启动设备
BOOL bNotEmpty,bHalf,bOverflow;
while(bDeviceADRun) // 循环采集AD数据
{
while(bDeviceADRun) //
{
PCI2006_GetDevStatusProAD(pApp->m_hDevice,&bNotEmpty,&bHalf,&bOverflow);//取得标志
if(!bHalf)
{
PCI2006_DelayTime(pApp->m_hDevice, 1); // 延时100纳秒(如果在98下,则延时1毫秒)
}
else
break;
}
ReadCount=PCI2006_ReadDeviceProAD_Half(pApp->m_hDevice, ADBuffer[ReadIndex], ReadSizeWords);
if(ReadCount) // 如果返回数据量等于请求量,则处理数据
{
/*
if(nProcessMode==3) // 数据存盘
{
if(WroteMB>=(pDoc->m_RemainMB-2))
{
AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
return FALSE;
}
PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadSizeWords*2); // 将8192*2个字的数据存放在硬盘上
FileLenghtWords+=ReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条
}*/
}
else // 如果返回数据量不等于请求量,则分析原因,再处理数据
{
AfxMessageBox("读取数据错误");
goto ExitReadThread;
}
// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
if(bNewSegmentData[ReadIndex]==TRUE)
{
AfxMessageBox("缓冲区溢出...", MB_ICONERROR);
goto ExitReadThread;
}
bNewSegmentData[ReadIndex] = TRUE;
// 建议:不要在数据采集线程中操作窗口,因为窗口操作(如放大、缩小、重绘)会花掉
// CPU很多时间,处理不当,会引起采集线程的严重堵塞,使数据被丢掉。详细情况请参考
// 软件说明书,在那里会告诉您很多解决方案。
SetEvent(hEvent);
ReadIndex++;
if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
}// 线程循环取样
ExitReadThread:
SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
Beep(3000, 1); // 响铃通知用户,线程已终止
return TRUE;
}
BOOL StopDeviceAD_Half(HANDLE m_hDevice)
{
bCreateDevice = FALSE;
bDeviceADRun = FALSE;
if(m_ReadThread)
{
WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE); // 等待子线程停止
}
if(m_ReadThread)
{
m_ReadThread->ExitInstance();
m_ReadThread=NULL;
}
if(!PCI2006_ReleaseDeviceProAD(m_hDevice))
{
AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
}
return TRUE;
}
//-------------------------------------------------------------------------------------------------------------------------------------
int m_IntReadSizeWords;
UINT ReadDataThread_Int(PVOID hWnd);
HANDLE hReadEventInt;
BOOL StartDeviceAD_Int(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
int nChannelCount,nRemainder;
nChannelCount = ADPara.ChannelCount ;
nRemainder = FIFO_HALF_LENGTH % nChannelCount;
m_IntReadSizeWords = FIFO_HALF_LENGTH - nRemainder;//计算读取点数 半满读取 一次读取最佳点数位 FIFO/2 个点
m_ReadThread=AfxBeginThread(ReadDataThread_Int,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
m_ReadThread->m_bAutoDelete=false;
hReadEventInt=PCI2006_CreateSystemEvent();
if(!PCI2006_InitDeviceIntAD(hDevice,hReadEventInt,m_IntReadSizeWords,&ADPara))
{
AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
return FALSE;
}
bDeviceADRun=TRUE; // 告之采集线程可以工作了
m_ReadThread->ResumeThread(); // 启动采集线程ReadThread
return TRUE;
}
UINT ReadDataThread_Int(PVOID hWnd) // 读数据线程
{
CSysApp *pApp=(CSysApp *)AfxGetApp();
CADDoc* pDoc=pApp->m_pADDoc;
// 复位段索引号
ReadIndex = 0;
ReadSizeWords=FIFO_HALF_LENGTH;
for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
{
bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
}
ULONG WroteMB=0;
CString str1;
ULONG Remaining;
PCI2006_StartDeviceIntAD(pApp->m_hDevice); // 初始化后,启动设备
while(bDeviceADRun) // 循环采集AD数据
{
do{
if(!bDeviceADRun) goto ExitReadThread;
}while(WaitForSingleObject (hReadEventInt, 100)!=WAIT_OBJECT_0);
do
{
Remaining=PCI2006_ReadDeviceIntAD(pApp->m_hDevice, ADBuffer[ReadIndex], m_IntReadSizeWords);
if(bNewSegmentData[ReadIndex]==TRUE)
{
AfxMessageBox("二级缓冲区溢出...", MB_ICONERROR);
goto ExitReadThread;
}
if(Remaining!=0xe1000000)
{
/*
if(nProcessMode==3) // 数据存盘
{
if(WroteMB>=(pDoc->m_RemainMB-2))
{
AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
goto ExitReadThread;
}
PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], m_IntReadSizeWords*2);
FileLenghtWords+=m_IntReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条
}*/
bNewSegmentData[ReadIndex] = TRUE;
// 建议:不要在数据采集线程中操作窗口,因为窗口操作(如放大、缩小、重绘)会花掉
// CPU很多时间,处理不当,会引起采集线程的严重堵塞,使数据被丢掉。详细情况请参考
// 软件说明书,在那里会告诉您很多解决方案。
SetEvent(hEvent);// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
ReadIndex++;
if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
}
else
{
// 如果您需要容错处理,防止缓冲区溢出,数据丢失,请加入下列代码
AfxMessageBox("系统很忙,整个一级缓冲区已满,建议您在数据采集时,关闭所有不必要的应用程序,或缩小波形窗口等...",MB_ICONSTOP);
goto ExitReadThread;
}
}while(Remaining&&bDeviceADRun);
}// 线程循环取样
ExitReadThread:
SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
Beep(3000, 1); // 响铃通知用户,线程已终止
return TRUE;
}
BOOL StopDeviceAD_Int(HANDLE m_hDevice)
{
bCreateDevice = FALSE;
bDeviceADRun = FALSE;
if(m_ReadThread)
{
WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE); // 等待子线程停止
}
if(m_ReadThread)
{
m_ReadThread->ExitInstance();
m_ReadThread=NULL;
}
if(!PCI2006_ReleaseDeviceIntAD(m_hDevice))
{
AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
}
PCI2006_ReleaseSystemEvent(hReadEventInt);//中断读数据消息
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -