串口编程-----要命的乱码问题,那位兄弟能拔刀相助!!不胜感激(200分)

  • 主题发起人 主题发起人 xielei
  • 开始时间 开始时间
X

xielei

Unregistered / Unconfirmed
GUEST, unregistred user!
背景:
对RS232串口编程,下位机通过串口传输数据,不过这些传输过来的数据中有汉字,
这一点比较特殊。通讯协议比较简单,首先下位机发一个01H过来,电脑如果接收到数
据01H,就返回01H给下位机,如果不是就返回03,或则04H 。下位机接收到电脑返回的01H
后,就开始发送数据,数据格式为:H001报警器 05通道 001 烟探测器 报火警 2001-
03-10 11:01:23 A001区 总经理室 回车符,换行符,校验字符,总共74个字节。
电脑接收下位机传送过来的数据以后自己要把头一个字节(表示信息主体的长度,比如H其
实就是72,表示后面的信息主体长度为72)解释成整形,比如72,而最后的一个字节是校验
字节,它是前面73个字节的ASCII值的类加,如果电脑这边把信息的千73个字节的ASCII值类
加等于最后一个字节的大小,那么就返回02H给下位机器,否则返回一个03给下位机。


出现的问题:
能够正确接受01H, 但是接收01H的同时也接收到FF,不知道什么原因,返回01H给下位机
后接受到的信息是乱码,如:H ? "? 仛 ?U+饦64=?腊雅?浓眇警?? 訷#F?1亰d?4?6 Q
4褬9轻? U?ā?5れ?
而且长度也不对,有的时候是79,80,有时又是81等。
供应商给我们一个测试程序,运行在Dos环境下,是用C语言写的,程序代码如下:
#include <string.h>
#include <time.h>
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <math.h>
#include <bios.h>
#include <graphics.h>
#include <io.h>
int intport2,statuport2,dataport2;
void init_comm(char num)
{int k;
k=inportb(0x21);
outportb(0x21,0xff); //DISABLE INTERRUPT
disable();
if(num==2)
{intport2=0x3f9;
dataport2=0x3f8;
statuport2=0x3fa;
outportb(statuport2+1,0x80); // SET DLAB=1
outportb(dataport2,0x18); //SET LOW DATA 1843200/(num*16) BAUD RATE=4800
outportb(intport2,0x00); //SET HIGH DATA
outportb(statuport2+1,0x2b); //LCR: N81
outportb(statuport2+2,0x0b); //SET MODEM (DTR,RTS) STATUS
outportb(intport2,0x00); //SET DALB=0
}
enable();
outportb(0x21,k&amp;0xc7);
}

void main()
{ char add=0,data_num=0,n;
int num=0,key=0,flag=1;
int k;
unsigned char data;
char cc[300];
printf("Wait...");
init_comm(2);
printf("ok %c%c",0x0d,0x0a);
while(key!=0x1b)
{if(bioskey(1))
key=bioskey(0)&amp;0xff;
k=inportb(statuport2+3);
if(k&amp;1)
{data=inportb(dataport2);
switch(flag)
{case 1:if(data==1)
{outport(dataport2,1);
flag=2;
}
break;
case 2:data_num=data;add=data;
if(data_num>0) flag=3;
else flag=1;
n=0;
break;
case 3:cc[n++]=data; add+=data;
data_num--;
if(data_num==0)
{flag=4;
}
break;
case 4:if(add==data)
{outport(dataport2,2);
cc[n]=0;cputs(cc);
}
else outport(dataport2,3);
flag=1;
break;
default:flag=1;break;
}
}
}
}


这个程序接受数据是正确的,我用Delphi5.0写了一个测试程序,但是结果是上面的那些情况,通讯用的串口的设置没有错误,设置为4800,N,8,1。我用的串口控件是Spcomm,程序如下:
unit Main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, SPComm;

type
TForm1 = class(TForm)
Label1: TLabel;
Comm1: TComm;
Memo1: TMemo;
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
sChecK:array[0..200] of char;
Flag:integer=1;
Num,n:integer;
//ch:byte;
add:shortint;
implementation

{$R *.DFM}
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
sReceive: byte;
iCount:integer;
sRec:string;
begin
case Flag of
1:
begin

Move(pchar(Buffer)^,sReceive,1);

if sReceive=1 then
begin
// bSend:=chr(1);
Comm1.WriteCommData(chr(1),1);
Memo1.Lines.Add(IntTohex(ord(sReceive),2));
Flag:=2;
exit;
end;
end;
2: begin
Move(pchar(Buffer)^,sReceive,1);
add:=sReceive;
Num:=sReceive;
if Num>0 then
begin
Move((pchar(Buffer)+1)^,sCheck,Num);//pchar(sRec)^,Num);
for iCount:=0 to Num-1 do
add:=ShortInt(add)+byte(ord(sCheck[iCount]));//(ord(sRec[iCount]));

sCheck[Num]:=chr(0);

Memo1.Lines.Add(StrPas(sCheck));

Move((Pchar(Buffer)+Num+1)^,sReceive,1);
if add=ShortInt(sReceive) then
begin
comm1.WriteCommData(chr(2),1);
Memo1.Lines.Add(IntToStr(add));
end
else
Comm1.WriteCommData(chr(3),1);
Flag:=1;
exit;
end;
Flag:=1;
n:=0;
exit;
end;
end;

请各位兄弟帮帮忙,先谢过了
 
请用SPComm或Cport试一下.
 
sCheck是怎么定义的?
flag初始化了没有,正确吗?
应该是flag=2之后的代码有问题,好好查查
 
干嘛不把C的源程序直接改过来用?我大略看了一下,可以的
 
To donkey:
sCheck:array[0..200] of char;
Flag:integer=1;

To dongberlin:
我用的控件是Spcomm,Cport没有用过。
 
你可以在调试时察看buffer里的数据是否是正确的
 
你最好为发送数据缓冲区声明一个全局变量,而且是动态数组,否则会很容易出现乱码。
 
先检查串口的停止位、速率、奇偶校验、数据位这些值有没有与下位机对应了?
 
对串口操作用SPCOMM真的好爽,在写的时候要注意要延时,在读的时候最好有自定义的校验
码非常实用,如要发3435,我所做的方式是《DATA》3435?《END》,?是自定对前面4个数
字的校验,试试,挺好的。
 
朋友,你是不是沈阳的,我也是,你说的是不是沈阳消防.....我在那干过一小小小段,由于一些原因不干了,可以找我大家一起研究研究,yangxiangjun@sohu.com
 
呵呵,你的程序根本没有理会BufferLength这个参数,怎么会正确
 
我该如何理会bufferLength请详细指点:
 
后退
顶部