📄 pm5002k.cpp
字号:
// ------------------------------------------------- //
// PM5002K 用WINDRV //
// ------------------------------------------------- //
#include <AFXWIN.h>
#include <windows.h>
#include "pm5002k_lib.h"
#include "c:/windriver/include/status_strings.h"
#include "pm5002k.h"
#include <stdio.h> //后加的
//陈新华 增加一个全局消息处理窗口句柄 g_hWndMessage
HWND g_hWndMessage;
//增加一个一个应用程序接口函数用来设置消息处理窗口句柄 g_hWndMessage 定义如下
void SetMessageWindow(HWND hWnd)
{
g_hWndMessage = hWnd;
}
//此函数由用户在设置采集卡参数调用
unsigned long m_errorLevel = 0;//返回错误号
unsigned long m_nCountFrom = 1;//默认通道号或芯片号从1开始算起
long AIRangeArr[MAX_AI_RANGE+1][2] =
{{0,0},{0,5000},{0,10000},{1000,5000},{-2500,2500},{-5000,5000},{-10000,10000}};//模拟量输出范围
long AORangeArr[MAX_AO_RANGE+1][2] =
{{0,0},{0,5000},{0,10000},{1000,5000},{-2500,2500},{-5000,5000},{-10000,10000},{0,0},{0,0},{0,10000},{4000,20000}};//模拟量输出范围
PM5002K_HANDLE hPM5002K = NULL;
unsigned short getAOInitCode(long nValue,\
unsigned long MaxDAinitCode,\
unsigned long AORangeIndex)
{
//根据指定的AORangeIndex把nValue转换为0-4095或0-255之间的值
// AORangeIndex=0 对应的数组元素只是用于占位,AORangeIndex=0一定不能转换
if( AORangeIndex != 0 ) //不为原码方式,才转换,避免不必要的精度损失
{
long leftVal = AORangeArr[AORangeIndex][0];
long rightVal = AORangeArr[AORangeIndex][1];
if(nValue < leftVal) nValue = leftVal;
if(nValue > rightVal) nValue = rightVal;
long returnVal = (nValue - leftVal)*MaxDAinitCode/(rightVal-leftVal);
return (unsigned short)returnVal;
}
else
{
return (unsigned short)nValue;
}
}
unsigned long CheckAddr(unsigned long nAddr)
{
//检查地址范围,使地址在0x100--0x3F0之间
//用 nAddr = (nAddr | 0x100) & 0x3F0; 不行,对于0x2F0会有错
if( nAddr < 0x100 )
{
nAddr = 0x100;
m_errorLevel = ERR_PARAMETER_BASEADDR;
}
else if( nAddr > 0x3F0 )
{
nAddr = 0x3F0;
m_errorLevel = ERR_PARAMETER_BASEADDR;
}
return nAddr;
}
unsigned long _stdcall GetDll_LastErrNO()
{
//得到当前的错误状态号
return m_errorLevel;
}
void _stdcall ClearDll_LastErrNO()
{
//清除错误号
m_errorLevel = 0;
}
unsigned long GetULongXBit(unsigned long dataDoubleWord,\
unsigned long nBit)
{
//得到一个无符号长整型的某一位
return (dataDoubleWord >> nBit) & 0x1;
}
unsigned long SetULongXBit(unsigned long dataDoubleWord,\
unsigned long nBit,\
unsigned long nState)
{
//设置一个无符号长整型的某一位,并将设置的无符号长整型返回
unsigned long dataDoubleMask = 1;//必须设此变量,使它与dataDoubleWord匹配,
//也就是如果用unsigned long 与 unsigned char 作位操作,高位结果与期望值不符
if(nState != 0)
{
// dataDoubleMask = nState;
dataDoubleMask = dataDoubleMask << nBit;
return dataDoubleWord | dataDoubleMask;
}
else
{
// dataDoubleMask = 1;
dataDoubleMask = ~(dataDoubleMask << nBit);//“~”才是按位取反,用“!”不行,会使非0全部为0
return dataDoubleWord & dataDoubleMask;
}
}
void _stdcall SetCountFrom(unsigned long nCountFrom)
{
//设置芯片号或通道号,从0开始还是从1开始
m_nCountFrom = (nCountFrom!=0)?1:0;//只能为0或1
}
unsigned long _stdcall GetCountFrom()
{
//返回芯片号或通道号,从0开始还是从1开始
return m_nCountFrom;
}
long _stdcall OpenDevicePM()
{
//打开设备,启动WinDriver,主要是为了设置m_errorLevel
hPM5002K = NULL;
if (!PM5002K_Open(&hPM5002K))
{
m_errorLevel = ERR_WINDRV;
return -1;
}
m_errorLevel = ZT_SUCCESS;//没有调用可能改变m_errorLevel的函数,所以此处必须设置m_errorLevel
return 0;
}
long _stdcall CloseDevicePM()
{
//关闭设备,关闭WinDriver,主要是为了设置m_errorLevel
if( hPM5002K != NULL )//如果不为空才关闭
{
PM5002K_Close(hPM5002K);
m_errorLevel = ZT_SUCCESS;//没有调用可能改变m_errorLevel的函数,所以此处必须设置m_errorLevel
return 0;
}
else
{
m_errorLevel = ERR_WINDRV;
return -1;
}
}
double changeToAIRange(unsigned long ADInitCode,\
unsigned long MaxADinitCode,\
unsigned long AIRangeIndex)
{
//根据模拟量的极性及范围,返回结果
//转换结果形式,转换后的结果可正可负可为小数,所以用double
//注意用二维数组作形参时,第2维的维数不能省
//AIMode=0必须代表原码,否则会出错
AIRangeIndex&=0xf;
if( AIRangeIndex != 0 ) //不为原码方式,才转换,避免不必要的精度损失
{
double leftVal = AIRangeArr[AIRangeIndex][0];
double rightVal = AIRangeArr[AIRangeIndex][1];
double returnVal = (rightVal - leftVal)*ADInitCode/MaxADinitCode + leftVal;
return returnVal;
}
else
{
return ADInitCode;
}
}
unsigned char _stdcall ReadB(unsigned long nAddr,\
unsigned long nOffset)
{
//8位读
unsigned char GetVal=0;
GetVal = PM5002K_ReadByte(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR);
m_errorLevel = ZT_SUCCESS;//函数成功调用
return (unsigned char)GetVal;
}
unsigned short _stdcall ReadW(unsigned long nAddr,\
unsigned long nOffset)
{
//16位读
unsigned short GetVal=0;
GetVal = PM5002K_ReadWord(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR);
m_errorLevel = ZT_SUCCESS;//函数成功调用
return (unsigned short)GetVal;
}
unsigned long _stdcall ReadD(unsigned long nAddr,\
unsigned long nOffset)
{
//32位读
unsigned long GetVal=0;
GetVal = PM5002K_ReadDword(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR);
m_errorLevel = ZT_SUCCESS;//函数成功调用
return (unsigned long)GetVal;
}
void _stdcall WriteB(unsigned long nAddr,\
unsigned long nOffset,\
unsigned long dataByte)
{
//8位写
PM5002K_WriteByte(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR, (unsigned char)dataByte);
m_errorLevel = ZT_SUCCESS;//函数成功调用
}
void _stdcall WriteW(unsigned long nAddr,\
unsigned long nOffset,\
unsigned long dataWord)
{
//16位写
PM5002K_WriteWord(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR, (unsigned short)dataWord);
m_errorLevel = ZT_SUCCESS;//函数成功调用
}
void _stdcall WriteD(unsigned long nAddr,\
unsigned long nOffset,\
unsigned long dataDoubleWord)
{
//32位写
PM5002K_WriteDword(hPM5002K, 0, nAddr+nOffset-PM5002K_IORange0_ADDR, dataDoubleWord);
m_errorLevel = ZT_SUCCESS;//函数成功调用
}
///////////////////////////中断中的回调函数//////////////////////////////////
void _stdcall PM5002K_Interrupt5HandlerRoutine(PM5002K_HANDLE hPM5002K,\
PM5002K_Interrupt5_RESULT *intResult,\
long *pResultArr,\
int inttimein)
{
int i;
int j;
long flag_sfifo;
// CString timeend;
//进入中断内存方式读4096数,读出数据个数是4096的倍数
inttimein=m_inttime;
if((ReadW(0x100,10)&0x2000)==0){ //判断是否半满
flag_sfifo=m_intflag*4096; //m_intflag是进入中断的次数,*4096后得出本次中断中储存数据的位置
//例:m_intflag=0时,储存在0~4095;m_intflag=1时,储存在(0~4095)+4096=4096~8191;
PM5002K_ReadHFifo(hPM5002K,0,2,m_sfifo+flag_sfifo,8192); //内存方式读取一次中断的数据,4096个
m_intflag++; //中断次数+1
// *m_eff++=m_intflag; //试验中断次数
}
//当最后一次中断结束后读取fifo众剩余的数据,加上前面的数据就是完整采样过程
if(m_intflag==inttimein){ //inttimein是中断次数,需要计算后用ZT_PM518INTTIMESET写入
//通过判断fifo非空采集剩余数据
j=0; //?? no use
for(i=0;i<4096;i++){ //由于此时fifo中的剩余数据<4096个,故循环4096次采样
if((ReadW(0x100,10)&0x4000)!=0) //判断fifo是否非空
// *m_eff++=ReadW( 0x100, 2); //无法让指针回到原点
*(m_eff+(j++))=ReadW( 0x100, 2);
}
*(m_eff+4095)=j;
//通过内存方式读取4096数
// PM5002K_ReadHFifo(hPM5002K,0,2,m_eff,8192);
//纪录采集结束时间测试采样的实时性
//自定义系统消息请在这里添加
//陈新华
//发送自定义消息給给指定的窗口句柄 g_hWndMessage
::SendMessage(g_hWndMessage,WM_SAMPLE_FINISH, 0,0);//WM_SAMPLE_FINISH 即为自定义的消息
//在此之前要先调用接口函数 SetMessageWindow 设置 g_hWndMessage
//陈新华
SYSTEMTIME sys;
GetLocalTime( &sys );
m_tendS=sys.wSecond;
m_tendMS=sys.wMilliseconds;
// timeend.Format("%d秒%d毫秒",m_tendS,m_tendMS);
// AfxMessageBox(timeend);
m_intflag=0; //一轮采集结束,中断纪录归0
}
}
//////////////////////////////成功的SFIFO///////////////////////////////
/*
void _stdcall PM5002K_Interrupt5HandlerRoutine(PM5002K_HANDLE hPM5002K,\
PM5002K_Interrupt5_RESULT *intResult,\
long *pResultArr)
{
int i,j;
intflag=(UINT)intResult->dwCounter;
if((intflag>intflag_sec)&&(intflag<10)){
intflag_sec=intflag;
for(i=0;i<4095;i++)pResultArr[i]=0;
for(i=0;i<4095;i++){
pResultArr[i]=ReadW( 0x100, 2); //可以采到,传到m_sdata里
m_sdata[i]=pResultArr[i];
m_sfifo[i+intflag*4095]=m_sdata[i];
}
}
}
*/
///////////////////////////////简化的SFIFO//////////////////////////////////////
/*
void _stdcall PM5002K_Interrupt5HandlerRoutine(PM5002K_HANDLE hPM5002K,\
PM5002K_Interrupt5_RESULT *intResult,\
long *pResultArr,\
int inttimein)
{
int i;
long flag_sfifo;
intflag=(UINT)intResult->dwCounter;
inttimein=m_inttime;
flag_sfifo=intflag*4095;
if((intflag>intflag_sec)&&(intflag<inttimein)){
intflag_sec=intflag;
for(i=0;i<4095;i++)
m_sfifo[i+flag_sfifo]=ReadW( 0x100, 2);
}
}
*/
////////////////////////////////////////////////////////////////////////////////
unsigned long _stdcall intenable(unsigned long nAddr)
{
//使能中断,返回值0-禁止中断 1-使能中断 -1-中断开启失败
int intena;
if (PM5002K_Interrupt5IsEnabled(hPM5002K))
{
PM5002K_Interrupt5Disable(hPM5002K);
intena=0;
}
else
{
intena=1;
if (!PM5002K_Interrupt5Enable(hPM5002K, PM5002K_Interrupt5HandlerRoutine))
intena=-1;
}
return intena;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -