各位大哥、大姐,小弟现在手头上有一设备的串口通讯协议,想把它用Spcomm封装到DLL里面,可是做了几次都不成功,大家能不能帮忙给看一下? (200分)

  • 主题发起人 主题发起人 Spring_Thunder
  • 开始时间 开始时间
S

Spring_Thunder

Unregistered / Unconfirmed
GUEST, unregistred user!
通讯格式采用RS232/RS485 通讯协议。<br>采用半双工通讯方式。<br>波特率:9600<br>数据位:8<br>停止位:1<br>奇偶校验位:无<br><br>相同的协议对于不同的设备在内部的数据存放格式不一定相同,但是对于外部主机设备,通讯的过程表现一样但是对于不同的设备具体的数据格式可能不同。<br><br>通讯流程:<br>1, 通讯主机向从机发送命令。发送的过程完全是主机主动,所有通讯都是由主机发送命令引起的。<br>2,每次通讯都以主机呼叫,收到从机的应答为一次通讯过程。<br>3,每次通讯的时间限定在100MS以内。(包括所有通讯过程,1主机发送的呼叫命令必须在100MS内发完<br>&nbsp; &nbsp; &nbsp; &nbsp;从机发送的应答命令也必须在100MS内发送完毕,)<br><br>4,通讯出错处理。<br> A,主机发送呼叫命令从机接收出错<br> 接收错误从机不应答,主机连续呼叫3次无应答者把该机当作没有开机或线路故障处理。<br><br> B,从机发送应答命令主机接收出错<br> 从机能够收到命令,但是主机收不到应答,或收到的应答错误如果连续3次错误当作没有开机或线路故障处理。<br><br> C,从机根本收不到命令<br> 检查通讯线路和接口芯片。<br><br> D,主机根本收不到应答<br> 检查通讯线路和接口芯片。<br> <br> E,传送的命令总是校验错误<br> 检查通讯线是否接反。<br> <br><br> F,收不到引导字66,bb,CC <br> 检查是否有干扰。<br><br>5,通讯命令每次以固定的 引导字66, BB,CC + 命令长度 + 命令字 + 地址 + 数据 + XOR校验<br><br>6,应答命令 &nbsp;命令长度 + 命令字反 + 地址 + 数据 + 校验和 <br> 应答命令长度不固定,具体长度由 ‘长度’BYTE 确定。<br><br><br>校验:XOR校验=一条命令的累计XOR,但是不包括 66,BB,CC引导字。<br><br>1、 读取时间<br> A2H A2H+地址+ XOR<br> 应答 5DH + 地址 + year + month + date + week+ hour + minute + second 返回该设备时间<br><br>2、 时间设置<br> A3H A3H+地址+时间信息+xor<br> 应答 5CH + 地址 + XOR<br><br>这只是其中的一部分协议,<br>我的DLL是这样写的<br>function Com_Open(aComName:String;aBaudRate:integer;aParity:TParity;aByteSize:TByteSize;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aStopBits:TStopBits):integer;StdCall;<br>begin<br>&nbsp; if FCom=nil then<br>&nbsp; &nbsp; FCom:=TComm.Create(nil);<br><br>&nbsp; &nbsp; FCom.CommName:=aComName;<br>&nbsp; &nbsp; FCom.BaudRate:=aBaudRate;<br>&nbsp; &nbsp; FCom.Parity:=aParity;<br>&nbsp; &nbsp; FCom.ByteSize:=aByteSize;<br>&nbsp; &nbsp; FCom.StopBits:=aStopBits;<br>&nbsp; &nbsp; FCOM.OnReceiveData:=ReceiveData;<br>&nbsp; try<br>&nbsp; &nbsp; FCom.StartComm;<br>&nbsp; &nbsp; Result:=0;<br>&nbsp; except<br>&nbsp; &nbsp; Result:=-1;<br>&nbsp; end;<br>end;<br><br>delphi的事件是不是不能写在DLL里面,我这样写都无法编译,不知道还望各位DFW帮忙看一下。如果有时间的话,用我上面的协议帮忙写一下,小弟将不盛感激。<br>小弟200分送上,
 
我是个菜鸟!:)<br>我以前做过类似的东东,不知道是否能帮上你。<br>FCom:=TComm.Create(nil);<br>好象有问题<br>是否应该将TComm声明一下。<br>只是提个建议,见笑了<br>
 
肯定是已经提前声明过了,
 
FCom,ReceiveData,StartComm你是怎么定义的,我做了以下修改可以通过编译了,可能不是<br>你想要的,但是希望对你有点帮助<br>function Com_Open(aComName:String):integer;<br>var<br>&nbsp; FCom:TCommConfig;<br>&nbsp; hComm:Cardinal;<br>begin<br>&nbsp; //if FCom=nil then<br>&nbsp; &nbsp;hComm :=CreateFile(PChar(aComName),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);//打开通信端口<br>&nbsp; &nbsp;GetCommstate(hComm,FCom.dcb);<br><br>&nbsp; &nbsp;if (hComm=INVALID_HANDLE_VALUE)then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp;ShowMessage('打开通信端口错误!');<br>&nbsp; &nbsp; &nbsp;CloseHandle(hComm);<br>&nbsp; &nbsp; &nbsp;Result:=-1;<br>&nbsp; &nbsp;end;<br><br>&nbsp; &nbsp;//FCom.dcb.:=aComName;<br>&nbsp; &nbsp;with FCom.dcb do<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp;BaudRate:=CBR_9600;<br>&nbsp; &nbsp; &nbsp;Parity:=NoPArity;<br>&nbsp; &nbsp; &nbsp;ByteSize:=8;<br>&nbsp; &nbsp; &nbsp;StopBits:=OneStopBit;//1停止位<br>&nbsp; &nbsp; &nbsp;Result:=0;<br>&nbsp; &nbsp;end;<br>&nbsp; &nbsp;//FCOM.OnReceiveData:=ReceiveData;<br>end;
 
KN兄,<br>你用的是API吧?我想用SPCOMM做<br>
 
无法编译的错误什么啊。
 
Incompatible types: 'method pointer and regular procedure'<br><br>提示这个错误
 
各位高手,如果是用API来做的话,都要用到哪些API函数,使用的顺序是怎样的?
 
CreatFile 打开串口<br>ReadFile 从串口读数据<br>WriteFile &nbsp;向串口发送数据
 
試一試這個控件,寫COM口爽的很,有源碼的<br>+------------------------------------------+<br>| ComPort Library version 2.63 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br>| for Delphi 3, 4, 5, 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br>| and C++ Builder 3, 4, 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br>| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br>| by Dejan Crnila &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br>| 1998-2001 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br>| C++ Builder support by Paul Doland &nbsp; &nbsp; &nbsp; |<br>+------------------------------------------+
 
spcom有源码的吧!你可以在dll里面直接调用spcom的源代码!我用cport就是这样做的!<br>我去研究一下spcom再给你答复吧!
 
我看了spcom的源代码,你可以两种选择:<br>1:在dll里面用个窗体,把spcom放进去。<br>2:在dll里面把spcom.pas加进来。我写了一点,你看看,应该可以参照!具体的函数就要你自己写了!<br>library dlldemo<br><br>{ Important note about DLL memory management: ShareMem must be the<br>&nbsp; first unit in your library's USES clause AND your project's (select<br>&nbsp; Project-View Source) USES clause if your DLL exports any procedures or<br>&nbsp; functions that pass strings as parameters or function results. This<br>&nbsp; applies to all strings passed to and from your DLL--even those that<br>&nbsp; are nested in records and classes. ShareMem is the interface unit to<br>&nbsp; the BORLNDMM.DLL shared memory manager, which must be deployed along<br>&nbsp; with your DLL. To avoid using BORLNDMM.DLL, pass string information<br>&nbsp; using PChar or ShortString parameters. }<br><br>uses<br>&nbsp; windows,<br>&nbsp; function_you in 'function_you .pas',<br>&nbsp; //CommUnit in 'CommUnit.pas',<br>&nbsp; SPComm in 'SPComm.pas';<br><br>procedure DLLEntryPoint(dwReason : DWord);<br>begin<br>&nbsp; case dwReason of<br>&nbsp; &nbsp; DLL_PROCESS_ATTACH:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Comm := TComm.Create(nil);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; DLL_PROCESS_DETACH:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Comm.Destroy;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br><br>exports<br>&nbsp; OpenCommPort, CloseCommPort........;<br><br><br>begin<br>&nbsp; DllProc := @DLLEntryPoint;<br>&nbsp; DLLEntryPoint(DLL_PROCESS_ATTACH);<br>end.
 
谢谢,众位高手,我正在集大家的意见改写,<br>等到我写完后,一定给大家散分,<br>欢迎大家 &nbsp; &nbsp;多多发言
 
procedure TForm1.Button3Click(Sender: TObject);<br>var<br>&nbsp; aComDev:integer;<br>&nbsp; aDCB:TDCB;<br>&nbsp; aTimeOut:TCommTimeOuts;<br>begin<br>&nbsp; aComDev:=CreateFile(pChar('COM1'),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);<br>&nbsp; if aComDev=INVALID_HANDLE_VALUE then<br>&nbsp; &nbsp; Exit<br>&nbsp; else<br>&nbsp; begin<br>&nbsp; &nbsp; if SetupComm(aComDev,4096,4096)=False then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; StatusBar1.Panels[0].Text:=inttostr(-2);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if GetCommState(aComDev,aDCB)=False then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; StatusBar1.Panels[0].Text:=inttostr(-3);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; aDCB.BaudRate:=9600;<br><br>&nbsp; &nbsp; if SetCommMask(aComDev,EV_RXCHAR)=False then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; StatusBar1.Panels[0].Text:=inttostr(-4);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if SetCommState(aComDev,aDCB)=False then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; StatusBar1.Panels[0].Text:=inttostr(-5);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br>用API来实现<br>为什么执行到<br>&nbsp; &nbsp; if SetCommState(aComDev,aDCB)=False then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; StatusBar1.Panels[0].Text:=inttostr(-5);<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>的时候会返回False呢?<br>用WriteFile也返回False<br>有没有人做过给一段代码看一看好吗?
 
type<br>&nbsp; TCOMMINFO = Record<br><br>&nbsp; &nbsp; hComHandle : Thandle; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Comm handle<br>&nbsp; &nbsp; {m_hSuperWnd : Thandle; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Handle of Windows<br>&nbsp; &nbsp; nMessageID : Cardinal; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Message ID}<br>&nbsp; &nbsp; hRevEvent : TEvent; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Event<br>&nbsp; &nbsp; nComPort : longword; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// COM1 COM2...<br>&nbsp; &nbsp; dwBaudRate : dword;<br>&nbsp; &nbsp; dwEvtMask : dword; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Event mask<br>&nbsp; &nbsp; byParity : Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Parity<br>&nbsp; &nbsp; byDataSize : Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Data size<br>&nbsp; &nbsp; byStopSize : Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Stop size<br>&nbsp; &nbsp; byFlowControl : Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Flow control &nbsp; 1 : none<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 : Hardware<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 : Software<br>&nbsp; &nbsp; dwInBufferSize : dword;<br>&nbsp; &nbsp; dwOutBufferSize : dword;<br>&nbsp; &nbsp; ReadOv, WriteOv &nbsp;: TOverLapped;<br>&nbsp; end;<br><br>function TComm.OpenCom({m_hWnd : THandle;nMessage : Cardinal}) : Cardinal;<br>var<br>&nbsp; bSuccessCode : Boolean;<br>&nbsp; dcb : TDCB;<br>&nbsp; CommTimeOuts : TCOMMTIMEOUTS;<br>&nbsp; CommProp : TCommProp;<br>&nbsp; cpPort : string;<br>begin<br>&nbsp; if bIsComOpen then begin result := 2; exit; end; &nbsp;//Alerady Open Com<br><br>&nbsp; /////////////////////////////////////////////<br>&nbsp; if (CommInfo.nComPort = 0) or (CommInfo.nComPort &gt; $10) then<br>&nbsp; begin result := 0; exit; end;<br><br>&nbsp; cpPort:=format('COM%d',[CommInfo.nComPort]);<br>&nbsp; CommInfo.hComHandle:= CreateFile(pChar(cpPort),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;GENERIC_READ+GENERIC_WRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nil,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OPEN_EXISTING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0);<br>&nbsp; if CommInfo.hComHandle =INVALID_HANDLE_VALUE then begin result := 0; exit; end;<br><br>&nbsp; bSuccessCode:=SetCommMask(CommInfo.hComHandle,CommInfo.dwEvtMask);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; bSuccessCode:=SetupComm(CommInfo.hComHandle,CommInfo.dwInBufferSize,CommInfo.dwOutBufferSize);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; bSuccessCode:=PurgeComm(CommInfo.hComHandle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PURGE_TXABORT or PURGE_TXCLEAR or PURGE_RXABORT or PURGE_RXCLEAR);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; bSuccessCode:=GetCommTimeouts(CommInfo.hComHandle,CommTimeOuts);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; CommTimeOuts.ReadIntervalTimeout:=$ffffffff;<br>&nbsp; CommTimeOuts.ReadTotalTimeoutMultiplier:=0;<br>&nbsp; CommTimeOuts.ReadTotalTimeoutConstant:=1000;<br>&nbsp; CommTimeOuts.WriteTotalTimeoutMultiplier:=50;<br>&nbsp; CommTimeOuts.WriteTotalTimeoutConstant:=0;<br>&nbsp; CommTimeOuts.WriteTotalTimeoutConstant := 2000;<br><br>&nbsp; bSuccessCode:=SetCommTimeouts(CommInfo.hComHandle,CommTimeOuts);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; CommProp.wPacketLength:=sizeof(COMMPROP);<br><br>&nbsp; GetCommProperties(CommInfo.hComHandle,CommProp);<br>&nbsp; if ((CommProp.dwSettableBaud and CommInfo.dwBaudRate) &lt;&gt; 0) and<br>&nbsp; &nbsp; &nbsp;((CommInfo.byParity = 0)or<br>&nbsp; &nbsp; &nbsp;((CommProp.wSettableStopParity and CommInfo.byParity) &lt;&gt; 0)) then<br>&nbsp; begin<br>&nbsp; &nbsp; FillChar(dcb, sizeof(dcb), 0);<br>&nbsp; &nbsp; dcb.DCBlength := sizeof(dcb);<br><br>&nbsp; &nbsp; bSuccessCode:=GetCommState(CommInfo.hComHandle,dcb);<br>&nbsp; &nbsp; if not bSuccessCode then<br>&nbsp; &nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; &nbsp; dcb.BaudRate:=(CommInfo).dwBaudRate;<br>&nbsp; &nbsp; dcb.Flags := $00000003;<br>&nbsp; &nbsp; dcb.ByteSize := 8;<br>&nbsp; &nbsp; dcb.Parity := NOPARITY;<br>&nbsp; &nbsp; dcb.StopBits := OneStopBit;<br>&nbsp; &nbsp; dcb.XonLim := 50;<br>&nbsp; &nbsp; dcb.XoffLim := 50;<br>&nbsp; &nbsp; dcb.XonChar := char($11); &nbsp; // XON<br>&nbsp; &nbsp; dcb.XoffChar := char($13); &nbsp;// XOFF}<br><br>&nbsp; &nbsp; bSuccessCode:=SetCommState((CommInfo).hComHandle,dcb);<br>&nbsp; &nbsp; if not bSuccessCode then<br>&nbsp; &nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br>&nbsp; end;<br>&nbsp; bSuccessCode:=EscapeCommFunction(CommInfo.hComHandle,SETDTR);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br>&nbsp; bSuccessCode:=EscapeCommFunction(CommInfo.hComHandle,SETRTS);<br>&nbsp; if not bSuccessCode then<br>&nbsp; begin CloseHandle(CommInfo.hComHandle); result := 0; exit; end;<br><br>&nbsp; bIsComOpen:=TRUE;<br><br>&nbsp; /////////////////////////////////////////////<br>&nbsp; CommInfo.hRevEvent:=TEvent.Create(nil,True,True,'');<br>&nbsp; if CommInfo.hRevEvent.Handle = THandle(nil) then<br>&nbsp; begin CloseCom(); result := 0; exit; end;<br><br>&nbsp; WatchCommThread := TWatchCommThread.Create(True);<br>&nbsp; WatchCommThread.Resume;<br><br>&nbsp; result := 1; &nbsp; //Success<br>end;<br>
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部