我来送分,有关MSComm控件!各位大虾,快来拿分,快来Help Me!(150分)

  • 主题发起人 主题发起人 jason
  • 开始时间 开始时间
J

jason

Unregistered / Unconfirmed
GUEST, unregistred user!
我用BCB编了MSComm控件的串口通讯程序,采用char数组进行二进制数据的传送。在发送端发送后,使用超级终端成功接收。但在接收端却遇到一些问题,如:"Cannot Convert 'char *' to "System:OleVariant",我试用WideString进行接收,但是发送的是buf[0]=235;buf[1]=169;buf[2]=127;接收的却是1 128 1这是何故?另外,为何每次在触发发送端的mscomm->portopen属性时,总是触发接收端的OnComm事件!
 
能否更详细一些?
 
我定义了char buf[3],buf中的三个元素为以上三个,我用超级终端接收时收到的
三个数同buf中所发的这三个数相同(分别是这三个数的二进制码,用Ultra Edit
察看),但是在用我自编的另一个程序接收(我想在Memo上显示以被检验,在发送
端我也用Memo检验,能成功显示),不知如何能成功的显示?另外,在发送端我关
闭端口时,用了MSComm->portopen=false,但是这句语句也触发接收端的OnComm
事件不知有何办法不触发!各位大虾多多赐教!
 
jason:你好
我不熟BC Build,在此只能给你DELPHI程序,基本用API完成,该程序我用过
没有问题,以供参考:(连线方式为:2-3,3-2,5-5,'*'为主要的API函数)
发送:
Var
CommTimeOuts:TCommTimeOuts;
FDCB:TDCB;
SendBuff:Array [0..50] of Char;
OS:TOverlapped;
WriteSize:DWord;
Begin
* ComHandle:=CreateFile('COM2',GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
* SetupComm(ComHandle,512,512);

* GetCommTimeOuts(ComHandle,CommTimeOuts);
CommTimeouts.ReadIntervalTimeout:=250;
CommTimeouts.ReadTotalTimeoutMultiplier:=0;
CommTimeouts.ReadTotalTimeoutConstant:=0;
CommTimeouts.WriteTotalTimeoutMultiplier:=0;
CommTimeouts.WriteTotalTimeoutConstant:=0;
* SetCommTimeOuts(ComHandle,CommTimeOuts);

* GetCommState(ComHandle,FDCB);
FDCB.BaudRate:=CBR_9600;
FDCB.Parity:=ODDPARITY;
FDCB.Stopbits:=ONESTOPBIT;
FDCB.Bytesize:=8;
* SetCommState(ComHandle,FDCB);
StrPCopy(SendBuff,'this is a test');
FillChar(Os,Sizeof(OS),0);
WriteFile(ComHandle,SendBuff,StrLen(SendBuff),WriteSize,@OS);
CloseHandle(ComHandle);
End;

接收:
Var
CommTimeOuts:TCommTimeOuts;
FDCB:TDCB;
SendBuff:Array [0..50] of Char;
OS:TOverlapped;
WriteSize:DWord;
PState:TComStat;
DelayTime:DWord;
Begin
* ComHandle:=CreateFile('COM2',GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
* SetupComm(ComHandle,512,512);

* GetCommTimeOuts(ComHandle,CommTimeOuts);
CommTimeouts.ReadIntervalTimeout:=250;
CommTimeouts.ReadTotalTimeoutMultiplier:=0;
CommTimeouts.ReadTotalTimeoutConstant:=0;
CommTimeouts.WriteTotalTimeoutMultiplier:=0;
CommTimeouts.WriteTotalTimeoutConstant:=0;
* SetCommTimeOuts(ComHandle,CommTimeOuts);

* GetCommState(ComHandle,FDCB);
FDCB.BaudRate:=CBR_9600;
FDCB.Parity:=ODDPARITY;
FDCB.Stopbits:=ONESTOPBIT;
FDCB.Bytesize:=8;
* SetCommState(ComHandle,FDCB);
DelayTime:=timeGetTime+12000; //timeGetTime 在MMSystem单元中

While DelayTime>timeGetTime Do
Begin
ClearCommError(ComHandle,WriteSize,@PState);
End;
if PState.cbInQue>0 Then Break;
Begin
FillChar(Os,Sizeof(OS),0);
//此时SendBuff为接收到的数据
ReadFile(ComHandle,SendBuff,PState.cbInQue,WriteSize,@OS);
//下面两句只是作为调试用,在接收窗口标题拦显示接收的数据
SendBuff[WriteSize]:=#0;
Self.Caption:=StrPas(SendBuff);
End;
CloseHandle(ComHandle);
End;

 
在Char数组和Variant是不相容的,你不能直接将Char数组赋给Variant,或直接将
Variant给Char数组,否则会出现你所说的错误,下面给出一例子:

type
TCharArray=array[0..1] of Char;
PCharArray=^TCharArray;

procedure TForm1.WriteCom(const Buf:array of Char;
var
V:Variant;
P:PCharArray;
i:Integer;
begin
V:= VarArrayCreate([Low(Buf), High(Buf)], varChar);
P := VarArrayLock(V);
try
for i:=Low(Buf) to High(Buf) do P^:=Buf;
finally
VarArrayUnlock(A);
end;
MsComm1.OutPut:=V;
end;

function TForm1.ReadCom(var Buf):Integer;
var
V:Variant;
P:PCharArray;
i:Integer;
begin
V:=MsComm1.Input;
P := VarArrayLock(V);
try
for i:=VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do
TCharArray(Buf)[i-VarArrayLowBound(V,1)]:=P^;
finally
VarArrayUnlock(A);
end;
end;
 
在接收16进制数>128的字符时,你的接收要用变体数组,
如先定义
var myvarint:Variant; //变体数组 //用于接收字符

//建立好数组
myvarint:=varArraycreate([0,499],varVariant);//数据接收变体数组

//在接收事件里
InputLen:=***
myvarint:=MSComm1.input;
这样 myvarint[*]里的数就对了
 
可能是字符集问题,Win95/98使用双字节表示一个字符,发送和接收时转换成单字节试试。
 
使用MSComm本来就会导侄双字节不能传输
的问题,在English Win95与Chinese Win95下面
会出现很讨厌的不兼容的问题。
建议不要用MSComm,而用API,这样一来可以直接
使用char数组。
可以参考tk128的程序。但是要实用还要用线程。
 
强烈建议使用SPCOMM操作串口
mscomm在VB下还能用,在Delphi下有很多兼容性问题
 
同感,我用Mscomm32发送超过128的字符时,接受却成了0x00,可怜不知道为什么?
 
MSComm有个属性InputMode设为comInputModeBinary即可
 
建议采用tk128的程序来实现串口通信,在Delphi下Mscomm控件不稳定,特别是它
的OnComm事件。
 
comport构件是一个很好的构件,请看它的描述:
Delphi and C++ Builder component for serial communication on Windows 95, Windows 98 and Windows NT 4.

Benefits:

?enables communication with modems or other devices connected to serial port

?easy of use but very powerful
?uses multithreading and overlapping for maximum performance
?available for Delphi 3, Delphi 4, C++ Builder 3 and C++ Builder 4
?source code of component is included in full version
?distributing component in applications is royalty free
我成功的用此构件解决了你这样的问题。只是它没有源码。
 
这样做,是正宗!! 可查MSDN文档
我的C程序大致是这样的:
接收:
OnOnCommMscomm1() //接收事件处理
{
VARIANT m_input1;
COleSafeArray m_input2;
long length,i;
BYTE data[5];
CString str;
if(m_Comm.GetCommEvent()==2) //接收缓冲区有字符
{
m_input1=m_Comm.GetInput(); //读取缓冲区的内容
m_input2=m_input1; //将VARIANT型变量转换为OleSafeArray型变量
length=m_input2.GetOneDimSize();//确定数据长度
for(i=0;i<length;i++)
m_input2.GetElement(&amp;i,data+i);//将数据转换为BYTE型数组
unsigned char a=*(char*)(data+0);
queen_r[tpor].cbcou=a;
a=*(char*)(data+1);
queen_r[tpor].order=a;
a=*(char*)(data+2);
queen_r[tpor].info1=a;
tpor=tpor+1;
if(tpor==QULEN) tpor=0;
Answer=0;
}
}

发送:
CByteArray SendBuf;
SendBuf.SetSize(5);
SendBuf.SetAt(0,(BYTE)order);//将要发送的数据强制转换成BYTE型
SendBuf.SetAt(1,(BYTE)cbcou);
SendBuf.SetAt(2,(BYTE)phno);
SendBuf.SetAt(3,(BYTE)zyd);
SendBuf.SetAt(4,(BYTE)zyu);
m_Comm.SetOutput(COleVariant(SendBuf));
 
折磨高的,帖子只有一半,再来!
这样做,是正宗!! 可查MSDN文档我的C程序是这样的:
接收:
Void MyView::OnOnCommMscomm1()
{
VARIANT m_input1;
COleSafeArray m_input2;
long length,i;
BYTE data[5];
CString str;
if(m_Comm.GetCommEvent()==2) //接收缓冲区有字符
{
m_input1=m_Comm.GetInput(); //读取缓冲区的内容
m_input2=m_input1; //将VARIANT型变量转换为COleSafeArray型变量
length=m_input2.GetOneDimSize();//确定数据长度
for(i=0;i<length;i++)
m_input2.GetElement(&amp;i,data+i);//将数据转换为BYTE型数组
unsigned char a=*(char*)(data+0);
queen_r[tpor].cbcou=a;
a=*(char*)(data+1);
queen_r[tpor].order=a;
a=*(char*)(data+2);
queen_r[tpor].info1=a;
tpor=tpor+1;
if(tpor==QULEN) tpor=0;
Answer=0;
}
}
发送:
CByteArray SendBuf;
SendBuf.SetSize(5);
SendBuf.SetAt(0,(BYTE)order);
SendBuf.SetAt(1,(BYTE)cbcou);
SendBuf.SetAt(2,(BYTE)phno);
SendBuf.SetAt(3,(BYTE)zyd);
SendBuf.SetAt(4,(BYTE)zyu);
m_Comm.SetOutput(COleVariant(SendBuf));
 
Cao 后一半。。。

for(i=0;i<lengtth;i++)
m_input2.GetElement(&amp;i,data+i);//将数据转换为BYTE型数组
unsigned char a=*(char*)(data+0);
queen_r[tpor].cbcou=a;
a=*(char*)(data+1);
queen_r[tpor].order=a;
a=*(char*)(data+2);
queen_r[tpor].info1=a;
tpor=tpor+1;
if(tpor==QULEN) tpor=0;
Answer=0;
}
}
发送:
CByteArray SendBuf;
SendBuf.SetSize(5);
SendBuf.SetAt(0,(BYTE)order);
SendBuf.SetAt(1,(BYTE)cbcou);
SendBuf.SetAt(2,(BYTE)phno);
SendBuf.SetAt(3,(BYTE)zyd);
SendBuf.SetAt(4,(BYTE)zyu);
m_Comm.SetOutput(COleVariant(SendBuf));
 
:~( go on

for...i....length...i++
m_input2.GetElement(&amp;i,data+i);//将数据转换为BYTE型数组

unsigned char a=*(char*)(data+0);
queen_r[tpor].cbcou=a;

a=*(char*)(data+1);
queen_r[tpor].order=a;

a=*(char*)(data+2);
queen_r[tpor].info1=a;

tpor=tpor+1;
if(tpor==QULEN) tpor=0;
Answer=0;
}
}
发送:
CByteArray SendBuf;
SendBuf.SetSize(5);
SendBuf.SetAt(0,(BYTE)order);
SendBuf.SetAt(1,(BYTE)cbcou);
SendBuf.SetAt(2,(BYTE)phno);
SendBuf.SetAt(3,(BYTE)zyd);
SendBuf.SetAt(4,(BYTE)zyu);
m_Comm.SetOutput(COleVariant(SendBuf));
 
多人接受答案了。
 

Similar threads

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