首页 > 范文大全 > 正文

基于MC35i的无线监测数据传输模块设计与实现

开篇:润墨网以专业的文秘视角,为您筛选了一篇基于MC35i的无线监测数据传输模块设计与实现范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

摘要:在介绍SMS无线数据传输与MC35i模块的基础上,解析SMS无线数据传输格式,采用标准C语言实现。结果表明采用C语言实现的基于mc35i模块实现电表的集中监测系统具有系统结构明晰、成本低、性能可靠等优点,适合于在近似领域推广使用。

关键词:SMS;无线监测;MC35i

中图分类号:TP393 文献标示码:A文章编号:1009-3044(2009)36-10594-03

The Design and Implement of the Wireless M&M System Based on the MC35i Module

CHEN Jun1, CHEN Lin2, WU Wen-ping2

(1.Xinjiang Branch of Armed Police, Urumqi 830063, China; 2.Unit 69046, Urumqi 830001, China)

Abstract: The format of the SMS wireless data transport is explained with the C language based on the introduction of the wireless Data transport and MC35i module. The result is reached that the centralized M&M system with the C language based on the the MC35i module has the advantages of clear system structure, low expensive, high stability and so on. The system can be used on similar areas.

Key words: SMS; Wireless M&M; MC35i

1 概述

本模块采用MC35i通过RS-232接口实现,数据传输上采用SMS方式进行。

SMS是由ESTI制定的一个规范,在收发短信上,按照时间先后有三种模式:Block模式、Text模式、PDU模式。在我国由于需要支持中文,基本都采用PDU模式。PDU模式使用三种编码,分别是7bit、8bit、16bit。16bit编码也叫UCS2编码或Unicode编码,要支持中文必须用UCS2编码方式,最多一次可发送70字符。

2 SMS数据格式解析

以一组收发数据为例,介绍SMS数据格式。

假设要发送“你好”到手机“13812345678”,发送的PDU数据串为:08 91 683108701305F0 11 00 0D 91 683118325476F8 00 08 00 04 4F60597D。其数据格式解析如下:

08:短消息服务中心地址长度,8个字节。

91:短消息服务中心号码类型。

683108701305F0:短消息服务中心号码,8613800731500。

11:文件头部。

00:信息参考。

0D:被叫号码长度13位。

91:被叫号码类型。

683118325476F8:被叫号码8613812345678。

00:协议标示。

08:数据编码方案。

00:有效期。

04:用户数据长度。

4F60597D:用户数据“你好”的Unicode编码。

假设接收到一组PDU串,08 91 683108701305F0 24 0B A1 3118325476F8 00 08 50303211509220 04 4F60597D。分析如下:

08:短消息服务中心地址长度,8个字节。

91:短消息服务中心号码类型。

683108701305F0:短消息服务中心号码8613800731500。

24:文件头字节。

0B:被叫号码长度,11位。

A1:被叫号码类型。

3118325476F8:被叫号码13812345678。

00:协议标示。

08:数据编码方案。

50303211509220:时间戳。

04:用户数据长度。

4F60597D:用户数据“你好”的Unicode编码。

3 SMS编程实现

SMS信息必须经过字符到字节以及其相反的转换。其转换函数为:int gsmString2Bytes(const char* pSrc,unsigned char* pDst,int nSrcLength),pSrc为源字符串指针,nSrcLength源字符串长度,pDst为目标数据指针;int gsmBytes2String(const unsigned char* pSrc,char* pDst,int nSrcLength),pSrc为源数据指针,nSrcLength源数据长度,pDst为目标字符串指针。代码略。

UCS2编码函数gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)和UCS2解码函数int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)部分代码如下所示:

UCS2编码,输入:pSrc - 源字符串指针,nSrcLength - 源字符串长度,输出:pDst - 目标编码串指针,返回:目标编码串长度

int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)

{ int nDstLength; // UNICODE宽字符数目

WCHAR wchar[128]; // UNICODE串缓冲区

// 字符串-->UNICODE串

nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);

// 高低字节对调,输出

for(int i=0; i

{ *pDst++ = wchar[i] >> 8; // 先输出高位字节

*pDst++ = wchar[i] & 0xff; // 后输出低位字节

}

// 返回目标编码串长度

return nDstLength * 2;

}

UCS2解码,输入:pSrc - 源编码串指针,nSrcLength -源编码串长度,输出:pDst -目标字符串指针,返回:目标字符串长度

int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)

{ int nDstLength; // UNICODE宽字符数目

WCHAR wchar[128]; // UNICODE串缓冲区

// 高低字节对调,拼成UNICODE

for(int i=0; i

{ wchar[i] = *pSrc++

wchar[i] |= *pSrc++; // 后低位字节

}

// UNICODE串-->字符串

nDstLength = WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);

// 输出字符串加个结束符

pDst[nDstLength] = '\0';

// 返回目标字符串长度

return nDstLength;

}

在PDU编码解码函数中,还要用到如下数据顺序转换函数:1、正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补'F'凑成偶数。输入:pSrc - 源字符串指针,nSrcLength - 源字符串长度,输出:pDst - 目标字符串指针,返回:目标字符串长度,int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength)。2、两两颠倒的字符串转换为正常顺序的字符串,输入: pSrc - 源字符串指针, nSrcLength - 源字符串长度,输出:pDst - 目标字符串指针,返回:目标字符串长度,int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength)。

PDU编码,用于编制、发送短消息,输入:pSrc - 源PDU参数指针,输出:pDst - 目标PDU串指针,返回:目标PDU串长度

int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst)

{ int nLength; // 内部用的串长度

int nDstLength; // 目标PDU串长度

unsigned char buf[256]; // 内部用的缓冲区

// SMSC地址信息段

nLength = strlen(pSrc->SCA); // SMSC地址字符串的长度

buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1; //SMSC地址信息长度

buf[1] = 0x91; // 固定: 用国际格式号码

nDstLength = gsmBytes2String(buf, pDst, 2); // 转换2个字节到目标PDU串

nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); // 转换SMSC号码到目标PDU串

// TPDU段基本参数、目标地址等

nLength = strlen(pSrc->TPA); // TP-DA地址字符串的长度

buf[0] = 0x11; // 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10)

buf[1] = 0; // TP-MR=0

buf[2] = (char)nLength; // 目标地址数字个数(TP-DA地址字符串真实长度)

buf[3] = 0x91; // 固定: 用国际格式号码

nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4);//转换4字节到目标PDU串

nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength);

//转换TP-DA到目标PDU串

// TPDU段协议标识、编码方式、用户信息等

nLength = strlen(pSrc->TP_UD); // 用户信息字符串的长度

buf[0] = pSrc->TP_PID; // 协议标识(TP-PID)

buf[1] = pSrc->TP_DCS; // 用户信息编码方式(TP-DCS)

buf[2] = 0; // 有效期(TP-VP)为5分钟

// UCS2编码方式

buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength);

// 转换TP-DA到目标PDU串

nLength = buf[3] + 4; // nLength等于该段数据长度

nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength);

// 转换该段数据到目标PDU串

// 返回目标字符串长度

return nDstLength;

}

PDU解码,用于接收、阅读短消息,输入:pSrc - 源PDU串指针,输出: pDst - 目标PDU参数指针,返回:用户信息串长度。

int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst)

{ int nDstLength; // 目标PDU串长度

unsigned char tmp; // 内部用的临时字节变量

unsigned char buf[256]; // 内部用的缓冲区

// SMSC地址信息段

gsmString2Bytes(pSrc, &tmp, 2); // 取长度

tmp = (tmp - 1) * 2; // SMSC号码串长度

pSrc += 4; // 指针后移,忽略了SMSC地址格式

gsmSerializeNumbers(pSrc, pDst->SCA, tmp); // 转换SMSC号码到目标PDU串

pSrc += tmp; // 指针后移

// TPDU段基本参数

gsmString2Bytes(pSrc, &tmp, 2); // 取基本参数

pSrc += 2; // 指针后移

// 取回复号码

gsmString2Bytes(pSrc, &tmp, 2); // 取长度

if(tmp & 1) tmp += 1; // 调整奇偶性

pSrc += 4; // 指针后移,忽略了回复地址(TP-RA)格式

gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA号码

pSrc += tmp; // 指针后移

// TPDU段协议标识、编码方式、用户信息等

gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取协议标识(TP-PID)

pSrc += 2; // 指针后移

gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取编码方式(TP-DCS)

pSrc += 2; // 指针后移

gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);// 服务时间戳字符串(TP_SCTS)

pSrc += 14; // 指针后移

gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)

pSrc += 2; // 指针后移

// UCS2解码

nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换

nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU

// 返回目标字符串长度

return nDstLength;

}

整体程序的编制就是调用以上函数,从而实现读取显示SMS信息和发送SMS信息的功能。

4 结论

该程序在电表远程监测应用,功能基本完善,性能可靠,由于程序采用标准C语言实现,可以不用改变移植到嵌入式系统使用,具有很好的通用性。

参考文献:

[1] 高守传,聂云铭,郑静.Visual C++开发指南[M].北京:人民邮电出版社,2007.

[2] 胡志坤,秦业,鄢锋.Visual C++通信编程工程实例精解[M].北京:机械工业出版社,2007.

[3] 龚建伟,熊光明.Visual C++/Turbo C 串口通信编程实践[M].2版.北京:电子工业出版社,2007.

[4] 赛奎春,高春艳,李俊民.Visual Basic 工程应用与项目实践[M].北京:机械工业出版社,2007.