一,简介

SIM 808发送短信分text模式和PDU模式。text模式已ascii码发送短信,这种模式比较简单,发送命令AT+CMGF=1就可以发送短信,而PDU模式比较复杂,首先发送命令AT+CMGF=0,才能进行发送PDU短信。这里主要讲解PDU的发送方式。

二,文本方式发送短信

确保SIM模块初始化完成:

1,设置发送模式

AT+CMGF=1

2,接收方电话号码

AT+CMGS=138XXXXxxxx

3,输入内容

>hello world !

4,完成发送

输入完短信内容后按组合键“ctrl+z”作为结束符,“ctrl+z”在ascii码中的数值是“0x1a”,所以在编程时可以直接在信息内容后进行字符串拼接。

三,PDU方式收发短信

1,发送短信

我们先来看PDU发送短信的流程:

1),设置发送模式

AT+CMGF=0

2),发送将发送的短信长度

AT+CMGS=信息长度

3),发送短信

0891683108705505F011000D91688112790924F70008000A68077b7e632f52a8002e

我们把短信内容给分段,

0891683108705505F0 11000D91688112790924F7000800 0A68077b7e632f52a8002e

绿色部分是号码中心段,蓝色部分是发送号码段,红色部分是发送信息段。

4),先来看中心号码段。

我们其实还可以将其再细分:

08           91           683108705505F0

其中91是国际化的意思,这个作为前缀必须加上。

683108705505F0是什么意思呢?我们将它奇数位和偶数位反转看看:

“683108705505F0”

“8613800755500F”

13800755500是深圳地区的中心号码,86是中国地区的前缀。F是因为在进行PDU编码的时候规定了如果号码位数是奇数位那么就要在末尾加F进行补齐,由于我们国家的手机号码位数都是11位,因此要在末尾补F。于是我们的中心号码加86补齐F再奇偶位反转最后加91国际化前缀就由原来的:

“13800755500”

变成了:

“91683108705505F0”

接着我们数一下它有多少位,16位,16/2=8,所以我们把整个中心号码组合编码后的长度除以2,最后以十六进制的表示方式加在它的前端就大功告成了。

“0891683108705505F0”

5),收信方号码段。

“11000D91688112790924F7000800”

将其细分:

1100         0D91688112790924F7    00     08     00

其中“1100”和“000800”分别是收信方号码段固定的前缀和后缀,所以一定要记得加上。其中08两位表明了发送短信的编码方式。如果为00是按7bit的编码发送短信英文字符数字常以这种方式发送;如果是04是按8bit的编码发送短信图片等一般以这种方式发送;如果是08则是以ucs2的编码方式发送中文都是以这种方式发送。

“688112790924F7”和中心号码段一样的编码方式,原型是:

“8618219790427”。

“0D91”需要注意一下,其中这里的“91”和中心号码段的“91”意义不一样了,这里是表示接收方的设备是手机的意思,“81”则是小灵通。“0D”是一个十六进制数,还原为十进制后是13,什么意思呢?接受方的号码是“8618219790427”共13位。

因此接收方电话经偶数位<补齐F>

然后<奇数偶数位反转>

再<加上号码长度>

最后<加上前后缀>最终由:

“8618219790427”

转型为:

“11000D91688112790924F7000800”。

6),信息段

“0A68077b7e632f52a8002e”

前面我们说过发送中文是以ucs2方式发送的,即unicode码发送,把68077b7e632f52a8002e编码还原成GB码是“标签振动.”

其编码(十六进制)长度是20位,20/2=10,10的十六进制表示方式是0X0A。因此信息段的最终编码为:

“0A68077b7e632f52a8002e”

7),组合

我们把上面的编码组合,于是发送的内容为

“0891683108705505F011000D91688112790924F70008000A68077b7e632f52a8002e”

我们把短信中心号码去除变为

“11000D91688112790924F70008000A68077b7e632f52a8002e”

计算一下字符串长度,50位。OK,50/2=25。于是在PDU模式下,我们所谓的“信息长度”:AT+CMGS=25。

至此整个PDU发送短信完成

2,接收短信

接收到的短信的解码和发送短信基本相同。我们先看一下两条接收到的短信编码

0891683108705505F0240D91683186869254F70000616032514222230163

0891683108705505F0240D91683186869254F7000861603251547523026211

将编码分段:

0891683108705505F0 24 0D 91 683186869254F7 00

0891683108705505F0 24 0D 91 683186869254F7 00

红色部分为短信编码00:7bit 04:8bit 08:ucs2,

绿色部分为短信中心时间戳,

蓝色部分为接发送的消息体长度.

橙色部分为消息体

四,一些转换函数

// 十六进制数据映射表

const char HexTbl[] = { "0123456789ABCDEF" };

// 十六进制字符转为数字

unsigned char HexChar2Number(char hex)

{

unsigned char value = 0;

if (hex >= '0' && hex <= '9')

{

value = hex - '0';

}

else if (hex >= 'A' && hex <= 'Z')

{

value = hex - 'A' + 10;

}

else if (hex >= 'a' && hex <= 'z')

{

value = hex - 'a' + 10;

}

return value;

}

// 两个十六进制字符转为十进制数据

unsigned char strHex2Byte(char *pHex)

{

unsigned char value;

value = HexChar2Number(pHex[0]) << 4;

value |= HexChar2Number(pHex[1]);

return value;

}

/**********************************************************

GSM PDU 7bit编码,由ASCII字符串转为编码后的7bit PDU字符串

"hellohello"----->"E8329BFD4697D9EC37"

pDst:编码后的目标指针

pSrc:编码前的ASCII字符串指针

返回:编码后的字符数据长度

***********************************************************/

int PDU_7BIT_Encoding(unsigned char *pDst, char *pSrc)

{

int i;

unsigned char hexVlaue;                                                    // 保存编码过程中的十六进制数据

unsigned char nLeft;                                                 // 左边应填充的位个数

unsigned char fillValue;                                            // 用于填充的数据

int Cnt = 0;                                                                // 编码后数据长度

int nSrcLength = strlen(pSrc);                                 // 源字符串长度

nLeft = 1;                                                                           // 初始值左边应填充1位

for (i = 0; i < nSrcLength; i++)

{

hexVlaue = *pSrc >> (nLeft - 1);              // 先将当前字符右移相应位;

fillValue = *(pSrc + 1) << (8 - nLeft);              // 取出下一个字符的低位,并从低位移到高位存放到fillValue

hexVlaue = hexVlaue | fillValue;             // 将下一个字符的低位补到该字符的高位得到该位的编码

*pDst++ = HexTbl[hexVlaue >> 4];        // 将编码后的十六进制转为相应的字符串放到pDst中

*pDst++ = HexTbl[hexVlaue & 0x0F];

Cnt += 2;                                                                   // 字符串长度加2

nLeft++;                                                                     // 左边应填充的位个数加1

if (nLeft == 8)                                                             // 移动8次后将产生一个空字符0x00,实为8个字节数据转为7字节数据

{

pSrc++;                                                                   // 跳过该字符

i++;

nLeft = 1;                                                           // 下次循环将重复前面过程

}

pSrc++;                                                                                 // 源字符串指针移向下一字符

}

*pDst = '\0';                                                                       // 字符串末尾设置为0

return Cnt;

}

/**********************************************************

GSM PDU 7bit字符串解码,由7bit PDU字符串转为ASCII字符串

"E8329BFD4697D9EC37"----->"hellohello"

pDst:解码后的ASCII字符串目标指针

pSrc:解码前的PDU 7bit字符串指针

返回:解码后的ASCII字符串长度

***********************************************************/

int PDU_7BIT_Decoding(char *pDst, char *pSrc)

{

int i;

int Cnt = 0;                                                               // 解码后字符串长度

unsigned char nLeft = 1;                                           // 左边填充位个数

unsigned char fillValue = 0;                            // 填充的数据

unsigned char oldFillValue = 0;                                // 上一次填充的数据

int srcLength = strlen(pSrc);                           // 获得PDU编码长度

for (i = 0; i < srcLength; i += 2)

{

*pDst = strHex2Byte(pSrc);                           // 获取当前字符

fillValue = (unsigned char)*pDst;

fillValue >>= (8 - nLeft);                                  // 取出编码时填充到该字节的数据

*pDst <<= (nLeft - 1);                                     // 左移至原始位置

*pDst &= 0x7F;                                                         // 去掉最高位

*pDst |= oldFillValue;                                       // 将上一次取出的补位加到末尾

oldFillValue = fillValue;

pDst++;                                                                               // 目标地址加1

Cnt++;                                                                                 // 解码长度加1

nLeft++;                                                                    // 左边填充位个数加1

if (nLeft == 8)                                                           // 第8个字节将产生一个完全的填充数据

{

*pDst = oldFillValue;                             // 直接将该填充数据放到下一个目标地址中

pDst++;

Cnt++;

nLeft = 1;                                                         // 复位nLeft,重复以上步骤

oldFillValue = 0;

}

pSrc += 2;                                                                 // 源指针向后移两字节

}

*pDst = '\0';                                                                       // 目标字符串末尾设为0

return Cnt;

}

五,参考资料

http://blog.sina.com.cn/s/blog_524846000101cwtr.html

http://wenku.baidu.com/link?url=G1G88hlkyiklD7gZpLpvZcibZDjZI1jrfn2CpVx2adu-uaXR7dxDcLHO2odX3xEzwBfiSQk1ho4HOLfVOfEmD-l9gxQ8yOUxROkVFLj4zwO

转载请注明出处:http://www.cnblogs.com/fyluyg/articles/5703306.html

sim808模块收发送短信的更多相关文章

  1. [stm32] SIM808模块之发短信\GPS\TCP\HTTP研究

    SIM8008是四频模块,全球可用.含有TTL电平接口等接口,能够实现发短信.打电话.GPRS传输数据.GPS等功能.[正版资料请找beautifulzzzz·博客园] 一些细节: >> ...

  2. STM32F103 GU906B模块GPRS、短信收发、拨号等功能的实现

    这个程序搞了我很久,尤其是对如何提高响应速度上,程序流程很简单,大概就是: 发送AT指令->等待模块响应->一旦响应了,立即返回,并处理掉. 这个程序不一定只能用在GU906上,程序框架在 ...

  3. Android--发送短信,并且通知发送方

    1.发送短信涉及到权限,我们需要把权限加上 2.当我们发送短信时,不管发送是否成功,接收方是否接收到,系统都会发送广播 3.这时我们注册广播去接收一下就可以了 4.布局文件很简单,里面就两个EditT ...

  4. android-发送短信

  5. iOS-发送短信验证码倒计时

    /** 发送手机验证码 */ -(void)startSenderYzmMessage{ __block ; //倒计时时间 dispatch_queue_t queue = dispatch_get ...

  6. Flutter-發送短信驗證碼

    import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; ...

  7. java 短信猫发送短信的方法

    用java实现短信收发的功能,目前一般项目中短信群发功能的实现方法大致有下面三种: ·                 1. 向运行商申请短信网关,不需要额外的设备,利用运行商提供的API调用程序发送 ...

  8. Android收发短信

    效果:点击发送短信开始发送短信 收到短信时将短信的内容显示出来 代码如下: 一.权限声明 <uses-permission android:name="android.permissi ...

  9. .Net core----使用容联云短信推送

    一直在忙于写接口,也没有时间去好好的整理的一片文档,写一篇经常的用到的短信推送案例 还是比较喜欢干货  作为有个程序员 有时候复制粘贴习惯了   实在的还是比较实在 比如能用复制解决的为什么不用复制 ...

随机推荐

  1. jQuery实现返回顶部功能

    整理两个实现功能,一个是右下角的返回顶部,一个是右侧的返回顶部,分别如图               第一种实现 一.JSP或HTML(主体结构) 在body中添加 <body id=" ...

  2. IceMx.Mvc 我的js MVC 框架 三、动手来写一个评论模块儿

    介绍 本人菜鸟,一些自己的浅薄见解,望各位大神指正. 本框架有以下优点 1.简单(调用简单.实现简单.不过度设计) 2.视图.控制器.模型分离(分离对于维护十分有必要) 3.组件化(每一个mvc模块儿 ...

  3. TaskTracker获取并执行map或reduce任务的过程1

    TaskTracker获取并执行map或reduce任务的过程(一) 我们知道TaskTracker在默认情况下,每个3秒就行JobTracker发送一个心跳包,也就是在这个心跳包中包含对任务的请求. ...

  4. TCP可靠传输的实现

    TCP可靠传输的实现 1.概述      为方便描述可靠传输原理,假定数据传输只在一个方向上进行,即A发送数据,B给出确认 2.以字节为单位的滑动窗口      TCP的滑动窗口是以字节为单位的.为了 ...

  5. enode框架step by step之事件驱动架构(EDA)思想的在框架中如何体现

    enode框架step by step之事件驱动架构(EDA)思想的在框架中如何体现 上一篇文章,我给大家分享了我的一个基于DDD以及EDA架构的框架enode,但是只是介绍了一个大概.接下来我准备用 ...

  6. wget ( download the whole page from the website )

    ---恢复内容开始--- wget -m -e robots=off -U "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1 ...

  7. [Android开发常见问题-11] Unable to execute dex: Multiple dex files define 解决方法

    最近在开发一个工程,其中用到了一个开源的库项目Android-ViewPagerIndicator. 这个项目是作为一个库出现的,如下图: 这个项目中包含了android-support-v4.jar ...

  8. php中empty和isset的区别

    比如: $_POST[ 'test']= ' ';那么: isset($_POST[ 'test']) ===> true; empty($_POST[ 'test']) ===> tru ...

  9. magento 小问题解决方案集

    magento错误 Mage registry key "_singleton/core/resource" already exists解决方法:1.清理magento的var/ ...

  10. HDU 2073 无限的路

    Problem Description 甜甜从小就喜欢画图画,最近他买了一支智能画笔,由于刚刚接触,所以甜甜只会用它来画直线,于是他就在平面直角坐标系中画出如下的图形: 甜甜的好朋友蜜蜜发现上面的图还 ...