| 作者 | 主题 |
|---|---|
|
四书五经 侠圣 经验值:3667 发帖数:762 精华帖:58 |
楼主
主题:C脚本中使用MSCOMM如何发送"0"字符,VB脚本中如何发送大于128的字符,虽然是非主流话题,但的确客户需要,希望斑主不要删帖
如题,客户要在WINCC中实现MODBUS RTU 协议(做为从站)与一个远端的DCS进行通讯.我已经用了很多方法,可就是这样,在C脚本中用MSCOMM控件无法发送0字符,在VB中又无法发送大于128的字符.当然我更希望在C脚本中实现发送0字符,毕竟C脚本处理数据的功能要强很多.
最后的方法我就是使用API了!不过实在不希望使用API. |
|
dcount107 侠圣 经验值:2840 发帖数:1737 精华帖:55 |
6楼
主题:回复:C脚本中使用MSCOMM如何发送
几经努力,这个问题应该算是可以得到解决了,呵呵。
对于字符串来说,C中的ASCII 0代表结束符,而VBS的CHR只支持到0~127,所以要解决这个问题,MsComm控件发送时必须使用Byte()格式的字节数组数据,接收也必须使用comInputModeBinary的接收方式。 不过遗憾的是VBS并不直接支持Byte()格式,其实我们声明的Dim SendByte(x)只是Variant()格式,因此需要想办法将其转换为Byte()格式就能拿来用了。 目前我的做法是用VB编写一个DLL文件,用于实现Variant()和Byte()之间的互相转化。 经测试,0~255的ASCII均可发送和接受,下面是效果图: 示例文件如下(WinCC V6.2 SP3)以及DLL文件(使用之前请选用RegSvr32.exe 注册一下)见附件: 点击此处查看附件
非淡泊无以明志,非宁静无以致远
|
|
四书五经 侠圣 经验值:3667 发帖数:762 精华帖:58 |
11楼
主题:回复:C脚本中使用MSCOMM如何发送
在全局C脚本中写一个全局动作,动作的触发条件是TAG触发,触发变量为"TrigComm"
#include "apdefap.h" int gscAction( void ) { typedef struct _COMMTIMEOUTS { DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ } COMMTIMEOUTS,*LPCOMMTIMEOUTS; typedef struct _DCB { DWORD DCBlength; /* sizeof(DCB) */ DWORD BaudRate; /* Baudrate at which running */ DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ DWORD fParity: 1; /* Enable parity checking */ DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ DWORD fDtrControl:2; /* DTR Flow control */ DWORD fDsrSensitivity:1; /* DSR Sensitivity */ DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ DWORD fInX: 1; /* Enable input X-ON/X-OFF */ DWORD fErrorChar: 1; /* Enable Err Replacement */ DWORD fNull: 1; /* Enable Null stripping */ DWORD fRtsControl:2; /* Rts Flow control */ DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ DWORD fDummy2:17; /* Reserved */ WORD wReserved; /* Not currently used */ WORD XonLim; /* Transmit X-ON threshold */ WORD XoffLim; /* Transmit X-OFF threshold */ BYTE ByteSize; /* Number of bits/byte, 4-8 */ BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ char XonChar; /* Tx and Rx X-ON character */ char XoffChar; /* Tx and Rx X-OFF character */ char ErrorChar; /* Error replacement char */ char EofChar; /* End of Input character */ char EvtChar; /* Received Event character */ WORD wReserved1; /* Fill for now. */ } DCB, *LPDCB; #pragma code("kernel32.dll") BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten, LPVOID lpOverlapped ); DWORD GetLastError(VOID); VOID Sleep( DWORD dwMilliseconds ); BOOL CloseHandle( HANDLE hObject ); HANDLE CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); BOOL GetCommTimeouts( HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts ); BOOL SetCommTimeouts(HANDLE hFile,LPCOMMTIMEOUTS lpCommTimeouts ); BOOL GetCommState( HANDLE hFile, LPDCB lpDCB ); BOOL SetCommState( HANDLE hFile, LPDCB lpDCB ); BOOL BuildCommDCBA(LPCSTR lpDef,LPDCB lpDCB ); #pragma code() #define GetObjectA GetObject int i; union{ /*定义一个联合*/ float f1; struct{ /*在联合中定义一个结构*/ char first; char second; char third; char forth; }half; }data; struct{ DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; LONG hEvent; }ov1,*ov2; char st1[100]; unsigned short crc; DWORD n1; HANDLE hFile; COMMTIMEOUTS ctmoOld,ctmoNew; DCB dcbCommPort; __object *pdl = NULL; __object *pic = NULL; __object *obj = NULL; if (GetTagBit("TrigComm")==0) return 0; pdl = __object_create("PDLRuntime"); pic = pdl->GetPicture("MAIN"); obj = pic->GetObject("MScomm1"); data.f1=GetTagFloat("AA1");//获取数据 st1[0]=02; st1[1]=03; st1[2]=8; st1[3]=data.half.first; st1[4]=data.half.second; st1[5]=data.half.third; st1[6]=data.half.forth; data.f1=GetTagFloat("AA2"); st1[7]=data.half.first; st1[8]=data.half.second; st1[9]=data.half.third; st1[10]=data.half.forth; crc=Calc_Crc((unsigned char *)st1,11);//计算CRC st1[11]=crc & 0x00ff; st1[12]=(crc & 0xff00)>>8; obj->PortOpen=FALSE; hFile = CreateFileA("COM3",0x80000000 0x40000000,0,NULL,3,0,NULL); printf("HFILE=%d",hFile); GetCommTimeouts(hFile,&ctmoOld); ctmoNew.ReadTotalTimeoutConstant = 100; ctmoNew.ReadTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutConstant = 0; SetCommTimeouts(hFile, &ctmoNew); dcbCommPort.DCBlength = sizeof(DCB); GetCommState(hFile, &dcbCommPort); BuildCommDCBA("9600,N,8,1", &dcbCommPort); SetCommState(hFile, &dcbCommPort); WriteFile(hFile, st1,13, &n1, NULL);//通过串口发送数据 printf("n1=%d",n1); Sleep(400); CloseHandle(hFile); obj->PortOpen=TRUE; SetTagBit("TrigComm",FALSE); __object_delete(obj); __object_delete(pic); __object_delete(pdl); return 0; 最终显示效果如下: |
|
youhm 至圣 经验值:13571 发帖数:4924 精华帖:81 |
13楼
主题:回复:C脚本中使用MSCOMM如何发送
在VBS脚本里变量都是以变体的形式存在的,但也还是有各种数据类型,只是有些是在VBS里无法构建的,比如Byte()
接收可以按楼上“四书五经”的方法直接解析,为了方便,我也做了转换的函数 附件包含DLL及VB源码和使用方法 点击此处查看附件 |