串口编程 解析接收的短消息 ( 积分: 20 )

  • 主题发起人 主题发起人 mawei0913_green
  • 开始时间 开始时间
还是在等。。。。
 
各位高人,菜鸟在等呀,还请各位高人能给与帮助!谢谢
 
可以考虑循环取,取到结束!
 
你先要判断读的是否是一条完整的短信,串口读的时候应该有“OK”返回,然后再判断是否解析短信时出了问题。我做过这方面的,不管是7位编码还是其它的肯定是没有问题的
 
同意jsxh0523的说法。
先看收得怎样,再看解得怎样,janker 也是这个意思。前面几位总是在解析上面绕,
会不会走弯路了?
串口和短信我也做过,没遇到这样的问题。
建议你先用串口检测程序,直接发送AT命令,看看读全了没有?我那时就是这样调试的
 
Anylib推出6.0版本!!!

自由灵活,所见即所得的表格组件,开发环境下设计表格内容,独有的单据和Excel两种界面风格,可设计出各种类型的界面,配合强劲的打印功能,轻松解决自由界面和报表难题。其显著特性包括:

01. 提供了单据, Excel ,Grid 三种界面风格。
02. 开发环境下设计表格,所见即所得。
03. 缩放打印和批量套打
04. 支持数据库和分组。
05. 既可以作为普通表格使用,又可以作为数据感知组件使用,或者两者同时使用。
06. 独特的双数据源连接,轻松实现单记录布局和主从表连接。
07. 除了通过数据集本身的方法来访问数据库的记录之外,还可以通过读取单元格的Text属性来实现,这样就不必在数据集间来回移动记录。
08. 支持unicode文本。
09. 提供了列排序,移动行列,隐藏行列,增删行列等功能。
10. 提供了 Excel 样式的过滤功能。
11. 方便的查找对话框。
12. 提供了单元格合并,单元格命名,只读单元格,锁定单元格等功能。
13. 提供了列对象,用于控制整列单元格。
14. 支持虚表,公式(包括自定义公式), RTF 格式文本,Ole 对象和图表。
15. 提供了按钮、下拉框、复选框、单选钮、日期、超链接、数值类等多种输入方式。
16. 支持整形、正整形、负整形、浮点数、正浮点数、负浮点数等输入方式。可自动处理千分位,可设置小数位数。
17. 九种文本和图形对齐方式,还可通过单元格边距控制输出位置。
18. 导入/导出 Excel 文件,相互粘贴数据。
19. 提供了自动调整行高,垂直文本输出功能。
20. 可以设置单元格掩码,附有掩码编辑器。
21. 设置单元格的 PasswordChar。
22. 单元格内容字符数限制。
23. 单元格支持图形,并且可以拉伸,层叠图形。
24. 可以显示/隐藏单元格的边框、可以设置边框的类型、大小、颜色。
25. 支持单元格斜线。
26. 3D 外观的单元格。
27. 设置单元格的光标和提示。
28. 支持自绘画单元格。
30. 设置固定行和列。
31. 保存到文件和流。
32. 提供了复制/粘贴区域功能。
33. VCL 版本可以插入其它可视 VCL 组件。


http://www.anylib.com
 
还有个奇怪的问题是:若是小灵通发送>=7长度的内容时,可以接收长度大约7的内容,请高人指教了,郁闷了!
 
和7byte解码有关吗
function TForm_Main.GsmAlphabetDecode(s: string): string;
var
c, j, i : integer;
t : string;
begin
//转化PDU串为二进制串

t := '';
i := 1;
while i <= Length(s) - 1 do
begin
t := t + Chr(StrToInt('$' + Copy(s, i, 2)));
i := i + 2;
end;

//解码
//解码标准见PDU 7bit编码说明
Result := '';
j := 1;
i := 0;
c := 0;
while (j <= Length(t)) and (i < 7) do
begin
if i < 7 then
begin
c := (Integer(t[j]) shl i) or c;
j := j + 1;
i := i + 8;
end;

Result := Result + Char(c and $7f);
c := c shr 7;
i := i - 7;
end;
end;
请高人指教了
 
帮你顶一个,随便发个交流群:
这里菜鸟云集,高手成群!
delphi交流群:4654765(delphi天堂)欢迎您的加入!让我们共同进步!!
加入者必须改名片为:{地点}+姓名 注:不改者勿扰!
 
菜鸟现把解码列出来,请各位指教
AT+CMGF=0

OK
AT+CNMI=2,3,0,2,1

OK
AT+CPMS=&quot;SM&quot;

+CPMS: 0,30,0,30

OK
AT+CMGL=4

OK
20071009152905 : AT+CMGD=1,4
AT+CPMS=&quot;SR&quot;

ERROR
AT+CMGL=4

ERROR
AT+CMGD=1,4

ERROR
20071009152914 : OK
20071009152942 : +CMTI: &quot;SM&quot;,1
20071009152942 : AT+CPMS=&quot;SM&quot;

+CPMS: 1,30,1,30

OK
AT+CMGR=1
AT+CMGD=1

ERROR
20071009152942 : +CMGR: 0,,27
0891683108100005F0240D91685118500943F700007001905192732308315A2C1683CD70

OK
20071009152942 : 接收:15810590347,07-10-09 15:29:37,1411103
20071009152943 : 发送:15810590347,您所查询的结算号不存在,请重新查询或打电话咨询
20071009152943 : AT+CMGS=113
0091
> 000D91685118500943F70008016260A8624067E58BE276847ED37B9753F74E0D5B585728FF0C8BF791CD65B067E58BE26216625375358BDD54A88BE2FF1A003000310030002D00380032003500360032003000330033002C003000310030002D00380032003500360032003000320032
20071009152948 : +CMGS: 3

OK

//这里我发送的内容为14111038,但是却显示1411103
 
你的解码程序有问题。

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
FCountryCode: string;
function ParseAPDUMessage(const sPDUMsg: string; var sGSMCenter,
sMobile, sMsg,
sTimeStamp: string;
var iType: integer; var bFreeHand, bBackCall,
bFlashSMS: boolean): Boolean;
public
{ Public declarations }
end;

var
Form1: TForm1;

function StrToBoolean(const Value: string): boolean;
function PDUToString7Bit (v : string) : string;
function PDUToStringUCS2 (v : string) : string;
implementation

{$R *.dfm}

function StrToBoolean(const Value: string): boolean;
begin
Result := Value = '1';
end;
function PDUToString7Bit (v : string) : string;
var
I, InLen, OutLen, OutPos : Integer;
TempByte, PrevByte : Byte;
begin
{ Check for empty input }
if v = '' then Exit;

{ Init variables }
PrevByte := 0;
OutPos := 1;

{ Set length of output string }
InLen := Length(v);
Assert(InLen <= 140, 'Input string greater than 140 characters');
OutLen := (InLen * 8) div 7;
SetLength(Result, OutLen);

{ Encode output string }
for I := 1 to InLen do begin
TempByte := Byte(v);
TempByte := TempByte and not ($FF shl (7-((I-1) mod 7)));
TempByte := TempByte shl ((I-1) mod 7);
TempByte := TempByte or PrevByte;
Result[OutPos] := AnsiChar(TempByte);
Inc(OutPos);

{ Set PrevByte for next round (or directly put it to Result) }
PrevByte := Byte(v);
PrevByte := PrevByte shr (7-((I-1) mod 7));
if (I mod 7) = 0 then begin
Result[OutPos] := AnsiChar(PrevByte);
Inc(OutPos);
PrevByte := 0;
end;
end;
if Result[Length(Result)] = #0 then
Result := Copy(Result, 1, pred(Length(Result)));
end;
function PDUToStringUCS2 (v : string) : string;
var
i,len,j:Integer;
t:String;
begin
Result:='';
len:=Length(v);
i:=1;
while i<=len do begin
t:=Copy(v,i,4);
j:=StrToInt('$'+t);
t:=widechar(j);
Result:=Result+t;
i:=i+4;
end;
end;

function TForm1.ParseAPDUMessage(const sPDUMsg: string; var sGSMCenter,
sMobile, sMsg,
sTimeStamp: string;
var iType: integer; var bFreeHand, bBackCall,
bFlashSMS: boolean): Boolean;
var
sNext, sTmp, St, sCodec: string;
iNumLength, I, TempI: integer;
bHasUDHI, bIsStatusReport: boolean;
begin
try
sNext := sPDUMsg;
iNumLength := StrToInt(Copy(sNext, 0, 2));
I := 0;
//NumLength is length of center number, in octets
if iNumLength > 0 then
begin
// Next two digits is Type-of-Address octet
I := StrToInt(Copy(sNext, 3, 2));
// I is the Type-of-Address octet
case I of
91 : begin

end;
81 : begin

end;
end; // End Case
// NumLength = length of center phone number
sTmp := '';
I := 5;
while I < (iNumLength * 2 + 3) do
begin
if sNext = 'F' then
sTmp := sTmp + sNext[I+1]
else
sTmp := sTmp + sNext[I+1] + sNext;
I := I + 2;
end;
// TempStaID is the Center Address at this point
sGSMCenter := sTmp;
end
else
begin
sNext := Copy(sNext, 3, Length(sNext));
end;
// TempI = octet is First Octet of SMS-Deliver PDU
TempI := StrToInt(Copy(sNext, I, 2));
// Get next octet
sNext := Copy(sNext, I + 2, Length(sNext));
St := Copy(sNext, 0, 2);
bHasUDHI := (TempI and $40) = $40;
bBackCall := (TempI and $80) = $80;
bIsStatusReport := (TempI and $02) = $02;
if not bIsStatusReport then
begin
case TempI of
4 : begin // This PDU is a SMS delivery

end;
11: begin // Message ready to send
if St = '00' then begin
// The &quot;00&quot; lets the phone set the message reference number.
sNext := Copy(sNext, 3, Length(sNext));
St := Copy(sNext, 0, 2);
end;
end;
24: begin // Status report indication returned

end;
end; // End Case
//Address-Length. Length of the sender number (0B hex = 11 dec)
iNumLength := (StrToInt('$' + St));
// Next two digits is Type-of-Address octet
I := StrToInt('$' + Copy(sNext, 3, 2));
case I of
133 : begin
// 85 in Hex = Voice mail ?
end;
145 : begin
// 91 in Hex
end;
129 : begin
// 81 in Hex
end;
200 : begin
// C8 in Hex
end;
end; // End Case
// NumLength = Length of phone number
sTmp := '';
if Odd(iNumLength) then
iNumLength := iNumLength + 1;
// Change NumLength to Octets
iNumLength := iNumLength Div 2;
I := 5;
while I < (iNumLength * 2 + 5) do begin
if sNext = 'F' then
sTmp := sTmp + sNext[I+1]
else
sTmp := sTmp + sNext[I+1] + sNext;
I := I + 2;
end;
// TempStaID is the StationID at this point
if Copy(sTmp, 1, Length(FCountryCode)) = FCountryCode then //remove the countrycode
sTmp := Copy(sTmp, Length(FCountryCode) + 1, Length(sTmp));
sMobile := sTmp;
// Protocol identifier of &quot;00&quot; and Data coding scheme of &quot;00&quot;
// are the 2 octets or the 4 added to I, below
sTmp := Copy(sNext, I, 2);
bBackCall := sTmp = '5F';
sCodec := Copy(sNext, I + 2, 2);
I := I + 4; // start of time stamp
St := '';
if sNext = 'A' then begin
// No time stamp - not sent yet
TempI := I + 2;
end else begin
St := sNext[I+1] + sNext + '/' + // Year
sNext[I+3] + sNext[I+2] + '/' + // Month
sNext[I+5] + sNext[I+4] + ',' + // Day
sNext[I+7] + sNext[I+6] + ':' + // Hours
sNext[I+9] + sNext[I+8] + ':' + // Minutes
sNext[I+11] + sNext[I+10] + '+' + // Seconds
sNext[I+13] + sNext[I+12]; // Time Zone
// 14 is length of time stamp - Keeping track where we are in TempS
TempI := I + 14;
sTimeStamp := St;
end;
// Get next octet
St := sNext[TempI] + sNext[TempI + 1];
// MessageLength
// iMessageLength := StrToInt('$' + St);
// U is the message
sNext := Copy(sNext, TempI + 2, Length(sNext));
// NumLength is the length of the message
iNumLength := Length(sNext);

sTmp := Copy(sCodec, 1, 1);
bFreeHand := StrToBoolean(sTmp);
if Copy(sCodec, 2, 1) = '0' then
begin
iType := 0;
// Change message to string form
// Set pointer to start of message
if Copy(sNext, 1, 4) = '0001' then
begin
bFlashSMS := True;
sNext := Copy(sNext, 5, iNumLength);
Dec(iNumLength, 4);
end;

if bHasUDHI then
begin
sCodec := Char(StrToInt('$' + Copy(sNext, 13, 2)) shr 1);
sNext := Copy(sNext, 15, iNumLength);
Dec(iNumLength, 14);
end;
I := 1;
sTmp := '';
while I < iNumLength do begin
St := '$' + sNext + sNext[I+1];
TempI := StrToInt(St);
sTmp := sTmp + Char(TempI);
I := I + 2;
end;
sNext := PDUToString7Bit(sTmp);
if bHasUDHI then
sNext := sCodec + sNext;
end
else if Copy(sCodec, 2, 1) = '8' then //汉字
begin
iType := 1;

if Copy(sNext, 1, 4) = '0001' then
begin
bFlashSMS := True;
sNext := Copy(sNext, 5, iNumLength);
Dec(iNumLength, 4);
end;
if bHasUDHI then
begin
sNext := Copy(sNext, 13, iNumLength);
Dec(iNumLength, 12);
end;

sNext := PDUToStringUCS2(sNext);
end
else if sCodec = '15' then //二进制 60029339
begin
iType := 2;
if bHasUDHI then
begin
sNext := Copy(sNext, 13, iNumLength);
Dec(iNumLength, 12);
end;
end;

// if iMessageLength = Length(sNext) then
// Store message
sMsg := sNext;
end
else
begin
Result := True;
end;
Result := True;
except
Result := False;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
sGSMCenter, sMobile, sMsg, sTimeStamp: string;
iType: integer;
bFreeHand, bBackCall, bFlashSMS: boolean;

begin
FCountryCode := Edit1.Text;
ParseAPDUMessage(Memo1.Text, sGSMCenter, sMobile, sMsg, sTimeStamp, iType, bFreeHand, bBackCall, bFlashSMS);
Memo2.Lines.Add(sGSMCenter);
Memo2.Lines.Add(sMobile);
Memo2.Lines.Add(sMsg);
Memo2.Lines.Add(sTimeStamp);
end;

end.
 
TO anewed:
高人还在吗,还请明示
 
我用c#做过类似模块,没有用现成的短信接收控件,是自己编程在串口事件接收数据。
开始时也遇到过接收数据不全的情况。后来发现串口接收事件每次接收到的字符数量
不固定的,要自己编程去合并接收到的字符,自己编程去判断是否接收完一整条短信
消息。我花了好多天时间才写完善该模块(pdu解码部分是网上下的,自己修改了一下,
串口接收事件中的数据处理则是自己编写的)
你代码中DecodeRecvData是响应串口接收事件吗?
 
TO :prg8848
是响应串口接收事件的
 
我的意思是你接收到的数据是正确的,只不过解析函数中将最后一位给丢了。
 
还没结束?
 
GSM短信远程抄表系统管理端源代码(pc控制手机模块收发GSM短信)
http://www.pgz8.cn/Software/Catalog93/4151.html

串口操作等,都是自己写的代码.不用现成控件的.可能对你有帮助.
 
接受答案了.
 
后退
顶部