既然需要通过串口来与短信modem进行通讯,就需要一个串口通讯控件,这里我使用了微软的mscomm32.ocx串口通讯控件。具体实现方法是通过对mscomm32.ocx的几个属性设置(串口端口设置、发送数据类型设置、读写缓冲区设置等)来达到串口与短信modem进行通讯的目的,然后对输入的短信息进行编码,把编码后的短信息发送至短信modem,再通过AT指令去控制modem的发送。整个软件由三个程序组成,一是发送主程序,二是短信编码程序,三是串口通讯控件,下面作一一介绍。
一、串口通讯控件
二、短信的编码
短信息是文本信息,短信modem只支持ASCII格式码的文本信息,ASCII码格式包括英文字母A-Z和数字0-9及一些标点符号等字符,为此对于中文短信息必须通过编码使中文变成ASCII码,短信编码有三种模式:BLOCKMODE、基于AT指令的TEXTMODE和基于AT指令的PDUMODE的编码,西门子6688手机支持PDUMODE的编码,这种编码方式是把短信正文经过16进制编码后发送。PDU的编码又分为7bit编码、8bit编码和16bit编码,7bit编码最多可发送160个字符,8bit编码最多可发送140个字符,而16bit编码最多可发送70个字符,这种编码被用显示Unicode(UCS2)文体信息,可被大多数手机显示,所以这里我采用的是UCS2编码,其最多可发送70个字符,不管是英文还是中文。
一条短信由三部分组成,一是接收方的手机号码,二是短信中心号码,三是短信内容。在实际的编码过程中,这三部分是分开来进行的,最后再把它们合三为一。
⑴、短信中心号码编码
首先把短信中心号码的奇数位与偶数位互换,然后看其长度是否为偶数,如果不是,在最后添加F,并对最后一位与F互换位置。接着在号码前加上91,相当于加上一个"+"字符。最后计算编码后的总长度并除以2,并把这个数格式化为二位的16进制数。例如:广州的短信中心号码为8613800200500,编码后为0891683108200005F0,08是91683108200005F0的长度除2,即16/2=8,二位16进制表示就是08。
㈡、接收方手机号码编码
首先检查当前接收方手机号码的前两位是否有86字样,如果没有就补上86,然后奇偶位互换,最后检查整个长度是否为偶数,如果不是就加上F,并对最后一位与F互换位置,如手机号码为13918765434,编码后为683119785634F4。
㈢、短信内容编码
首先采用Big-Endian字节顺序的Unicode格式编码,即高低位互换,接着把它存入一个字节数组,然后去掉进行Unicode编码过程中的“-”字符,最后把整条编码好后的短信内容长度除2,并格式化成二位16进制数添加到编码后的短信内容前面。
例如,短信内容为:你好,HELLO!,编码后为:4F60597DFFOC00480065006C006C006F0021,最后根据国内PDU编码的原则在接收手机号编码前加上11000D91,在短信内容前加上000800,并把以上三部分编码串起来即可。
三、AT指令
AT指令类似于DOS命令,由命令与一些参数组成,来完成对modem实现某一功能的控制。AT指令有很多个,它的基本格式是AT+操作功能符+回车,我编写的这款短信发送软件实际只使用了两个AT指令,分别是:AT+CSCA和AT+CMGS,前一个是获取存于手机SIM卡里面的短信中心号码的命令,后面一个是发送一条短信命令。通常向modem发送一个AT指令,modem如果执行完成都会有一个执行结果回送。
四、短信发送软件主程序
下面是主程序的代码,图1是主程序的运行界面
PDUdecodingsms=newPDUdecoding();
MSCommcom=newMSComm();
Threadt,w;
private
{
xiancheng1();
}
voidxiancheng1()//连接串口
t=newThread(newThreadStart(InitCom));//定义连接线程
t.Start();//启动线程
privateboollianjie(stringduankou,stringbotelv)
try
stringdk=duankou.Trim().Substring(3);
if(com.PortOpen==true)com.PortOpen=false;
com.CommPort=Convert.ToInt16(dk);//串口号
com.InputMode=MSCommLib.InputModeConstants.comInputModeText;//传输的数据形式是文本
com.InputLen=0;//读取整个接收缓冲区内容
com.Settings=botelv+",N,8,1";//串口基本参数设置
com.PortOpen=true;//打开串口
com.OutBufferCount=0;//清空发送缓冲区
com.InBufferCount=0;//清空接收缓冲区
returntrue;
catch
MessageBox.Show("错误:连接参数有错,请重新选择!");
returnfalse;
voidInitCom()
inti;
if(lianjie(duankou.SelectedItem.ToString(),bote.SelectedItem.ToString()))
stringBuffer="";
stringbufy="AT+CSCA\r";
for(i=0;i<5;i++)
com.Output=bufy;//发送数据到串口发送缓冲区
Buffer+=com.Input;//接收串口接收缓冲区的数据
break;
if(i>4)
label5.Text="连接失败,重新连接!!";
else
intNum1=Buffer.LastIndexOf("86");
zhongxinhao.Text=Buffer.Substring(Num1,13);
label5.Text="连接成功!!";
com.PortOpen=false;
t.Abort();
privatevoidbutton2_Click(objectsender,System.EventArgse)
Application.Exit();
voidfsduanxin()
w=newThread(newThreadStart(fs));//定义发送线程
w.Start();//启动线程
privatevoidbutton3_Click(objectsender,System.EventArgse)
fsduanxin();
voidfs()
stringdhnum=shoujihaoma.Text;
fsdx(dhnum);//发送短信
w.Abort();
voidfsdx(stringdanhuahaoma)//发送短信程序段
inti=0;
duanxinshoufa.Text="正在发送,稍候";
stringdecodedSMS=sms.smsDecodedsms(zhongxinhao.Text,danhuahaoma,neirong.Text);
stringbufy="AT+CMGS="+sms.nLength+"\r";
for(i=0;i<10;i++)
com.Output=bufy;
Thread.Sleep(300);
Buffer+=com.Input;
Thread.Sleep(500);
if(Buffer.Length>0&&Buffer.EndsWith(">"))//判断AT指令执行的回送结果
stringbuf=decodedSMS+"\x01a";
com.Output=buf;
Thread.Sleep(1000);
stringchenggong="发送成功!";
stringResult=String.Format("{0},{1},{2}。\n",danhuahaoma,neirong.Text,chenggong);
duanxinshoufa.Text+="\r\n"+Result;
duanxinshoufa.Text+=".";
if(i>9)
duanxinshoufa.Text="发送失败,请重新发送!";
在程序中使用了线程控制,目的是协调程序运行与串口通讯之间的同步问题。另外在主程序中使用AT指令时都使用了循环,通过对AT指令执行结果回送的检测,判断AT指令是否被正确地执行,如果未被正确执行,则通过循环控制重发AT指令直至AT指令正确执行为止。
1、此程序我只在西门子6688,SL45i手机上成功应用。
2、此程序是在.NET平台上开发的,所以要在你的电脑上安装ms.net.framework1.1,这是一个免费软件,网上有下载。
3、程序中所使用的mscomm32.ocx控件需要注册,注册步骤如下:
①、将Mscomm32.ocx,Mscomm32.dep两个文件复制到系统SYSTEM32文件夹中。
②、用Windows下的注册工具regsvr32注册该OCX控件,点击“开始”->"运行",再在其中填入Regsvr32C:\windows\system32\Mscomm32.ocx。
③、在注册表中手工新建一个主键项:先在点击“开始”->"运行",再在其中填入regedit命令打开注册表,找到HKEY_CLASSES_ROOT\Licenses,在其中添加主键:4250E830-6AC2-11cf-8ADB-00AA00C00905并将内容设置为:kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun。