sim808模块收发送短信
一,简介
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://www.cnblogs.com/fyluyg/articles/5703306.html
sim808模块收发送短信的更多相关文章
- [stm32] SIM808模块之发短信\GPS\TCP\HTTP研究
SIM8008是四频模块,全球可用.含有TTL电平接口等接口,能够实现发短信.打电话.GPRS传输数据.GPS等功能.[正版资料请找beautifulzzzz·博客园] 一些细节: >> ...
- STM32F103 GU906B模块GPRS、短信收发、拨号等功能的实现
这个程序搞了我很久,尤其是对如何提高响应速度上,程序流程很简单,大概就是: 发送AT指令->等待模块响应->一旦响应了,立即返回,并处理掉. 这个程序不一定只能用在GU906上,程序框架在 ...
- Android--发送短信,并且通知发送方
1.发送短信涉及到权限,我们需要把权限加上 2.当我们发送短信时,不管发送是否成功,接收方是否接收到,系统都会发送广播 3.这时我们注册广播去接收一下就可以了 4.布局文件很简单,里面就两个EditT ...
- android-发送短信
- iOS-发送短信验证码倒计时
/** 发送手机验证码 */ -(void)startSenderYzmMessage{ __block ; //倒计时时间 dispatch_queue_t queue = dispatch_get ...
- Flutter-發送短信驗證碼
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; ...
- java 短信猫发送短信的方法
用java实现短信收发的功能,目前一般项目中短信群发功能的实现方法大致有下面三种: · 1. 向运行商申请短信网关,不需要额外的设备,利用运行商提供的API调用程序发送 ...
- Android收发短信
效果:点击发送短信开始发送短信 收到短信时将短信的内容显示出来 代码如下: 一.权限声明 <uses-permission android:name="android.permissi ...
- .Net core----使用容联云短信推送
一直在忙于写接口,也没有时间去好好的整理的一片文档,写一篇经常的用到的短信推送案例 还是比较喜欢干货 作为有个程序员 有时候复制粘贴习惯了 实在的还是比较实在 比如能用复制解决的为什么不用复制 ...
随机推荐
- c++中的类型擦除
(原创)c++中的类型擦除 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除.有必要做个说明,类 ...
- CYQ.Data 支持WPF相关的数据控件绑定.Net获取iis版本
CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09) 事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便 ...
- iOS 开发问题集锦(一)
最近在QQ群里好多人问一些比较基础的问题,在这罗列一下: 1.键盘上的斜杠键坏掉了,怎么样用快捷键进行注释呢? 首先在Xcode中注释的默认快捷键为:command+/: 其次可以自行修改快捷键:Xc ...
- PHP使用DomDocument抓取HTML内容
有时候会有需要从一个HTML页面来分离出你需要的一些数据来进行处理. 当然自己分析文件肯定可以,但是比较快速且方便的是使用正则表达式或者DOM. 鉴于正则表达式我不熟悉,所以我打算使用DOM来完成. ...
- 挖一下插件v1.5版本发布
Chrome图片下载插件,支持网页截屏 v.1.5更新说明: 1.增加下载图片按日期分类保存选项,便于管理,用户可根据需要开启/关闭此设置 2.增加网页图片采集快捷键: (1)采集页面图片(Ctrl+ ...
- IOS开发笔记 - 基于SDWebImage的网络图片加载处理
前言: 在IOS下通过URL读一张网络图片并不像Asp.net那样可以直接把图片路径放到图片路径的位置就ok, 而是需要我们通过一段类似流的方式去加载网络图片,接着才能把图片放入图片路径显示. 这里找 ...
- 在Linux Mint13下编译安装mono运行时
最近一直想体验下mono在web开发上到底进展到什么程度,挑战一下它对web开发的极限.因为asp.net mvc本身依赖windows平台的东西不太多,所以这些assembly移植到mono/lin ...
- Java乔晓松-android中的帧动画FrameByFrame
先看效果后上代码: 动画开始---- 动画切换的界面---- 动画播放完毕后的跳转界面----- 重要的方法: imageView.setBackgroundResource(R.anim.frame ...
- Day1-python理论基础
一.python介绍 Python 的创始人为Guido van Rossum.Guido为了打发圣诞节的无趣,于1989年发明,在荷兰国家数学和计算机科学研究所设计出来的(作为ABC 语言的一种继 ...
- 以域管理账户连接到TFS或git时,设置IE允许Cookies
在 Windows 域环境中,每个项目组会创建一个项目管理账户,在和其他项目组进行数据交互时,只需要授予该项目管理账户相应的权限,方便了权限的管理.对于项目组管理账户:domain\admin,该域账 ...