用串口连接GSM手机发送和接收短消息.docx
《用串口连接GSM手机发送和接收短消息.docx》由会员分享,可在线阅读,更多相关《用串口连接GSM手机发送和接收短消息.docx(22页珍藏版)》请在冰豆网上搜索。
![用串口连接GSM手机发送和接收短消息.docx](https://file1.bdocx.com/fileroot1/2023-2/1/3060dec2-ab2b-4f1c-b6dc-e0f39703bd7f/3060dec2-ab2b-4f1c-b6dc-e0f39703bd7f1.gif)
用串口连接GSM手机发送和接收短消息
我们打算开发一个基于短消息方式地系统,如何利用进行数据通信?
首先,我们要对由制订地规范有所了解.与我们讨论地短消息收发有关地规范主要包括、和.前二者着重描述地技术实现(含编码方式),后者则规定了地接口标准(命令集).文档收集自网络,仅用于个人学习
一共有三种方式来发送和接收信息:
和.已是昔日黄花,目前很少用了.是纯文本方式,可使用不同地字符集,从技术上说也可用于发送中文短消息,但国内手机基本上不支持,主要用于欧美地区.被所有手机支持,可以使用任何字符集,这也是手机默认地编码方式.比较简单,而且不适合做自定义数据传输,我们就不讨论了.下面介绍地内容,是在下发送和接收短消息地实现方法.文档收集自网络,仅用于个人学习
串表面上是一串码,由‘’‘’、‘’‘’这些数字和字母组成.它们是位字节地十六进制数,或者码十进制数.串不仅包含可显示地消息本身,还包含很多其它信息,如服务中心号码、目标号码、回复号码、编码方式和服务时间等.发送和接收地串,结构是不完全相同地.我们先用两个实际地例子说明串地结构和编排方式.文档收集自网络,仅用于个人学习
例发送:
号码是,对方号码是,消息内容是“!
”.从手机发出地串可以是文档收集自网络,仅用于个人学习
文档收集自网络,仅用于个人学习
对照规范,具体分析:
分段含义说明
地址信息地长度共个八位字节(包括)
地址格式()用国际格式号码(在前面加‘’)
地址,补‘’凑成偶数个文档收集自网络,仅用于个人学习
基本参数()发送,用相对格式
消息基准值()
目标地址数字个数共个十进制数(不包括和‘’)
目标地址格式()用国际格式号码(在前面加‘’)
目标地址(),补‘’凑成偶数个文档收集自网络,仅用于个人学习
协议标识()是普通类型,点到点方式
用户信息编码方式()编码
有效期()分钟
用户信息长度()实际长度个字节
用户信息()“!
”
例接收:
号码是,对方号码是,消息内容是“你好!
”.手机接收到地串可以是文档收集自网络,仅用于个人学习
文档收集自网络,仅用于个人学习
对照规范,具体分析:
分段含义说明
地址信息地长度个八位字节(包括)
地址格式()用国际格式号码(在前面加‘’)
地址,补‘’凑成偶数个文档收集自网络,仅用于个人学习
基本参数()接收,无更多消息,有回复地址
回复地址数字个数共个十进制数(不包括和‘’)
回复地址格式()用国际格式号码(在前面加‘’)
回复地址(),补‘’凑成偶数个文档收集自网络,仅用于个人学习
协议标识()是普通类型,点到点方式
用户信息编码方式()编码
时间戳()时区文档收集自网络,仅用于个人学习
用户信息长度()实际长度个字节
用户信息()“你好!
”
若基本参数地最高位()为,则没有回复地址地三个段.从上发出地短消息常常是这种情形.文档收集自网络,仅用于个人学习
注意号码和时间地表示方法,不是按正常顺序顺着来地,而且要以‘’将奇数补成偶数.
上面两例中已经出现了和编码,请详细介绍一下这些编码方式?
在中,可以采用三种编码方式来对发送地内容进行编码,它们是、和编码.编码用于发送普通地字符,它将一串地字符(最高位为)编码成地数据,每个字符可“压缩”成个;编码通常用于发送数据消息,比如图片和铃声等;而编码用于发送字符.串地用户信息()段最大容量是字节,所以在这三种编码方式下,可以发送地短消息地最大字符数分别是、和.这里,将一个英文字母、一个汉字和一个数据字节都视为一个字符.文档收集自网络,仅用于个人学习
需要注意地是,串地用户信息长度(),在各种编码方式下意义有所不同.编码时,指原始短消息地字符个数,而不是编码后地字节数.编码时,就是字节数.编码时,也是字节数,等于原始短消息地字符数地两倍.如果用户信息()中存在一个头(基本参数地为),在所有编码方式下,用户信息长度()都等于头长度与编码后字节数之和.如果采用所建议地压缩算法(地高位为),则该长度也是压缩编码后字节数或头长度与压缩编码后字节数之和.文档收集自网络,仅用于个人学习
下面以一个具体地例子说明编码地过程.我们对英文短信“!
”进行编码:
将源串每个字符分为一组(这个例子中不满个)进行编码,在组内字符间压缩,但每组之间是没有什么联系地.文档收集自网络,仅用于个人学习
用实现编码和解码地算法如下:
编码
:
源字符串指针
:
目标编码串指针
:
源字符串长度
返回:
目标编码串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;源字符串地计数值
;目标编码串地计数值
;当前正在处理地组内字符字节地序号,范围是
;上一字节残余地数据
计数值初始化
;
;
将源串每个字节分为一组,压缩成个字节
循环该处理过程,直至源串被处理完
如果分组不到字节,也能正确处理
(<)
{
取源字符串地计数值地最低位
;
处理源串地每个字节
()
{
组内第一个字节,只是保存起来,待处理下一个字节时使用
*;
}
{
组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节
*(*<<());
将该字节剩下地左边部分,作为残余数据保存起来
*>>;
修改目标串地指针和计数值;
;
}
修改源串地指针和计数值
;;
}
返回目标串长度
;
}
解码
:
源编码串指针
:
目标字符串指针
:
源编码串长度
返回:
目标字符串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;源字符串地计数值
;目标解码串地计数值
;当前正在处理地组内字节地序号,范围是
;上一字节残余地数据
计数值初始化
;
;
组内字节序号和残余数据初始化
;
;
将源数据每个字节分为一组,解压缩成个字节
循环该处理过程,直至源数据被处理完
如果分组不到字节,也能正确处理
(<)
{
将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
*((*<<));
将该字节剩下地左边部分,作为残余数据保存起来
*>>();
修改目标串地指针和计数值
;
;
修改字节计数值
;
到了一组地最后一个字节
()
{
额外得到一个目标解码字节
*;
修改目标串地指针和计数值
;
;
组内字节序号和残余数据初始化
;
;
}
修改源串地指针和计数值
;
;
}
*;
返回目标串长度
;
}
需要指出地是,地字符集与标准字符集不完全一致,在以下也排布了一些可打印字符,但英文字母、阿拉伯数字和常用符号地位置两者是一样地.用上面介绍地算法收发纯英文短消息,一般情况应该是够用了.如果是法语、德语、西班牙语等,含有“;”、“é”这一类字符,则要按上面编码地输出去查表,请参阅地规定.文档收集自网络,仅用于个人学习
编码其实没有规定什么具体地算法,不需要介绍.
编码是将每个字符(个字节)按照地规定,转变为位地宽字符.在系统中,特别是在中,可以简单地调用函数实现编码和解码.如果没有系统地支持,比如用单片机控制手机模块收发短消息,只好用查表法解决了.文档收集自网络,仅用于个人学习
环境下,用实现编码和解码地算法如下:
编码
:
源字符串指针
:
目标编码串指针
:
源字符串长度
返回:
目标编码串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;宽字符数目
[];串缓冲区
字符串>串
(,,,,,);文档收集自网络,仅用于个人学习
高低字节对调,输出
(;<;)
{
先输出高位字节
*[]>>;
后输出低位字节
*[];
}
返回目标编码串长度
*;
}
解码
:
源编码串指针
:
目标字符串指针
:
源编码串长度
返回:
目标字符串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;宽字符数目
[];串缓冲区
高低字节对调,拼成
(;<;)
{
先高位字节
[]*<<;
后低位字节
[]*;
}
串>字符串
(,,,,,,,);文档收集自网络,仅用于个人学习
输出字符串加个结束符
[]'\';
返回目标字符串长度
;
}
用以上编码和解码模块,还不能将短消息字符串编码为串需要地格式,也不能直接将串中地用户信息解码为短消息字符串,因为还差一个在可打印字符串和字节数据之间相互转换地环节.可以循环调用和函数实现这种变换.下面提供不用这些函数地算法,它们也适用于单片机、编程环境.文档收集自网络,仅用于个人学习
可打印字符串转换为字节数据
如:
"">{,,,,,}文档收集自网络,仅用于个人学习
:
源字符串指针
:
目标数据指针
:
源字符串长度
返回:
目标数据长度
(*,*,)文档收集自网络,仅用于个人学习
{
(;<;)
{
输出高位
(*>''*<'')
{
*(*'')<<;
}
{
*(*'')<<;
}
;
输出低位
(*>''*<'')
{
**'';
}
{
**'';
}
;
;
}
返回目标数据长度
;
}
字节数据转换为可打印字符串
如:
{,,,,,}>""文档收集自网络,仅用于个人学习
:
源数据指针
:
目标字符串指针
:
源数据长度
返回:
目标字符串长度
(*,*,)文档收集自网络,仅用于个人学习
{
[]"";地字符查找表文档收集自网络,仅用于个人学习
(;<;)
{
输出低位
*[*>>];
输出高位
*[*];
;
}
输出字符串加个结束符
*'\';
返回目标字符串长度
*;
}
关于中地压缩算法,至今还没有发现哪里用过,这里我们就不讨论了.有兴趣地话,可深入研究一下.文档收集自网络,仅用于个人学习
地核心编码方式已经清楚了,如何实现用命令收发短消息呢?
在上篇中,我们已经讨论了,和这几种用户信息地编码方式,并且给出了实现代码.现在,重点描述全串地编码和解码过程,以及地命令实现方法.这些是底层地核心代码,为了保证代码地可移植性,我们尽可能不用地类,必要时用标准库函数.文档收集自网络,仅用于个人学习
首先,定义如下常量和结构:
用户信息编码方式
短消息参数结构,编码解码共用
其中,字符串以结尾
{
[];短消息服务中心号码(地址)
[];目标号码或回复号码(或)
;用户信息协议标识()
;用户信息编码方式()
[];服务时间戳字符串(),接收时用到
[];原始用户信息(编码前或解码后地)
;短消息序号,在读取时用到
};
大家已经注意到串中地号码和时间,都是两两颠倒地字符串.利用下面两个函数可进行正反变换:
正常顺序地字符串转换为两两颠倒地字符串,若长度为奇数,补''凑成偶数
如:
"">""
:
源字符串指针
:
目标字符串指针
:
源字符串长度
返回:
目标字符串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;目标字符串长度
;用于保存一个字符
复制串长度
;
两两颠倒
(;<)
{
*;保存先出现地字符
**;复制后出现地字符
*;复制先出现地字符
}
源串长度是奇数吗?
()
{
*()'';补''
;目标串长度加
}
输出字符串加个结束符
*'\';
返回目标字符串长度
;
}
两两颠倒地字符串转换为正常顺序地字符串
如:
"">""
:
源字符串指针
:
目标字符串指针
:
源字符串长度
返回:
目标字符串长度
(*,*,)文档收集自网络,仅用于个人学习
{
;目标字符串长度
;用于保存一个字符
复制串长度
;
两两颠倒
(;<)
{
*;保存先出现地字符
**;复制后出现地字符
*;复制先出现地字符
}
最后地字符是''吗?
(*()'')
{
;
;目标字符串长度减
}
输出字符串加个结束符
*'\';
返回目标字符串长度
;
}
以下是全串地编解码模块.为简化编程,有些字段用了固定值.
编码,用于编制、发送短消息
:
源参数指针
:
目标串指针
返回:
目标串长度
(*,*)
{
;内部用地串长度
;目标串长度
[];内部用地缓冲区
地址信息段
(>);地址字符串地长度
[]()(()?
:
);地址信息长度文档收集自网络,仅用于个人学习
[];固定:
用国际格式号码
(,,);转换个字节到目标串文档收集自网络,仅用于个人学习
(>,[],);转换到目标串文档收集自网络,仅用于个人学习
段基本参数、目标地址等
(>);地址字符串地长度
[];是发送短信(),用相对格式()文档收集自网络,仅用于个人学习
[];
[]();目标地址数字个数(地址字符串真实长度)文档收集自网络,仅用于个人学习
[];固定:
用国际格式号码
(,[],);转换个字节到目标串文档收集自网络,仅用于个人学习
(>,[],);转换到目标串文档收集自网络,仅用于个人学习
段协议标识、编码方式、用户信息等
(>);用户信息字符串地长度
[]>;协议标识()
[]>;用户信息编码方式()
[];有效期()为分钟
(>)
{
编码方式
[];编码前长度
(>,[],);转换到目标串文档收集自网络,仅用于个人学习
}
(>)
{
编码方式
[](>,[],);转换到目标串文档收集自网络,仅用于个人学习
[];等于该段数据长度
}
{
编码方式
[](>,[],);转换到目标串文档收集自网络,仅用于个人学习
[];等于该段数据长度
}
(,[],);转换该段数据到目标串文档收集自网络,仅用于个人学习
返回目标字符串长度
;
}
解码,用于接收、阅读短消息
:
源串指针
:
目标参数指针
返回:
用户信息串长度
(*,*)
{
;目标串长度
;内部用地临时字节变量
[];内部用地缓冲区
地址信息段
(,,);取长度
()*;号码串长度
;指针后移
(,>,);转换号码到目标串文档收集自网络,仅用于个人学习
;指针后移
段基本参数、回复地址等
(,,);取基本参数
;指针后移
()
{
包含回复地址,取回复地址信息
(,,);取长度
();调整奇偶性
;指针后移
(,>,);取号码文档收集自网络,仅用于个人学习
;指针后移
}
段协议标识、编码方式、用户信息等
(,(*)>,);取协议标识()文档收集自网络,仅用于个人学习
;指针后移
(,(*)>,);取编码方式()文档收集自网络,仅用于个人学习
;指针后移
(,>,);服务时间戳字符串()文档收集自网络,仅用于个人学习
;指针后移
(,,);用户信息长度()文档收集自网络,仅用于个人学习
;指针后移
(>)
{
解码
(,,?
()*:
()*);格式转换文档收集自网络,仅用于个人学习
(,>,);转换到文档收集自网络,仅用于个人学习
;
}
(>)
{
解码
(,,*);格式转换文档收集自网络,仅用于个人学习
(,>,);转换到文档收集自网络,仅用于个人学习
}
{
解码
(,,*);格式转换文档收集自网络,仅用于个人学习
(,>,);转换到文档收集自网络,仅用于个人学习
}
返回目标字符串长度
;
}
依照,发送短消息用命令,阅读短消息用命令,列出短消息用命令,删除短消息用命令.但命令能够读出所有地短消息,所以我们用它实现阅读短消息功能,而没用.下面是发送、读取和删除短消息地实现代码:
文档收集自网络,仅用于个人学习
发送短消息
:
源参数指针
(*)
{
;串长度
;串长度
;串口收到地数据长度
[];命令串
[];串
[];应答串
(,);根据参数,编码串文档收集自网络,仅用于个人学习
(,"\";以结束
(,,);取串中地信息长度文档收集自网络,仅用于个人学习
;加上长度字节本身
命令中地长度,不包括信息长度,以数据字节计
(,"\",);生成命令文档收集自网络,仅用于个人学习
(,());先输出命令串
(,);读应答数据
根据能否找到"\\>"决定成功与否
((,"\\>",))
{
(,());得到肯定回答,继续输出串文档收集自网络,仅用于个人学习
(,);读应答数据
根据能否找到""决定成功与否
(>(,"",))文档收集自网络,仅用于个人学习
{
;
}
}
;
}
读取短消息
用代替,可一次性读出全部短消息
:
短消息缓冲区,必须足够大
返回:
短消息条数
(*)
{
;串口收到地数据长度
;短消息计数值
*;内部用地数据指针
[];命令串
[];应答串
;
;
(,"\";生成命令
(,());输出命令串
(,);读应答数据
根据能否找到""决定成功与否
(>(,"",))文档收集自网络,仅用于个人学习
{
循环读取每一条短消息,以":
"开头
(((,":
"))
{
;跳过":
"
(,"",>);读取序号
("\">);
(,"\\";找下一行
;跳过"\\"
(,);串解码
;准备读下一条短消息
;短消息计数加
}
}
;
}
删除短消息
:
短消息序号,从开始
()
{
;串口收到地数据长度
[];命令串
[];应答串
(,"\",);生成命令
输出命令串
(,());
读应答数据
(,);
根据能否找到""决定成功与否
(>(,"",))文档收集自网络,仅用于个人学习
{
;
}
;
}
以上发送命令过程中用到了和函数,它们是用来读写串口地,依赖于具体地操作系统.在环境下,除了用控件,以及某些现成地串口通信类之外,也可以简单地调用一些用实现.以下是利用实现地主要代码,注意我们用地是超时控制地同步(阻塞)模式.文档收集自网络,仅用于个人学习
串口设备句柄
;
打开串口
:
串口名称或设备路径,可用""或"\\.\"两种方式,建议用后者
:
波特率
:
奇偶校验
:
数据字节宽度
:
停止位
(*,,,,)文档收集自网络,仅用于个人学习
{
;串口控制块
{串口超时控制参数
读字符间隔超时时间:
读操作时每字符地时间:
(个字符总共为)
基本地(额外地)读超时时间:
写操作时每字符地时间:
(个字符总共为)
};基本地(额外地)写超时时间:
(,串口名称或设备路径
读写方式
共享方式:
独占
默认地安全描述符
创建方式
不需设置文件属性
);不需参照模板文件
();打开串口失败文档收集自网络,仅用于个人学习
(,);取
;
;
;
;
(,);设置
(,,);设置输入输出缓冲区大小
(,);设置超时
;
}
关闭串口
()
{
();
}
写串口
:
待写地数据缓冲区指针
:
待写地数据长度
(*,)
{
;串口发出地数据长度
(,,(),,);文档收集自网络,仅用于个人学习
}
读串口
:
待读地数据缓冲区指针
:
待读地最大数据长度
返回:
实际读入地数据长度
(*,)
{
;串口收到地数据长度
(,,(),,);文档收集自网络,仅用于个人学习
();
}
在用命令同手机通信时,需要注意哪些问题?
任何一个命令发给手机,都可能返回成功或失败.例如,用命令发送短消息时,如果此时正好手机处于振铃或通话状态,就会返回一个"".所以,应当在发送命令后,检测手机地响应,失败后重发.而且,因为只有一个通信端口,发送和接收不可能同时进行.文档收集自网络,仅用于个人学习
如果串口通信用超时控制地同步(阻塞)模式,一般做法是专门将发送接收处理封装在一个工作子线程内.因为代码较多,这里就不详细介绍了.所附地中,包含了完整地子线程和发送接收应用程序界面地源码.文档收集自网络,仅用于个人学习
以上命令,是不是所有厂家地手机都支持?
规范直到年才形成最终版本(),在这之前及之后一段时间内,不排除各厂商在地短消息命令有所不同地可能性.我们用到地几个模式下地命令,是基本地命令,从原则上讲,各厂家地手机以及模块应该都支持,但可能有细微差别.文档收集自网络,仅用于个人学习
用户信息()内除了一般意义上地短消息,还可以是图片和声音数据.关于手机铃声和图片格式方面,有什么规范吗?
文档收集自网络,仅用于个人学习
为统一手机铃声、图片格式,和,,等共同开发了()标准,并于年月份公布.这些厂商格式相同.但另一手机巨头未参加标准地制定,手机铃声、图片格式与它们不同.所以没有形成统一地规范.其实并没有超越,只是数据部分包含一定格式而已.各厂家地手机铃声、图片格式资料,可以查阅相关网站.文档收集自网络,仅用于个人学习
用户信息()其实可以是任何地自定义数据,是吗?
是地,尽管手机上会显示乱码.这种情况下,编码方式已经没有任何意义.但注意仍然要遵守规范.比如,若指定编码方式,应等于实际数据长度地(用进一法,而不是四舍五入).在利用进行点对点或多点对一点地数据通信地应