// XDemo51: A/I from I-8017h // Compiler: BC++ 3.1 // Compile mode: large // Project: user.c // v7000.c // vModbus.c [after XS8_3002] // ..\LIB\8000E.Lib // ..\LIB\TCPIPL.Lib // ..\LIB\XS8_NNNN.Lib, with NNNN being the lib file's version. // ..\Lib\8017HL.Lib // I-8017H is a high speed analog input madule. This demo show how to // read data from I-8017H. We use two TCP port: // port 10000: for receiving commands from PC. // port 9999: for sending data to PC. // User can use client1, client4, ***GetString to test this demo. // Refer to following the location: // ftp://ftp.icpdas.com.tw/pub/cd/8000cd/napdos/8000/843x883x/tcp/xserver/client/common/vb5/ // This demo provides 5 mode to read the data: // 1): 1 channel A/D convert to Float // (1 sampling point) // 2): 1 channel A/D convert to HEX // (1 sampleing point) // 3): 1 channels polling mode A/D convert to Hex // (multi sampling points) // 4): 1 channel interrupt mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 50K Hz Max.) // 5): 8 channels interrupt-scan mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 10K Hz Max.) // To use I-8017H, you need 2 extra files(8017h.h, 8017HL.Lib). The original // 2 files are located in directory 8000\841x881x\master\I8017H\[Bc|MSC]. // Hardware: 8000E + I-8017H // Refer 8000\843x883x\TCP\Doc\[Big5|Eng|Gb2312]\Vxcomm.htm // 8000\843x883x\TCP\Xserver\Xserver.htm // 8000\843x883x\TCP\Xserver\Function.htm // to get more information. // // [22/Feb/2002] by Kevin // // [08/Nov/2002] by Kevin // Correct comment of function ARRAY_HEX_CALIBRATION and Get_AD_HValue(Mode2). #include #include #include #include "..\lib\module.h" #include "..\lib\8017h.h" // Input gain of 8017h const Gain10=0; //+- 10 V const Gain5=1; //+- 5 V const Gain25=2; //+- 2.5 V const Gain125=3; //+-1.25 V const Gain20=4; //+- 20 mA // Input mode of 8017h const Polling=0; const Interupt=1; int iReading; //For reading I-8017H. iReading<>0 ==> in reading int DEBUG=1; //If DEBUG<>0, print some debug message to PC monitor int far iDataBuf[8192]; // To store 8K sampling points in Hex number. float far fDataBuf[8192]; // To store 8K sampling points in float number. char far sDataBuf[32767]; // 8K points (4 bytes/point for float) // 16K points(2 bytes/point for integer) TCPREADDATA P9999={0,0,0,sDataBuf}; // The last parameter declare the bufer size. int iSlot=0,iChannel=0,iPoint=1024,iGain=0; unsigned int iFrequency=50000; void Mode1(int iSlot,int iChannel,int iGain); void Mode2(int iSlot,int iChannel,int iGain); void Mode3(int iSlot,int iChannel,int iPoint,int iGain); void Mode4(int iSlot,int iChannel,int iPoint,unsigned int iFrequency,int iGain); void Mode5(int iSlot,int iPoint,unsigned int iFrequency,int iGain); void UserCount(void) { } void UserEnd(void) { Print("Call UserEnd().\r\n"); StopUserTimerFun(); } void UserInit(void) { /* In this function, user CAN: 1. initialize user's program. 2. set time interval for calling UserCount(). 3. set initial value of I/O or variables for UserLoopFun(). 4. set initial value of I/O or variables for another functions. 5. change the default TCP PORT 10000/9999/502 to others value. [after XS8_3004.lib] Syntax: Port10000=newport_10000; for calling UserCmd (user.c) Port9999=newport_9999; for calling VcomCmd7000 (v7000.c) Port502=newport_502; for calling VcomCmdModbus (vModbus.c) [after XS8_3002.lib] PortUser=newport_User; for calling VcomCmdUser (user.c) [after XS8_3005.lib] Default port value: Port10000=10000; Port9999=9999; Port502=502; PortUser=0; If the port value is 0, Xserver will not listen that port. That means the port will be disable. Please refer to XDemo09 & XDemo11 for example code */ int iTotalSlot,i; InitLib(); // To use [MiniOS7 for 8000 new], you need call this function // at begin of c program. // XS8_nnnn.Lib has not add this function to it's kernel. // So, you need call that in UserInit. // To know what difference between original MiniOS7 and new MiniOS7, // please refer CD:\Napdos\MiniOS7\8000new\8000-new_eng.txt // 8000-new_big5.txt // 8000-new_gb2312.txt // [26,Oct,2002] by Kevin //InstallCom1(115200,8,0,1); SetBaudrate(1,115200L); //TO use I-8017H, you must first initial the module. iTotalSlot=GetNumberOfSlot(); for(i=0;i (Float)"); break; case '2': sscanf(Cmd+1,"%d %d %d",&iSlot,&iChannel,&iGain); Set_8017H_LED(iSlot,2); //Turns on the 2nd LED of the 8017H. if(DEBUG) { printCom1("\n\rUse Mode2\n\r"); printCom1("Slot%d Channel%d Gain:%d\n\r",iSlot,iChannel,iGain); } RefreshWDT(); Mode2(iSlot,iChannel,iGain); strcpy(Response,"A/D ==> (Hex)"); break; case '3': sscanf(Cmd+1,"%d %d %d %d",&iSlot,&iChannel,&iPoint,&iGain); Set_8017H_LED(iSlot,4); //Turns on the 3th LED of the 8017H. if(DEBUG) { printCom1("\n\rUse Mode3\n\r"); printCom1("Slot%d Channel%d Point=%d Gain:%d\n\r",iSlot,iChannel,iPoint,iGain); } RefreshWDT(); Mode3(iSlot,iChannel,iPoint,iGain); strcpy(Response,"Polling"); break; case '4': sscanf(Cmd+1,"%d %d %d %u %d",&iSlot,&iChannel,&iPoint,&iFrequency,&iGain); Set_8017H_LED(iSlot,8); //Turns on the 4th LED of the 8017H. if(DEBUG) { printCom1("\n\rUse Mode4\n\r"); printCom1("Slot%d Channel%d Point=%d Frequency=%d Hz Gain:%d\n\r",iSlot,iChannel,iPoint,iFrequency,iGain); } RefreshWDT(); Mode4(iSlot,iChannel,iPoint,iFrequency,iGain); strcpy(Response,"Interrupt"); break; case '5': sscanf(Cmd+1,"%d %d %u %d",&iSlot,&iPoint,&iFrequency,&iGain); Set_8017H_LED(iSlot,16); //Turns on the 5th LED of the 8017H. if(DEBUG) { printCom1("\n\rUse Mode5\n\r"); printCom1("Slot%d Point=%d Frequency=%d Hz Gain:%d\n\r",iSlot,iPoint,iFrequency,iGain); } RefreshWDT(); Mode5(iSlot,iPoint,iFrequency,iGain); strcpy(Response,"Interrupt scan"); break; } return 1; } return 1; // return OK } int VcomUserBinaryCmd(TCPREADDATA *p) { VcomSendSocket(p->Socket,"User-defined command(23)",24); // return 24 bytes. return 1; // any value will be accept } int VcomCmdUser(TCPREADDATA *p) { /* VCOM3005 (Feb,22,2002) or later will call this function for PortUser. When packets received by TCP PORT PortUser(user defined) of 7188E/8000E, Xserver will call this function. user can get the following message: p->ReadUartChar : the buffer store the command data. Maximum length of p->ReadUartChar is 32767 bytes. p->Length : the command data length. p->Socket : the socket number that receive the command, that is when the user function wants return message to the client, just use the socket to send data. usage: VcomSendSocket(p->Socket,pdata,datalength); */ /* here just send back the command to the client. */ VcomSendSocket(p->Socket,p->ReadUartChar,p->Length); return 1; /* any value will be accept */ } void ARRAY_HEX_CALIBRATION(int *iData,int iSlot,int iGain,int iPoint) { // *iData: int array pointer to calibrate AI value. //This function is designed for function I8017H_AD_POLLING, // I8017H_AD_INT,I8017H_AD_INT_SCAN. //To get best A/D sampling performance, these 3 functions don't // calibrate values during sampling process. // So, you need to call ARRAY_HEX_CALIBRATION to get exact values. //After calibration, all values will between -32768 ~ +32767. long lData; int i; // The first point of AI is not correct. // You msut throw it away. // Thus, the index is from 1 to iPoint. for(i=1;i<=iPoint;i++) { lData=iData[i]>>2; lData=lData*Gain8017H[iSlot][iGain]; //Gain8017H is declared in 8017h.h lData=lData>>13; lData=(lData+Offset8017H[iSlot][iGain]); //Offset8017H is declared in 8017h.h if(lData>32767) lData=32767; else if(lData<-32768) lData=-32768; iData[i]=lData; } } // [[[ A/D mode of 8017h ]]] // // 1): 1 channel A/D convert to Float // (1 sampling point) // 2): 1 channel A/D convert to HEX // (1 sampleing point) // 3): 1 channels polling mode A/D convert to Hex // (multi sampling points) // 4): 1 channel interrupt mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 50K Hz Max.) // 5): 8 channels interrupt-scan mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 10K Hz Max.) void Mode1(int iSlot,int iChannel,int iGain) { // 1 channel A/D convert to Float // (1 sampling point) // // iGain: 0 ==> for +-10.0 V // 1 ==> for +- 5.0 V // 2 ==> for +- 2.5 V // 3 ==> for +- 1.25V // 4 ==> for +-20.0 mA float fValue; Set_8017H_Channel_Gain_Mode(iSlot,iChannel,iGain,Polling); if(iGain!=Gain20) fValue=Get_AD_FValue(iGain); //For valtage input. if(DEBUG) printCom1("Value=%7.4f\n\r",fValue); sprintf(P9999.ReadUartChar,"Value= %+7.4f\n\r",fValue); P9999.Length=15; VcomSendSocket(P9999.Socket,P9999.ReadUartChar,P9999.Length); } void Mode2(int iSlot,int iChannel,int iGain) { // 1 channel A/D convert to HEX // (1 sampleing point) // // iGain: 0 ==> for +-10.0 V // 1 ==> for +- 5.0 V // 2 ==> for +- 2.5 V int iValue; // 3 ==> for +- 1.25V // 4 ==> for +-20.0 mA int iValue; Set_8017H_Channel_Gain_Mode(iSlot,iChannel,iGain,Polling); iValue=Get_AD_HValue(); //reads 14-bit value. // 8017H is 14-bit resolution. It uses 14-bit 2's format to store values. // When A/D value between 0000 ~ 1FFF ==> value >=0 // between 2000 ~ 3FFF ==> value <0 // Algorithm to convert 14-bit integer (iValue) to float (fValue) // fValue=iValue/8192*span ,fValue>=0, iValue between 0000~1FFF // fValue=(8192-iValue)/8192*span ,fValue<0, iValue between 2000~3FFF if(DEBUG) printCom1("Value=%04X(Hex)\n\r",iValue); sprintf(P9999.ReadUartChar,"Value=%04X(Hex)",iValue); P9999.Length=15; VcomSendSocket(P9999.Socket,P9999.ReadUartChar,P9999.Length); } void Mode3(int iSlot,int iChannel,int iPoint,int iGain) { // 1 channels polling mode A/D convert to Hex // (multi sampling points) // // iGain: 0 ==> for +-10.0 V // 1 ==> for +- 5.0 V // 2 ==> for +- 2.5 V int iValue; // 3 ==> for +- 1.25V // 4 ==> for +-20.0 mA unsigned long st; iReading=1; //iReading is a global variable. st=*TimeTicks; I8017H_AD_POLLING(iSlot,iChannel,iGain,iPoint,iDataBuf); //iDataBuf is a global integer array. if(DEBUG) printCom1("Polling takes %lu ms\n\r",*TimeTicks-st); //The function I8017H_AD_POLLING just reads the values, it doesn't //calibrat these values. You must call the function ARRAY_HEX_CALIBRATION //to get the exact values. st=*TimeTicks; ARRAY_HEX_CALIBRATION(iDataBuf,iSlot,iGain,iPoint); //iDataBuf is a global integer array. //To convert the integer value to a float value: //============================= // fValue=iVlaue/32768*fGain; //============================= //The fGain is: //fGain=10.0; ==>+-10.0V //fGain=5.0; ==>+- 5.0V //fGain=2.5; ==>+- 2.5V //fGain=1.25; ==>+-1.25V //fGain=2.5/125; ==>+-20.0mA if(DEBUG) printCom1("CIBRATION takes %lu ms\n\r",*TimeTicks-st); st=*TimeTicks; VcomSendSocket(P9999.Socket,iDataBuf,iPoint*2); //iDataBuf is a global integer array. if(DEBUG) printCom1("Sending takes %lu ms\n\r",*TimeTicks-st); iReading=0; } void Mode4(int iSlot,int iChannel,int iPoint,unsigned int iFrequency,int iGain) { // 1 channel interrupt mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 50K Hz Max.) // // iFrequency: 200~50000(unit: Hz). // iGain: 0 ==> for +-10.0 V // 1 ==> for +- 5.0 V // 2 ==> for +- 2.5 V int iValue; // 3 ==> for +- 1.25V // 4 ==> for +-20.0 mA int iCount,i,j; unsigned long st; iReading=1; //iReading is a global variable. st=*TimeTicks; iCount=iPoint; j=0; while(iCount>0) { // The function I8017H_AD_INT can deal 8K points maximum. // If you want to read more than 8K points, you must call // I8017H_AD_INT many times. if(iCount>=8192) { i=8192; iCount=iCount-8192; } else { i=iCount; iCount=0; } I8017H_AD_INT(iSlot,iChannel,iGain,i,iFrequency,iDataBuf+j); //iDataBuf is a global integer array. j+=i; RefreshWDT(); } if(DEBUG) printCom1("INT takes %lu ms\n\r",*TimeTicks-st); //The function I8017H_AD_INT just reads the values, it doesn't //calibrat these values. You must call the function ARRAY_HEX_CALIBRATION //to get the exact values. st=*TimeTicks; ARRAY_HEX_CALIBRATION(iDataBuf,iSlot,iGain,iPoint); //iDataBuf is a global integer array. //To convert the integer value to a float value: //============================= // fValue=iVlaue/32768*fGain; //============================= //The fGain is: //fGain=10.0; ==>+-10.0V //fGain=5.0; ==>+- 5.0V //fGain=2.5; ==>+- 2.5V //fGain=1.25; ==>+-1.25V //fGain=2.5/125; ==>+-20.0mA if(DEBUG) printCom1("CIBRATION takes %lu ms\n\r",*TimeTicks-st); RefreshWDT(); st=*TimeTicks; VcomSendSocket(P9999.Socket,iDataBuf,iPoint*2); //iDataBuf is a global integer array. if(DEBUG) printCom1("Sending takes %lu ms\n\r",*TimeTicks-st); iReading=0; } void Mode5(int iSlot,int iPoint,unsigned int iFrequency,int iGain) { // 8 channels interrupt-scan mode A/D convert to Hex // (multi sampling points) // (Sampling rate: 10K Hz Max.) // // -> Ch0 -> Ch1 -> Ch2 -> Ch3 -> Ch4 ->Ch5 -> Ch6 -> Ch7 ->- // |_________________________________________________________| // // iFrequency: 200~10000 (unit: Hz). // iGain: 0 ==> for +-10.0 V // 1 ==> for +- 5.0 V // 2 ==> for +- 2.5 V int iValue; // 3 ==> for +- 1.25V // 4 ==> for +-20.0 mA int iCount,i,j; unsigned long st; iReading=1; //iReading is a global variable. st=*TimeTicks; iCount=iPoint; j=0; while(iCount>0) { // The function I8017H_AD_INT_SCAN can deal 8K points maximum. // If you want to read more than 8K points, you must call // I8017H_AD_INT_SCAN many times. if(iCount>=8192) { i=8192; iCount=iCount-8192; } else { i=iCount; iCount=0; } I8017H_AD_INT_SCAN(iSlot,iGain,i,iFrequency,iDataBuf+j); j+=8192; RefreshWDT(); } if(DEBUG) printCom1("INT_SCAN takes %lu ms\n\r",*TimeTicks-st); //The function I8017H_AD_INT just reads the values, it doesn't //calibrat these values. You must call the function ARRAY_HEX_CALIBRATION //to get the exact values. st=*TimeTicks; ARRAY_HEX_CALIBRATION(iDataBuf,iSlot,iGain,iPoint); //To convert the integer value to a float value: //============================= // fValue=iVlaue/32768*fGain; //============================= //The fGain is: //fGain=10.0; ==>+-10.0V //fGain=5.0; ==>+- 5.0V //fGain=2.5; ==>+- 2.5V //fGain=1.25; ==>+-1.25V //fGain=2.5/125; ==>+-20.0mA if(DEBUG) printCom1("CIBRATION takes %lu ms\n\r",*TimeTicks-st); RefreshWDT(); st=*TimeTicks; VcomSendSocket(P9999.Socket,iDataBuf,iPoint*2); //iDataBuf is a global integer array. if(DEBUG) printCom1("Sending takes %lu ms\n\r",*TimeTicks-st); iReading=0; } void PortUserStart(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E via the user's defined port(PortUser), the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing } void Port9999Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 9999, the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing } void Port502Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 502, the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing }