做MODBUS的时候,采用SPCOMM以16进制方式发送数据的有关问题,着

做MODBUS的时候,采用SPCOMM以16进制方式发送数据的问题,着急
我采用串口调试工具,做调试的有十六进制和ASCII两种方式,对这两种方式,还是有点模糊,本质上不是都是二进制吗?或者是有些字符采用ASCII码不好表示,所以采用十六进制方式发送吗?我发送“0101001300150C00”通过串口调试工具,采用十六进制方式发送的时候有响应,采用ASCII方式的时候没响应,这是为什么吗?还有如果我用SPCOMM发送这串数据,采用十六进制方式发送该怎么编写呢?调试了好一会儿了,没响应,接受的也有区别了吧?跟ASCII方式,像下面这种方式就不可以了吧,
var
  TempString:String;

 SetLength(TempString,BufferLength);
  Move(Buffer^,TempString[1],BufferLength);

 showmessage( TempString);

------解决方案--------------------
HEX与ASC是表示方式,最终都是通过二进制发送的;比如发送一个ASC字符‘a’,对应的十六进制0x97,直接发送这个字符即可,接收方如果现实HEX就是0x97,ASC则是‘a’。
------解决方案--------------------
数据不管十进制还是十六进制发到串口都是一种格式,所以无所谓,如果把字符串02 01 0A 03 发过去的话,可以这样变一下: StrToInt(‘$‘+‘02‘) 或 pos(MidStr(trim(MainFrm.PME1.Text),i,1),‘1234567890ABCDE‘);
------解决方案--------------------
Spcomm串口通信的实现

Spcomm串行通信控件具有多线程的特性,接收和发送数据分别在两个线程内完成,接收线程负责收到数据时触发OnReceiveData事件;用WriteCommData()函数将待发送的数据写入输出缓冲器,发送线程在后台完成数据发送工作。在接收和发送数据前需要初始化串口,用StartComm方法打开串口,退出程序时用StopComm方法关闭串口。

实现PC机与单片机之间的数据发送及接收需要以下步骤:

(1)初始化并打开串口

需要选择本次通信使用的串口,确定通信协议,即设置波特率、校验方式、数据位、停止位等属性,打开该串口。示例代码如下:

//初始化并打开串口

Comm1.BaudRate:=9600;//波特率9600bps

Comm1.Parity:=None;//奇偶检验无

Comm1.ByteSize:=8;//数据位8

Comm1.StopBits:=1;//停止位1

Comm1.StartComm; //打开串口

(2)建立握手信号

实现PC机与单片机之间的通信,首先要调通它们之间的握手信号,握手信号可以随意选择某特定字符串, 当PC发出这样一帧数据后,通过接收事件能收到单片机返回的这一帧数据或特定的某字符串,则表示握手成功,系统通信正常。两者之间就可以按照协议相互传输数据。否则需重新建立握手信号。

 (3)发送数据

在编写基于串口的计算机工业测控时,通常需要由PC机向下位机发送命令以控制下位机的行为,同时向下位机发送有关数据。利用Spcomm串口控件向下位机发送数据示例代码如下:

//发送数据和控制字程序

procedure senddata;

var

i:integer; commflg : Boolean;

begin

commflg:=true ;

for i:=1 to 8 do

begin

if not fcomm comml writecommdata(sendbutter,i) then

begin

Commflg=false;

break;

end;

end;

end;

 (4) 接收数据

在编写基于串口的计算机工业测控时,通常需要由下位机向PC机发送数据以使PC机了解系统的测试数据或下位机的运行状态,并进而控制下位机的行为。利用Spcomm串口控件接收下位机发送的数据信息的示例代码如下:

//事件驱动方式接收数据程序

procedure TForm1.CommlReceiveData(Sender:Tobject;

Buffer:Pointer; bufferLength:Word);

var

receivedata:array of byte;

begin

sleep(100);//等待100ms,保证接收到所有数据

move(buffef ,receivedata,bufferlength);

//将接收缓存区中的数据转移到数组中

……

end;

(5) 关闭串口

在系统开发中,应注意在不使用串口时应及时关闭串口,释放系统资源,否则可能会影响系统的其它应用。关闭串口的代码如下:

procedure TForm1.FormClose ( Sender;TObj ect:var Action:TCIoseAction );

begin

comml.StopComm ;

end;

4 Spcomm串口通信的关键技术问题

Spcomm应用的核心在于主线程、读线程和写线程之间的消息传递机制,而通信数据相关信息的传递也是以消息传递的方式进行的。在使用Spcomm进行串口通信编程,除按照说明使用外,还需要特别注意以下两个问题。

首先,Spcomm是通过ReadIntervalTimeout属性的设置,来确定所接收到的数据是否属子同一帧数据,其默认值是100ms,也就是说,只要任何两个字节到达的时间间隔小于1OOms,都被认为是属于同一帧数据,在与单片机协同工作时,要特别注意这个问题[2]。

另外,Spcomm的默认属性设置是支持软件流控制的,用于流控制的字符是13H(XoffChar)和11H(XonChar),当单片机以二进制方式发送数据时,必须要禁用Spcomm对于软件流控制的支持,否则,在数据帧中出现的13H,11H会被Spcomm作为控制字符而加以忽略。


------解决方案--------------------
跟你下位机有关,一般都只接受整数数据,不接受字符数据,其实也接收,只不过命令就对不上了,当然都是二进制,但是值是不一样的,比如你传的使六进制是$A,十进制值就是10,你传字符串A,十进制值就是65,所以就会造成命令对不上了,当然不会有正常的响应
------解决方案--------------------
1、弄清楚下位机支持的modbus功能码
比如01号是干啥的,这样才能有的放矢
2、弄清楚报文格式,如果是标准的modbus协议,按着标准的来
3、如你所说,用串口调试工具,打开端口,发送数据
最好用十六进制,这样也好看些,按照报文发送
4.、下位机收到数据会有返回的,modbus最后两位是crc16校验码
这个需要自己写个算法,或者网上搜,
5、串口调试成功呢,根据调试编码