/* XDemo69: Save the channel value from 7018 and DI to Save to Flash (Log) Compiler: BC++ 3.1 Compile mode: large Project: user.c v7000.c vModbus.c [after vcom3002.lib] ..\Lib\7186EL.Lib ..\Lib\tcp_dm32.lib ..\Lib\VcomNNNN.Lib, with NNNN being the lib file's version. Command sets 19set start-> Start to save log to flash 19set stop -> Stop to save log to flash 19set debug --> Set the debug port to monitor the data log --> COM port 1~8 19get log --> Get how many log exist on the Flash 19get log all --> Get all log from Flash 19get log n1 n2 --> Get 19del log --> Delete all Log saved on the Flash 19reset --> Rest the system This demo shows how to build a Data log system on the 7188E series The valid log totally saved to Flash are 12288. The every one log occupies the 16bytes of the Flash. Use "19set start" command to read AI0 of 7018/7017 and DI0 of X107 and then save to Flash as a Log for a period time set by the command "19set logtime". Use "19set stop" to stop saving the LOG. The default logtime is 1000, and saving the LOG is in stop state. Hardware: uPAC-7186EX and X107 + 7017/7018 whose address is 00, baudrate is 9600, checksum is disable. [Dec 18, 2008] by Liam */ #include #include #include #include #include "..\lib\7186e.h" #include "..\lib\tcpip32.h" #include "..\lib\vxcomm.h" #define _X107 // plug X107 on the uPAC-7186EX #ifdef _X107 #define _DOCh 7 #define _DICh 6 #define _DOBase 0 #define _DIBase 1 #else #define _DOCh 4 #define _DICh 4 #define _DOBase 0 #define _DIBase 0 #endif #define _MAXLOG_ 12288 //65536*3/16 #define _1stSegment_ 0 #define _2ndSegment_ (_MAXLOG_/3*1) //4096 #define _3rdSegment_ (_MAXLOG_/3*2) //8192 struct data{ char buf[8]; // +01.234 7 data chars + 1 zero char = 8 chars }Value[8]; // 8 channels BYTE DO[_DOCh], DI[_DICh];//The offset value of DO,DI BYTE cLog; BYTE bDebug; //debug port DWORD lLogTimeInterval=1000; // the frequency of saving log to flash DWORD stime; BYTE TotalCOMport; int iActionIndex, iSaveIndex; BYTE bCheckSerial; void (*reset)(void)=(void (*)(void))0xFFFF0000L; //reset funtion int Flash_MultiRead(int iSeg,int ioffset, int iCount, char* cData) { int i; for(i=ioffset;i<(ioffset+iCount);i++) { *cData=FlashRead(iSeg,i); cData++; } return 0; } int Flash_MultiWrite(int iSeg, int ioffset, int iCount, char* cData) { int i, iRet; for(i=ioffset; i<(ioffset+iCount); i++) { iRet=FlashWrite(iSeg, i, *cData); if(iRet<0) return iRet; else cData++; RefreshWDT(); } return 0; } WORD checkTotalLog(WORD iAI,WORD iSI) { if(!ReadNVRAM(3))//A flag saved on the address 3 of NVRAM is used to record whether the segment 0xc000,d000,e000 has ever writed,(over 12288) (1: Yes, 0: No) return iAI; else { switch(iSI) { case _1stSegment_: //first segment return iAI; case _2ndSegment_: //second segment case _3rdSegment_: //third segment return (_MAXLOG_-iSI+iAI); } } return 0; } int Log_Save2Flash(char *Temp, WORD ilen) { /* AI LOG format N M1 D H M2 S I n + 0 0 . 0 0 0 C 0 byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 DI LOG format N M1 D H M2 S I n 0 C 0 byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 byte(0) N: how many data save on the log (AI:15,DI:9) byte(1~5) M1: Month, D: Day, H: hour, M2: Minute, S: second byte(6) I: AI value(8~14), C:checksum(15) byte(6) I: DI value(8), C:checksum(9) byte(7) n: AI or DI channel number */ unsigned iSeg; int i, iRet, iTotal; char sLog[16]; int iYear, iMonth, iDay; int iHour, iMinute, iSecond; BYTE iCye; WORD iTotalLog; //save the log index max:6144 (2048*3) (65536/32=2048) if(ilen>9) //9+7=16 (7 denotes length(1)+date(2)+ time(3) + \r(6)) return -10; if(bDebug) printCom(bDebug, "Start to Log_Save2Flash, ilen:%d\r\n", ilen); iCye=ReadNVRAM(3); //A flag saved on the address 3 of NVRAM is used to record whether the segment 0xc000,d000,e000 has ever writed,(over 12288) (1: Yes, 0: No) if(iActionIndex==_MAXLOG_ && !iCye) { WriteNVRAM(3, 1); iActionIndex=0; iSaveIndex=_2ndSegment_; //Move to second segment FlashErase(0xc000); } else if(iActionIndex==_1stSegment_ && iCye) iSaveIndex=_2ndSegment_; else if(iActionIndex==_2ndSegment_ && iCye) iSaveIndex=_3rdSegment_; else if(iActionIndex==_3rdSegment_ && iCye) iSaveIndex=_1stSegment_; iTotal=7+ilen; //(7 denotes length(1)+date(2)+ time(3) + \r(6)) GetDate(&iYear, &iMonth, &iDay); //Date GetTime(&iHour, &iMinute, &iSecond); //Time sprintf(sLog, "%c%c%c%c%c%c", (char)iTotal, (char)iMonth, (char)iDay, (char)iHour, (char)iMinute, (char)iSecond); for(i=0; i=_3rdSegment_) //segment 3 0xE000 iSeg=0xe000; if((iRet=FlashRead(iSeg, (iActionIndex%_2ndSegment_)*16))!=0xff) // modified in 2007.07.24 { FlashErase(iSeg); if(bDebug) printCom(bDebug, "FlashErase:%04X, iRet= %02X\r\n", iSeg, iRet); } iRet=Flash_MultiWrite(iSeg, (iActionIndex%_2ndSegment_)*16, 16, sLog); //// modified in 2007.07.24 if(!iRet) { iActionIndex++; WriteNVRAM(0,iActionIndex&0xff); //low byte WriteNVRAM(1,iActionIndex>>8&0xff); //high byte WriteNVRAM(4,iSaveIndex&0xff); //low byte WriteNVRAM(5,iSaveIndex>>8&0xff); //high byte iTotalLog=checkTotalLog(iActionIndex, iSaveIndex); if(bDebug) printCom(bDebug, "iTotalLog:%u,iActionIndex:%u,iSaveIndex:%u,iSeg:%x,offset:%u\r\n",iTotalLog,iActionIndex,iSaveIndex,iSeg,(iActionIndex%4096)*16); } return iRet; } int Log_LoadFromFlash(char *Temp, WORD istart, WORD inumber) //ibufferLen:buffer length,istart: Finding the first index of Datalog what you want,inumber:Total data count of DataLog. return: 0 finish. 1 not finish. { int i,iSeg; int iRet; int iCye; WORD wStart; BYTE sText[20]; char sLog[100]; if(bDebug) printCom(bDebug, "iStart:%d, inumber:%d\r\n", istart, inumber); sprintf(Temp, "\r\nLog Table on the Flash\r\nItem Log Date Time\tComponet value\r\n"); iCye=ReadNVRAM(3); //A flag saved on the address 3 of NVRAM is used to record whether the segment 0xc000,d000,e000 has ever writed,(over 12288) (1: Yes, 0: No) if(!iCye) wStart=istart; else wStart=istart+iSaveIndex; for(i=0; i=_3rdSegment_) //segment 3 0xE000 iSeg=0xe000; else if(iCye && wStart==_MAXLOG_) { wStart=0; iSeg=0xc000; } iRet=Flash_MultiRead(iSeg, (wStart-1)%_2ndSegment_*16, 16, sText); if(!iRet) { sprintf(sLog, "No.%d\t,%d/%d\t%d:%d:%d ",i,sText[1],sText[2],sText[3],sText[4],sText[5]); strcat(Temp, sLog); if(sText[sText[0]-1]!=0x0d) // the end character of log is 0x0d { strcpy(sLog, "The wrong log data!\r\n"); strcat(Temp, sLog); } else { if(bDebug) printCom(bDebug, "sText[6]:%d..sText:%s\r\n", sText[6], sText+6); if(sText[6]=='0') // AI channels { sprintf(sLog, " AI%c", sText[7]); strcat(Temp, sLog); strncpy(sLog, sText+8,7); sLog[7]=0x0; strcat(Temp, sLog); } else if(sText[6]=='1') // DI channels { sprintf(sLog, " DI%c", sText[7]); strcat(Temp, sLog); if(!sText[8]) strcat(Temp, " off"); else strcat(Temp, " on"); } } strcat(Temp, "\r\n"); } wStart=wStart+1; RefreshWDT(); } if(bDebug) printCom(bDebug, "Temp:%s\r\n", Temp); return 0; } void DIO_Access(void) { int iRet, i; iRet=inportb(_DIBase); // printCom(bDebug,"DI=%d\r\n",iRet);//com2 for(i=0;i<_DICh;i++) { DI[i]=~(iRet>>i)& 0x01; } RefreshWDT(); iRet=0; for(i=0;i<_DOCh;i++) iRet=iRet+DO[i]*(1<+00.000+01.000+02.000+03.000+04.000+05.000+06.000+07.000" // str[0] is '>'. The data of values starts at 1. iPointer=1; //Reads value of each channel. for(iChannel=0; iChannel<=7; iChannel++) //Update AI { for(i=0; i<7;i++) // one channel has 7 characters. { Value[iChannel].buf[i]=str[iPointer++]; } Value[iChannel].buf[7]=0x0; // add the zero end to the string. //if(bDebug) //printCom(bDebug,"Channel %d : %s \n\r",iChannel, Value[iChannel].buf); } DIO_Access(); //Update DIO } else if(bDebug) printCom(bDebug, "ReceiveResponseFrom7000 error!!,return:%d\r\n", bCheckSerial); } } void UserInit(void) { /* Initialize user's program. Please refer to XDemo04 for detail description. Please refer to XDemo09 for example code. */ int i, j; InitLib(); SetBaudrate(2, 9600L); // com port= 2, baudrate =9600, data bit=8, non parity SetDataFormat(2,8,0,1); TotalCOMport=GetComportNumber(); //total COM port in the current 7188e cLog=0; //The initilation value is 0 bDebug=EE_RandomRead(1, 0x15); //Read block 1 ,0x15 if(bDebug>TotalCOMport) { bDebug=1; //debug is COM1 //baudrate =115200, data bit=8, non parity used for debug port SetBaudrate(bDebug, 115200L); // com port= 1 SetDataFormat(bDebug, 8, 0, 1); } else { /* All of the program user.c needn't function Installcom(). Becuase they have install When the Xserver initialize. If you want to change the baud rate.data format, please using the function SetBaudrate().SetDataFormat(). */ //_InstallCom(bDebug,115200L,8,0,1); SetBaudrate(bDebug, 115200L); // com port= 1 SetDataFormat(bDebug, 8, 0, 1); } j=ReadNVRAM(0); //low byte i=ReadNVRAM(1); //high byte iActionIndex=(i<<8)+j; if(iActionIndex>_MAXLOG_) iActionIndex=0; j=ReadNVRAM(4); //low byte i=ReadNVRAM(5); //high byte iSaveIndex=(i<<8)+j; if(iSaveIndex>_MAXLOG_) iSaveIndex=0; if(bDebug) printCom(bDebug, "j:%d,i:%d,iActionIndex:%d,iSaveIndex:%d\r\n",j,i,iActionIndex,iSaveIndex); } void UserLoopFun(void) { /* VxComm.exe will call this function every scan time Please refer to XDemo11 for Real-time I/O control */ char Stemp[20]; if(cLog) //Log switch { // if(bDebug) // printCom(bDebug,"cLog:%d, lLogTimeInterval:%lu, stime:%lu\r\n",cLog,lLogTimeInterval,stime); if(*TimeTicks-stime>lLogTimeInterval) { if(!bCheckSerial) { sprintf(Stemp, "0%c%s", 0+48, Value[0].buf); //Save AI(0) 0(0~n)-->Save AI0 to a LOG Log_Save2Flash(Stemp, 9); // AI(1)+N(1)+value(7) } else { sprintf(Stemp,"0%c%s%02d", 0+48, "Err", bCheckSerial+48); Log_Save2Flash(Stemp, 7); // AI(1)+N(1)+Err(5) } sprintf(Stemp,"1%c%c", 0+48, DI[0]); //Save DI(1) 0(0~n)-->Save DI0 to a LOG Log_Save2Flash(Stemp, 3); // DI(1)+N(1)+value(1) stime=*TimeTicks; } } } int UserCmd(unsigned char *Cmd,unsigned char *Response) { /* Xserver executes this function when received a package form TCP port 10000 and the first two bytes are "19". Funtion of Xserver, Please refer to XDemo04 for detail description. */ char *cm1; int ipara=0, i, iDebug_temp; static WORD isStart, isNumber;//for log , and isNumber is defined to detect using the Triggered or Reset the Event in Status trigger WORD iTotalLog; cm1=strtok(Cmd," "); if(cm1!=NULL) { if(!strcmp(strlwr(cm1),"set")) //set { cm1=strtok(NULL," "); if(!strcmpi(cm1,"debug")) //19set debug xxx, set 7188E debug port (port=0 to close debug port) { cm1=strtok(NULL," "); ipara=atoi(cm1); if(ipara>TotalCOMport) strcpy(Response,"Illegal COM port\r\n"); else { EE_WriteEnable(); EE_RandomWrite(1, 0x15, (unsigned char)ipara); //debug port block0 0x15 1byte if(ipara==0) { bDebug=0; strcpy(Response,"Close debug port\r\n"); } else { bDebug=ipara; sprintf(Response,"Set debug port to %d\r\n",ipara); } EE_WriteProtect(); } } else if(!strcmpi(strlwr(cm1), "start")) //19set start, start to save log to flash { cLog=1; AddUserTimerFunction(UserCount, lLogTimeInterval/2); // Update AI and DI value for 1/2 lLogTimeInterval stime=*TimeTicks; sprintf(Response," Start save log to flash\r\n"); } else if(!strcmpi(strlwr(cm1),"stop")) //19set stop ,stop to save log to flash { cLog=0; sprintf(Response," Stop save log to flash\r\n"); } else if(!strcmpi(strlwr(cm1), "logtime")) //19set logtime xxxxx, { cm1=strtok(NULL, " "); sscanf(cm1, "%lu", &lLogTimeInterval); if(lLogTimeInterval<1000 || lLogTimeInterval>100000) // 1~100 second lLogTimeInterval=5000; sprintf(Response, " The lLogTimeInterval is %lu\r\n", lLogTimeInterval); } else strcpy(Response, "Illegal command\r\n"); } else if(!strcmp(strlwr(cm1), "del")) { cm1=strtok(NULL, " "); if(!strcmpi(cm1, "log")) //19del log { FlashErase(0xc000); iActionIndex=0; iSaveIndex=0; WriteNVRAM(3, 0); //clear the flag to 0 (//A flag saved on the address 3 of NVRAM is used to record whether the segment 0xc000,d000,e000 has ever writed,(over 12288) (1: Yes, 0: No)) WriteNVRAM(0, 0); //low byte WriteNVRAM(1, 0); //high byte WriteNVRAM(4, 0); //low byte WriteNVRAM(5, 0); //high byte strcpy(Response, "del all logs!!\r\n"); } } else if(!strcmp(strlwr(cm1), "get")) //get { cm1=strtok(NULL, " "); if(!strcmpi(cm1, "logtime")) //19get logtime { sprintf(Response," lLogTimeInterval is %lu\r\n", lLogTimeInterval); } else if(!strcmpi(cm1, "log")) //19get log 2 10, get the 10 logs from the second log { if(iTotalLog=checkTotalLog(iActionIndex, iSaveIndex)) // { cm1=strtok(NULL, " "); if(!strcmp(cm1, "all")) { isStart=1; isNumber=iTotalLog; } else { sscanf(cm1, "%d", &isStart); if(cm1==NULL) { if(!ReadNVRAM(3)) // A flag saved on the address 3 of NVRAM is used to record whether the segment 0xc000,d000,e000 has ever writed,(over 12288) (1: Yes, 0: No) sprintf(Response, "\r\n%u logs (No.1~%u) in the Flash!!\r\n",iTotalLog,iTotalLog); else { if(iTotalLog<_2ndSegment_) sprintf(Response, "\r\n%u logs (No.1~%u,No.4096~12288) in the Flash!!\r\n",_2ndSegment_+iTotalLog,iTotalLog); else if(iTotalLog<_3rdSegment_) sprintf(Response, "\r\n%u logs(No.1~%u,No.8192~12288) in the Flash!!\r\n",_2ndSegment_+iTotalLog,iTotalLog); else sprintf(Response, "\r\n%u logs(No.1~%u) in the Flash!!\r\n",iTotalLog,iTotalLog); } return 1; } cm1=strtok(NULL, " "); sscanf(cm1, "%d", &isNumber); //The number of log you want to read if(isNumber>50) //The maxium log for once getting { sprintf(Response, "The total data size of log are over the default!!\r\n"); return 1; } if(bDebug) printCom(bDebug, "start:%d,number:%d,Read:%d\r\n", isStart, isNumber, ReadNVRAM(3)); if(ReadNVRAM(3)) //if the segment 0xc000,d000,e000 has ever writed,(over 12288) { if(iTotalLog<_2ndSegment_) { if(isStart<_2ndSegment_ && isStart>iTotalLog) { sprintf(Response, "\r\nWrong starting position :%d\r\n", isStart); return 1; } else { if((isNumber>(_MAXLOG_-_2ndSegment_)&& isStart>=_2ndSegment_)|| (isNumber>iTotalLog && isStartiTotalLog) { sprintf(Response,"\r\nWrong starting position :%d\r\n",isStart); return 1; } else { if((isNumber>(_MAXLOG_-_3rdSegment_)&& isStart>=_3rdSegment_)|| (isNumber>iTotalLog && isStart=_3rdSegment_) { if(isStart<_3rdSegment_ && isStart>iTotalLog) { sprintf(Response,"\r\nWrong starting position :%d\r\n",isStart); return 1; } else { if(isNumber>iTotalLog && isStartiTotalLog) { sprintf(Response, "\r\nWrong starting position :%d\r\n", isStart); return 1; } else { if(isNumber>(iTotalLog-isStart+1)) //if the number of the first log you want to read is larger than the total number of log, return error { sprintf(Response, "\r\nWrong Log number:%d\r\n", isNumber); return 1; } } } } iDebug_temp=bDebug; if(isNumber>=iTotalLog) bDebug=0; // close the debug port i=Log_LoadFromFlash(Response, isStart, isNumber); if(i!=0) strcpy(Response, "Read log error!!\r\n"); bDebug=iDebug_temp; } else sprintf(Response, "\r\nNo log Data on the Flash memory\r\n"); } else sprintf(Response, "Illegal command,%s\r\n", cm1); } else if(!strcmp(cm1, "reset")) reset(); else sprintf(Response,"Illegal command,%s\r\n", cm1); } return 1; } int VcomUserBinaryCmd(TCPREADDATA *p) { /* VXCOMM.EXE 2.6.12(04,Sep,2001) or later will support this function. Xserver executes this function when received a package form TCP port 10000 and the first two bytes are "23". Please refer to XDemo04 for detail description. Please refer to XDemo23 for example code. */ 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. Please refer to XDemo04 for detail description. */ VcomSendSocket(p->Socket,p->ReadUartChar,p->Length); return 1; /* any value will be accept */ } 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. Please refer to XDemo04 for detail description. */ 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. Please refer to XDemo04 for detail description. */ 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. Please refer to XDemo04 for detail description. */ skt=skt; //do nothing }