您现在所在的是:

串口通信

回帖:0个,阅读:3220 [上一页] [1] [下一页]
29673
思南 管理员
文章数:14047
年度积分:62
历史总积分:29673
注册时间:2001/3/12
发站内信
发表于:2004/3/29 17:22:00
#0楼
转载大富翁论坛 用Spcomm/MScomm串口通信的问题

问题:串口的老问题 (600分) ( 积分:100, 回复:9, 阅读:155 )  分类:局域网 / 通讯
来自:wancc, 时间:2002-06-04 10:51:00, ID:970841  
1.用Mscomm32(vb6带)在Delphi中的收发过程的代码
2.用Spcomm 在Delphi中的收发过程的代码

我用了上面的两个控件发现Mscomm32能发送接收 可是不知道怎样将返回的数据还原成看的
懂的数据(unicode?),我是和51单片机通讯的 谁能写出发送、接收代码将送上300分

用Spcomm也是不知道怎样将返回的数据还原成看的懂的数据,另外它能否象Mscomm一样可以
等到Buffer中有一定个数的字节后再收的功能呢?能否写出原代码将送上300分

其实我看了以前关于串口的帖子 发现大家都是说一半的多 而能写全代码的少 希望这次
各位大侠能写全些的代码供大家学习一下 谢谢!



来自:gzgylgl, 时间:2002-04-04 00:19:00, ID:1022126  
我没用过单片几,但于PLC通信做过。一般传过去用字符或ACSII码。传过来用16进制的(PLC)。



来自:antelep, 时间:2002-06-01 16:58:00, ID:1137497  
发送和接收都用byte型即可



来自:visualboy, 时间:2002-06-01 23:46:00, ID:1138074  
一般串行通讯用ASCII码比较多,当然也有用16进制,正好我都做过。如果是发送端不断发送,那么你可以用事件方式触发。如果是应答方式,你可以用轮询的方式来做。
我以前一直是用VB写跟外围通讯的程序。所以不能提供给你delphi,不过Vb源程序和C源程序倒有

C

int _read_data_register(unsigned int uAddress,unsigned int number)
{    unsigned char uSend[]={2,0x30,0x30,0x30,0x30,0x30,0x30,0x32,3,0x30,0x30};
unsigned char uReceive[104];
unsigned int uTmp;
unsigned int uSum;
unsigned int num;
long lTmp;
int i,j;

if(TESTING==1)
{    for(i=0;i<number;i++)uRead_value[i]=0;
return TRUE;
}

init_plc();
num=number*2;
if((num/16)>=10)
uSend[6]=(unsigned char)(num/16+0x41-10);
else
uSend[6]=(unsigned char)(num/16+0x30);
if((num%16)>=10)
uSend[7]=(unsigned char)((num%16)+0x41-10);
else
uSend[7]=(unsigned char)((num%16)+0x30);

uAddress=uAddress*2+0x1000;

uTmp=uAddress & 0x000f;
uSend[5]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);
uTmp=(uAddress>>4) & 0x000f;
uSend[4]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);
uTmp=(uAddress>>8) & 0x000f;
uSend[3]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);
uTmp=(uAddress>>12)&0x000f;
uSend[2]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);

uSum=0;
for(i=1;i<9;i++)
uSum=uSum+(unsigned char)uSend[i];
uTmp=uSum&0x000f;
uSend[10]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);
uTmp=(uSum>>4)&0x000f;
uSend[9]=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);

 /*disable();*/
for(i=0;i<11;i++)
{    for(lTmp=0L;lTmp<DELAY_TIMES;lTmp++)
{    if((inportb(STATS_PORT)&0x20)!=0)
break;
}
if(lTmp>=DELAY_TIMES)
{
/*enable();*/
return(FALSE);
}

outportb(DATA_PORT,uSend[i]);
}
disable();


for(lTmp=0;lTmp<DELAY_TIMES;lTmp++)
{    if((inportb(STATS_PORT)&1)!=0)
break;
}
if(lTmp>=DELAY_TIMES)
{
enable();
return(FALSE);
}
uReceive[0]=inportb(DATA_PORT);
if(uReceive[0]!=2)
{
enable();
return(FALSE);
}
for(i=1;i<number*4+4;i++)
{    for(lTmp=0L;lTmp<DELAY_TIMES;lTmp++)
{    if((inportb(STATS_PORT)&1)!=0)
break;
}
if(lTmp>=DELAY_TIMES)
{
enable();
return(FALSE);
}
uReceive[i]=inportb(DATA_PORT);
}
enable();
uSum=0;
for(i=1;i<number*4+2;i++)
uSum=uSum+(unsigned int)uReceive[i];
uTmp=uSum&0xf;
uTmp=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);


if((unsigned char)uTmp!=uReceive[number*4+3])return(FALSE);
uTmp=(uSum>>4)&0xf;
uTmp=(uTmp<10)?(uTmp+0x30):(uTmp+0x41-0xa);


if((unsigned char)uTmp!=uReceive[number*4+2])return(FALSE);
for(j=0;j<number;j++)
{    for(i=j*4+1;i<j*4+5;i++)
uReceive[i]=(uReceive[i]>0x39)?uReceive[i]-0x41+0xa:uReceive[i]-0x30;
uRead_value[j]=(((((uReceive[j*4+3]<<4)+uReceive[j*4+4])<<4)+uReceive[j*4+1])<<4)+uReceive[j*4+2];
}
return TRUE;
}

VB
Private Sub Command1_Click()
Dim sendByte(2) As Byte
Dim sendTXT(4) As Byte
Dim Index As Long
Dim Sendstring As String
Dim inString() As Byte
Dim sTime As Single
Dim CRCHi, CRCLo As Byte
Dim i As Integer

Command1.Enabled = False
sendByte(0) = 5
sendByte(1) = Asc("D")
sendByte(2) = Asc("L")
sendTXT(0) = sendByte(0)
sendTXT(1) = sendByte(1)
sendTXT(2) = sendByte(2)
Index = CRC16(sendByte)
CRCLo = Index Mod 256
CRCHi = Index \ 256
sendTXT(3) = CRCLo
sendTXT(4) = CRCHi

MSComm1.InBufferCount = 0
MSComm1.Output = sendTXT
sTime = Timer
Do
DoEvents
If Timer > sTime + 0.01 Then Exit Do
Loop Until MSComm1.InBufferCount > 0

If MSComm1.InBufferCount > 0 Then
inString = MSComm1.Input
If inString(0) = 6 Then
sTime = Timer
Do
 If Timer > sTime + 8 Then Exit Do
Loop
MsgBox "擦除完毕!", vbExclamation, "完成"
Else
MsgBox "擦除失败!", vbExclamation, "提示"
Command1.Enabled = True
Exit Sub
End If
Else
MsgBox "擦除失败!", vbExclamation, "提示"
Command1.Enabled = True
Exit Sub
End If




来自:dracula_king, 时间:2002-06-02 10:54:00, ID:1138393  
SPCOMM的例子

CommName:填写COM1
COM2…等串口的名字
在打开串口前,必须填写好此值。
BaudRate:设定波特率9600,4800等,根据实际需要来定,在串口打开后也可更改波特率,实际波特率随之更改。
ParityCheck:奇偶校验。
ByteSize:字节长度_5 _6 _7 _8等,根据实际情况设定。
Parity:奇偶校验位
StopBits:停止位
SendDataEmpty:这是一个布尔属性,为true时表示发送缓存为空,或者发送队列里没有信息;为False时表示表示发送缓存不为空,或者发送队列里有信息。
2.方法
Startcomm过程用于打开串口,当打开失败时通常会报错,错误主要有7种:
⑴串口已经打开 ;
⑵打开串口错误 ;
⑶文件句柄不是通讯句柄;
⑷不能够安装通讯缓存;
⑸不能产生事件 ;
⑹不能产生读进程;
⑺不能产生写进程;
StopComm过程用于关闭串口,没有返回值。
函数WriteCommData(pDataToWrite: PChar;dwSizeofDataToWrite:Word
): boolean 用于发送一个字符串到写线程,发送成功返回true
发送失败返回false
执行此函数将立即得到返回值,发送操作随后执行。函数有两个参数,其中
pdatatowrite是要发送的字符串,dwsizeofdatatowrite 是发送的长度。
3.事件
OnReceiveData : procedure (Sender: TObject;Buffer: Pointer;BufferLength:Word) of object 
当输入缓存有数据时将触发该事件,在这里可以对从串口收到的数据进行处理。Buffer中是收到的数据,bufferlength是收到的数据长度。
OnReceiveError : procedure(Sender: TObject; EventMask: DWORD)
当接受数据时出现错误将触发该事件。
 三.SPCOMM的使用
下面,我们结合一个串口通讯的例子来说明SPCOMM的使用。
为了实现PC与单片机8051之间的通讯,首先要调通它们之间的握手信号,假定它们之间的通讯协议是,PC到8051一帧数据6个字节
8051到PC一帧数据也为6个字节
当PC发出(F0 01 FF FF 01 F0)后能收到这样一帧(F0 01 FF FF 01 F0),表示数据通信握手成功,两者之间就可以按照协议相互传输数据。在PC方要发送及接受数据需要以下步骤:
1.创建一个新的工程COMM.DPR,把窗体的NAME属性改为FCOMM,把窗体的标题改为测试通讯,添加控件。
对COMM1(黑色矩形围住的控件)进行属性设计,设波特率4800,校验位无,字节长度_8,停止位_1,串口选择COM1。Memo1中将显示发送和接受的数据。选择File/Save
As将新的窗体存储为Comm.pas。
2.编写源代码
变量说明
var
FCOMM: TFCOMM;
Viewstring:string;
i:integer;
rbuf
sbuf:array[1..6] of byte;
打开串口
procedure TFCOMM.FormShow(Sender: TObject);
begin
comm1.StartComm;
end;
关闭串口
procedure TFCOMM.FormClose(Sender: TObject; var Action: TCloseAction);
begin
comm1.StopComm;
end;
发送数据
自定义的发送过程
procedure senddata;
var
i:integer;
commflg:boolean;
begin
viewstring:="";
commflg:=true;
for i:=1 to 6 do
begin
if not fcomm.comm1.writecommdata(@sbuf[i]
1) then
begin
commflg:=false;
break;
end;
sleep(2); {发送时字节间的延时}
viewstring:=viewstring+inttohex(sbuf[i] 2)+" ";
end;
viewstring:="发送"+viewstring;
fcomm.memo1.lines.add(viewstring);
fcomm.memo1.lines.add("");
if not commflg then messagedlg("发送失败!" mterror [mbyes]0);
end;
procedure TFCOMM.Btn_sendClick(Sender: TObject);{发送按钮的点击事件}
begin
sbuf[1]:=byte($f0); {帧头}
sbuf[2]:=byte($01); {命令号}
sbuf[3]:=byte($ff);
sbuf[4]:=byte($ff);
sbuf[5]:=byte($01);
sbuf[6]:=byte($0f); {帧尾}
senddata;{调用发送函数}
end;
接收过程
procedure TFCOMM.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
i:integer;
begin
viewstring:=""; move(buffer^ pchar(@rbuf^) bufferlength);
for i:=1 to bufferlength do
viewstring:=viewstring+inttohex(rbuf[i] 2)+" ";
viewstring:="接受"+viewstring;
memo1.lines.add(viewstring);
memo1.lines.add("");
end;
如果memo1上显示发送F0 01 FF FF 0F 和 接受F0 01 FF FF F0
这表示串口已正确的发送出数据并正确的接受到数据,串口通讯成功。
不行的话联系我,我吧我的程序发给你 QQ:1975722



来自:SS2000, 时间:2002-06-02 11:14:00, ID:1138421  
>>用Spcomm也是不知道怎样将返回的数据还原成看的懂的数据?
不知道什么样的数据你才能看懂??
SPComm返回的是PChar,是字符为单位的指针,你怎样才能看懂?
这个问题和SPComm没有关系,是你自己对计算机的数据表示方式理解不够
>>等到Buffer中有一定个数的字节后再收的功能呢?
这个问题可以做到,如果你想做的话,但是你需要修改SPComm控件,或者说增强SPComm
的功能,因为目前的SPComm做不到
具体方法是在
procedure TReadThread.Execute;函数中
定义有 szInputBuffer: array[0..INPUTBUFFERSIZE-1] of Char;
修改INPUTBUFFERSIZE这个值成为你所要的值,同时把ReadIntervalTimeout属性值
设置为足够大,比如1234567890或者为0,这样在获得指定的字节数之后才会
发出接收消息




来自:dracula_king, 时间:2002-06-02 11:20:00, ID:1138439  
  我的程序可以看懂返回的数据呀,将接收数组定义为BYTE型



来自:SupermanTm, 时间:2002-06-04 00:18:00, ID:1141667  
把数据报文的格式告诉我,我给你源代码,测试后你给我分!
treemanwww@163.com




来自:cook, 时间:2002-06-04 08:23:00, ID:1141835  
我做过一个给自己的下位机测试的程序(c51)
你要的话给你吧。
cook@sina.com



来自:御键飞天, 时间:2002-06-04 10:51:00, ID:1142174  
这是我编写的使用MSComm控件进行串口通讯的完整例子,功能上能进行文本方式,二进制方式的通讯,
在Delphi6下编译通过,在Delphi5下只需将uses单元的Variants项去除即可,如满意,请适当给分,呵呵!
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, OleCtrls, MSCommLib_TLB, ExtCtrls, Menus, Unit2, ComCtrls, ToolWin, ImgList;

type
 TForm1 = class(TForm)
  Panel1: TPanel;
  Memo1: TMemo;
  Splitter2: TSplitter;
  Memo2: TMemo;
  MainMenu1: TMainMenu;
  ComSet1: TMenuItem;
  N1: TMenuItem;
  N2: TMenuItem;
  N4: TMenuItem;
  N5: TMenuItem;
  N6: TMenuItem;
  N7: TMenuItem;
  N8: TMenuItem;
  N9: TMenuItem;
  N10: TMenuItem;
  N11: TMenuItem;
  N12: TMenuItem;
  N13: TMenuItem;
  N14: TMenuItem;
  MSComm1: TMSComm;
  ControlBar1: TControlBar;
  ToolBar1: TToolBar;
  ToolButton1: TToolButton;
  ToolButton3: TToolButton;
  ToolButton4: TToolButton;
  ToolButton5: TToolButton;
  ImageList1: TImageList;
  OpenDialog1: TOpenDialog;
  SaveDialog1: TSaveDialog;
  ImageList2: TImageList;
  StatusBar1: TStatusBar;
  procedure FormCreate(Sender: TObject);
  procedure MSComm1Comm(Sender: TObject);
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  procedure N13Click(Sender: TObject);
  procedure N14Click(Sender: TObject);
  procedure N2Click(Sender: TObject);
  procedure N4Click(Sender: TObject);
  procedure N6Click(Sender: TObject);
  procedure N9Click(Sender: TObject);
  procedure ToolButton5Click(Sender: TObject);
 private
  { Private declarations }
  Recvar:variant;
  BinaryFlag,TextFlag:Boolean;
 public
  { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

Procedure SendBinary(Str:String);
var
 Sendvar:Variant;
 Ch1,Ch2:Char;
 Byte1,Byte2:Byte;
 I:Integer;
begin
 Sendvar:=VarArrayCreate([1,Length(Str) div 2],varByte);
 Byte1:=0;
 Byte2:=0;
 for I:=1 to Length(Str) div 2 do
  begin
   Ch1:=Str[2*I-1];
   Ch2:=Str[2*I];
   if (Ch1>='0') and (Ch1<='9') then
    Byte1:=Ord(Ch1)-48
   else if (Ch1>='A') and (Ch1<='F') then
    Byte1:=Ord(Ch1)-55;
   if (Ch2>='0') and (Ch2<='9') then
    Byte2:=Ord(Ch2)-48
   else if (Ch2>='A') and (Ch2<='F') then
    Byte2:=Ord(Ch2)-55;
   Sendvar[I]:=Byte1*16+Byte2;
  end;
 Form1.MSComm1.Output:=Sendvar;
end;

procedure SendText(Str:String);
begin
 Form1.MSComm1.Output:=Str;
end; 

procedure TForm1.FormCreate(Sender: TObject);
begin
 BinaryFlag:=False;
 TextFlag:=True;
 MsComm1.InBufferCount:=0;
 MsComm1.OutBufferCount:=0;
 MsComm1.InputLen:=0;
 MsComm1.RThreshold:=1;
 MsComm1.SThreshold:=1;
 Recvar:=VarArrayCreate([0,63],varByte);
end;

procedure TForm1.MSComm1Comm(Sender: TObject);
var
 I,J:Integer;
begin
 if MsComm1.CommEvent=2 then //串口事件为接收;
 begin
  if BinaryFlag=True then
  begin
   I:=MSComm1.InBufferCount; //接收缓冲区内已有数据个数;
   MSComm1.InputLen:=I;
   Recvar:=MSComm1.Input;
   for J:=0 to I-1 do
    Memo2.Text:=Memo2.Text+IntToHex(Recvar[J],2);
  end;
  if TextFlag=True then
   Memo2.Text:=Memo2.Text+MsComm1.Input;
  end; 
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if MSComm1.PortOpen=True then
  MSComm1.PortOpen:=False;
end;

procedure TForm1.N13Click(Sender: TObject);
begin
 BinaryFlag:=False;
 TextFlag:=True;
 N13.Checked:=True;
 N14.Checked:=False;
 MSComm1.InputMode:=0; //设置方式为文本方式;
end;

procedure TForm1.N14Click(Sender: TObject);
begin
 BinaryFlag:=True;
 TextFlag:=False;
 N13.Checked:=False;
 N14.Checked:=True;
 MSComm1.InputMode:=1; //设置方式为二进制方式;
end;

procedure TForm1.N2Click(Sender: TObject);
begin
 with Form2 do
 if ShowModal=mrOK then
 begin
  if MSComm1.PortOpen=True then
   MSComm1.PortOpen:=False;
  if RadioButton1.Checked then
   MsComm1.CommPort:=1
  else
   MsComm1.CommPort:=2;
   //设置疮口参数;
   MsComm1.Settings:=ComboBox1.Text+ComboBox2.Text+ComboBox3.Text+ComboBox4.Text;
   //打开串口;
   MsComm1.PortOpen:=True;
  end;
end;

procedure TForm1.ToolButton5Click(Sender: TObject);
begin
 if MSComm1.PortOpen=False then
 begin
  MessageDlg('串口未打开',mtError,[mbOK],0);
  Exit;
 end;
 if BinaryFlag then
  SendBinary(Memo1.Text); //发送二进制方式,注意去除回车换行符;
 if TextFlag then
  SendText(Memo1.Text);  //发送文本方式;
end;

procedure TForm1.N4Click(Sender: TObject);
begin
 if TextFlag=True then
  OpenDialog1.InitialDir:=GetCurrentDir()+'\文本文件夹\';
 if BinaryFlag=True then
  OpenDialog1.InitialDir:=GetCurrentDir()+'\二进制文件夹\';
 OpenDialog1.DefaultExt:='.txt';
 if OpenDialog1.Execute then
  Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
end;

procedure TForm1.N6Click(Sender: TObject);
begin
 if TextFlag then
  SaveDialog1.InitialDir:=GetCurrentDir()+'\文本文件夹\';
 if BinaryFlag then
  SaveDialog1.InitialDir:=GetCurrentDir()+'\二进制文件夹\';
 SaveDialog1.DefaultExt:='.txt';
 if SaveDialog1.Execute then
  Memo2.Lines.SaveToFile(SaveDialog1.FileName);
end;

procedure TForm1.N9Click(Sender: TObject);
begin
 Close;
end;

end.



图
如您对论坛有好的建议或创想,请加大版主微信号:gkong2015
大版主推荐【工控百家谈】微信公众号,业界大拿原创内容分享

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

109.2007