最详细的AT指令说明

概述

手机的短消息实现目前有三种方法:

1.通过移动网关发送短消息,使用该方法不需要附加的硬件,但是需要到电信部门申请网关,比较适用于一些大型的网络通讯公司开发,目前华为,中兴等公司就做的这方面的工作,并且还有相应的开发包供开发人员使用.

2.在电脑上通过GSM

MODEM向手机发送中文短消息,这是目前比较适合于小项目开发的一种方法,所需硬件包括一款手机,提供GSM

MODEM,以及相应的数据线或是红外线适配器.该方法编码简单,只需对AT指令和串口编程比较熟悉就可以实现,而且对硬件需求不高,并能自动收发短消息.

3.通过一些网站上提供的短信发送功能来实现,比如新浪网,网易都提供这方面的服务,这种方法是这三种方法中实现起来最简单,所需资源最少的,但是对于网站的依赖性太强,对网络的依赖同样无法避免,不适用于项目开发.

通过第二种方法收发短消息又分为三种模式:Block模式、Text模式和Pdu。使用Block机生产厂家提供驱动支持,现在还没有发现哪个厂家公布支持这种短信发送模式,而Pdu模式开发起来比较复杂,并且需要编写专门的函数来将文本转换为Pdu格式,比较繁琐.相对而言,应用Text模式开发及方便也简单,是一种不错的选择,不过使用Text模式开发只能发送ASCII,对于中文的Unicode码不能发送.

使用Text模式发送短信其实很简单,只要对于AT指令有基本的了解,就能编写出短消息的发送程序,可是一直以来介绍该方法的文章却少之又少,很多人认为使用该方法太简单,不值一提.不过对于简单的应用来说,该方法也不失于一种不错的选择.

短信编码
  在收发短信方面,按时间产生先后,共产生了三种模式:Block Mode、基于AT指令的Text Mode、基于AT指令的PDU Modem, Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因我们主要探讨PDU模式的发送。以西门子3508手机为例。
  SMS是由Etsi所制定的一个规范(GSM 03.40 GSM 03.38)。当使用7-bits编码时,它可以发送最多160个字符;但用8-bit编码,最多可以发送140个字符,通常无法直接通过手机显示;还有用16-bit编码时,最多70个字符,被用来显示Unicode(UCS2)文本信息,可以被大多数的手机所显示。今天讨论的是UCS2编码,也就是说,最多只能发送70个字符,不管英文还是中文。
  现例如我们现在要发送如下信息,向手机13715342642发送"你好,Hello!"。在没有发送之前,你要清楚,手机SIM卡所在地的短信中心号,并不是你现在所在地方的短信中心号,深圳的短信中心号是:8613800755000,即使到外地,短信中心号仍是深圳。从上面得到了下面的信息:
  接收的手机号:13715342642
  短信中心号:8613800755000
  短信内容:你好,Hello!
  在实际使用中,上面这些信息并不为手机所执行,要进行编码手机才会执行,先不管,看看编码后的信息:
0891683108705500F011000D91683117352446F<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2000800124" unitname="F">2000800124F</chmetcnv>60597DFF<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="C">0C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="480065006" unitname="C">00480065006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="C">006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="F">006F</chmetcnv>0021
解释一下:
  08 - 指的是短信中心号的长度,也就是指(91)+( <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="683108705500" unitname="F">683108705500F</chmetcnv>0)的长度
  91 - 指的是短信息中心号码类型。91TON/NPI遵守International/E.164标准,指在号码前需加'+'号;此外还有其它数值,但91最常用。
  <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="683108705500" unitname="F"><span lang="EN-US">683108705500F</span></chmetcnv>0 - 短信息中心号码。由于位置上略有处理,实际号码应为:8613800731500(字母F是指长度减1)。这需要根据不同的地域作相应的修改。前面的(08)+(91)+( <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="683108705500" unitname="F">683108705500F</chmetcnv>0)实际上就构成了整个短信的一部份,通称短消息中心地址(Address of the SMSC)。
  11 - 文件头字节
  00 - 信息类型(TP-Message-Reference
  0D - 被叫号码长度
  91 - 被叫号码类型
  其实在实际处理中,我们通常把11000D91写死在程序中,因为在国内,这些数据都是不会改变的。
  <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="683117352446" unitname="F"><span lang="EN-US">683117352446F</span></chmetcnv>2 -被叫号码,经过了位移处理,实际号码为"8613715342642"。上面的(00+0D+91+( <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="683117352446" unitname="F">683117352446F</chmetcnv>2),构成了整个短信的第二部份目的地址(TP-Destination-Address)。
  00 - 协议标识TP-PID,这里一般为00
  08 - 数据编码方案TP-DCSTP-Data-Coding-Scheme,采用前面说的USC2(16bit)数据编码
  00 - 有效期TP-VPTP-Valid-Period
  12-长度TP-UDLTP-User-Data-Length),也就是<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="4" unitname="F"><span lang="EN-US">4F</span></chmetcnv>60597DFF<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="C">0C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="480065006" unitname="C">00480065006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="C">006C</chmetcnv>的长度 36 / 2 = 18 的十六进 12

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="4" unitname="F"><span class="f141"><span lang="EN-US" style="font-size: 8pt; color: black; font-family: 宋体;">4F</span></span></chmetcnv>60597DFF<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="C">0C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="480065006" unitname="C">00480065006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="C">006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="F">006F</chmetcnv>0021- 这里就是短信内容了,实际内容为:"你好,Hello!"

AT指令

一、 一般命令

1 AT+CGMI 给出模块厂商的标识。

2 AT+CGMM 获得模块标识。这个命令用来得到支持的频带(GSM 900DCS 1800 PCS 1900)。当模块有多频带时,回应可能是不同频带的结合。

3 AT+CGMR 获得改订的软件版本。

4 AT+CGSN 获得GSM模块的IMEI(国际移动设备标识)序列号。

5 AT+CSCS 选择TE特征设定。这个命令报告TE用的是哪个状态设定上的MEME于是可以转换每一个输入的或显示的字母。这个是用来发送、读取或者撰写短信。

6 AT+WPCS 设定电话簿状态。这个特殊的命令报告通过TE电话簿所用的状态的MEME于是可以转换每一个输入的或者显示的字符串字母。这个用来读或者写电话簿的入口。

7 AT+CIMI 获得IMSI。这命令用来读取或者识别SIM卡的IMSI(国际移动签署者标识)。在读取IMSI之前应该先输入PIN(如果需要PIN的话)。

8 AT+CCID 获得SIM卡的标识。这个命令使模块读取SIM卡上的EF-CCID文件。

9 AT+GCAP 获得能力表。(支持的功能)

10 A/ 重复上次命令。只有A/命令不能重复。这命令重复前一个执行的命令。

11 AT+CPOF 关机。这个特殊的命令停止GSM软件堆栈和硬件层。命令AT+CFUN=0的功能与+CPOF相同。

12 AT+CFUN 设定电话机能。这个命令选择移动站点的机能水平。

13 AT+CPAS 返回移动设备的活动状态。

14 AT+CMEE 报告移动设备的错误。这个命令决定允许或不允许用结果码“+CME ERROR:<xxx>”或者“+CMS ERROR:<xxx>”代替简单的“ERROR”。

15 AT+CKPD 小键盘控制。仿真ME小键盘执行命令。

16 AT+CCLK 时钟管理。这个命令用来设置或者获得ME真实时钟的当前日期和时间。

17 AT+CALA 警报管理。这个命令用来设定在ME中的警报日期/时间。(闹铃)

18 AT+CRMP 铃声旋律播放。这个命令在模块的蜂鸣器上播放一段旋律。有两种旋律可用:到来语音、数据或传真呼叫旋律和到来短信声音。

19 AT+CRSL 设定或获得到来的电话铃声的声音级别。

二、 呼叫控制命令

1 ATD 拨号命令。这个命令用来设置通话、数据或传真呼叫。

2 ATH 挂机命令。

3 ATA 接电话。

4 AT+CEER 扩展错误报告。这个命令给出当上一次通话设置失败后中断通话的原因。

5 AT+VTD 给用户提供应用GSM网络发送DTMF(双音多频)双音频。这个命令用来定义双音频的长度(默认值是300毫秒)。

6 AT+VTS 给用户提供应用GSM网络发送DTMF双音频。这个命令允许传送双音频。

7 ATDL 重拨上次电话号码。

8 AT%Dn 数据终端就绪(DTR)时自动拨号。

9 ATS0 自动应答。

10 AT+CICB 来电信差。

11 AT+CSNS 单一编号方案。

12 AT+VGRAT+VGT 增益控制。这个命令应用于调节喇叭的接收增益和麦克风的传输增益。

13 AT+CMUT 麦克风静音控制。

14 AT+SPEAKER 喇叭/麦克风选择。这个特殊命令用来选择喇叭和麦克风。

15 AT+ECHO 回音取消。

16 AT+SIDET 侧音修正。

17 AT+VIP 初始化声音参数。

18 AT+DUI 用附加的用户信息拨号。

19 AT+HUI 用附加的用户信息挂机。

20 AT+RUI 接收附加用户信息。

三、 网络服务命令

1 AT+CSQ 信号质量。

2 AT+COPS 服务商选择。

3 AT+CREG 网络注册。获得手机的注册状态。

4 AT+WOPN 读取操作员名字。

5 AT+CPOL 优先操作员列表。

四、 安全命令

1 AT+CPIN 输入PIN

2 AT+CPIN2 输入PIN2

3 AT+CPINC PIN的剩余的尝试号码。

4 AT+CLCK 设备锁。

5 AT+CPWD 改变密码。

五、 电话簿命令

1 AT+CPBS 选择电话簿记忆存储。

2 AT+CPBR 读取电话簿表目。

3 AT+CPBF 查找电话簿表目。

4 AT+CPBW 写电话簿表目。

5 AT+CPBP 电话簿电话查询。

6 AT+CPBN 电话簿移动动作。这个特殊命令使电话簿中的条目前移或后移(按字母顺序)

7 AT+CNUM 签署者号码。

8 AT+WAIP 防止在下一次重起时初始化所有的电话簿。

9 AT+WDCP 删除呼叫电话号码。

10 AT+CSVM 设置语音邮件号码。

六、 短消息命令

1 AT+CSMS 选择消息服务。支持的服务有GSM-MOSMS-MTSMS-CB

2 AT+CNMA 新信息确认应答。

3 AT+CPMS 优先信息存储。这个命令定义用来读写信息的存储区域。

4 AT+CMGF 优先信息格式。执行格式有TEXT方式和PDU方式。

5 AT+CSAS 保存设置。保存+CSAS+CSMP的参数。

6 AT+CRES 恢复设置。

7 AT+CSDH 显示文本方式的参数。

8 AT+CNMI 新信息指示。这个命令选择如何从网络上接收短信息。

9 AT+CMGR 读短信。信息从+CPMS命令设定的存储器读取。

10 AT+CMGL 列出存储的信息。

11 AT+CMGS 发送信息。

12 AT+CMGW 写短信息并存储。

13 AT+CMSS 从存储器中发送信息。

14 AT+CSMP 设置文本模式的参数。

15 AT+CMGD 删除短信息。删除一个或多个短信息。

16 AT+CSCA 短信服务中心地址。

17 AT+CSCB 选择单元广播信息类型。

18 AT+WCBM 单元广播信息标识。

19 AT+WMSC 信息状态(是否读过、是否发送等等)修正。

20 AT+WMGO 信息覆盖写入。

21 AT+WUSS 不改变SMS状态。在执行+CMGR+CMGL后仍保持UNREAD

七、 追加服务命令

1 AT+CCFC 呼叫继续。

2 AT+CLCK 呼叫禁止。

3 AT+CPWD 改变追加服务密码。

4 AT+CCWA 呼叫等待。

5 AT+CLIR 呼叫线确认限制。

6 AT+CLIP 呼叫线确认陈述。

7 AT+COLP 联络线确认陈述。

8 AT+CAOC 费用报告。

9 AT+CACM 累计呼叫计量。

10 AT+CAMM 累计呼叫计量最大值。

11 AT+CPUC 单价和货币表。

12 AT+CHLD 呼叫相关的追加服务。

13 AT+CLCC 列出当前的呼叫。

14 AT+CSSN 追加服务通知。

15 AT+CUSD 无组织的追加服务数据。

16 AT+CCUG 关闭的用户组。

八、 数据命令

1 AT+CBST 信差类型选择。

2 AT+FCLASS 选择模式。这个命令把模块设置成数据或传真操作的特殊模式。

3 AT+CR 服务报告控制。这个命令允许更为详细的服务报告。

4 AT+CRC 划分的结果代码。这个命令在呼叫到来时允许更为详细的铃声指示。

5 AT+ILRR 本地DTE-DCE速率报告。

6 AT+CRLP 无线电通信线路协议参数。

7 AT+DOPT 其他无线电通信线路参数。

8 AT%C 数据压缩选择。

9 AT+DS 是否允许V42二度数据压缩。

10 AT+DR 是否报告V42二度数据压缩。

11 AT/N 数据纠错选择。

九、 传真命令

1 AT+FTM 传送速率。

2 AT+FRM 接收速率

3 AT+FTH HDLC协议设置传真传送速率。

4 AT+FRH HDLC协议设置传真接收速率。

5 AT+FTS 停止特定时期的传送并等待。

6 AT+FRS 接收沉默。

十、 第二类传真命令

1 AT+FDT 传送数据。

2 AT+FDR 接收数据。

3 AT+FET 传送页标点。

4 AT+FPTS 页转换状态参数。

5 AT+FK 终止会议。

6 AT+FBOR 页转换字节顺序。

7 AT+FBUF 缓冲大小报告。

8 AT+FCQ 控制拷贝质量检验。

9 AT+FCR 控制接收传真的能力。

10 AT+FDIS 当前会议参数。

11 AT+FDCC 设置DCE功能参数。

12 AT+FLID 定义本地ID串。

13 AT+FPHCTO 页转换超时参数。

十一、V24-V25命令

1 AT+IPR 确定DTE速率。

2 AT+ICF 确定DTE-DCE特征结构。

3 AT+IFC 控制DTE-DCE本地流量。

4 AT&C 设置DCD(数据携带检测)信号。

5 AT&D 设置DTR(数据终端就绪)信号。

6 AT&S 设置DST(数据设置就绪)信号。

7 ATO 回到联机模式。

8 ATQ 决定手机是否发送结果代码。

9 ATV 决定DCE响应格式。

10 ATZ 恢复为缺省设置。

11 AT&W 保存设置。

12 AT&T 自动测试。

13 ATE 决定是否回显字符。

14 AT&F 回到出厂时的设定。

15 AT&V 显示模块设置情况。

16 ATI 要求确认信息。这命令使GSM模块传送一行或多行特定的信息文字。

17 AT+WMUX 数据/命令多路复用。

十二、特殊AT命令

1 AT+CCED 电池环境描述。

2 AT+CCED 自动RxLev指示。

3 AT+WIND 一般指示。

4 AT+ALEA MEMSC之间的数据密码模式。

5 AT+CRYPT 数据密码模式。

6 AT+EXPKEY 键管理。

7 AT+CPLMN PLMN上的信息。

8 AT+ADC 模拟数字转换度量。

9 AT+CMER 移动设备事件报告。这个命令决定是否允许在键按下时是否主动发送结果代码。

10 AT+WLPR 读取语言偏好。

11 AT+WLPW 写语言偏好。

12 AT+WIOR 读取GPIO值。

13 AT+WIOW GPIO值。

14 AT+WIOM 输入/输出管理。

15 AT+WAC 忽略命令。这个特殊命令允许忽略SMSSS和可用的PLMN

16 AT+WTONE 播放旋律。

17 AT+WDTMF 播放DTMF旋律。

18 AT+WDWL 下载模式。

19 AT+WVR 配置信差的声音速率。

20 AT+WDR 配置数据速率。

21 AT+WHWV 显示硬件的版本。

22 AT+WDOP 显示产品的出厂日期。

23 AT+WSVG 声音增益选择。

24 AT+WSTR 返回指定状态的状态。

25 AT+WSCAN 扫描。

26 AT+WRIM 设置或返回铃声指示模式。

27AT+W32K 是否允许32kHz掉电方式。

28 AT+WCDM 改变缺省旋律。

29 AT+WSSW 显示内部软件版本。

30 AT+WCCS 编辑或显示订制性质设置表。

31 AT+WLCK 允许在特定的操作符上个性化ME

32 AT+CPHS 设置CPHS命令。

33 AT+WBCM 电池充电管理。

34 AT+WFM 特性管理。是否允许模块的某些特性,如带宽模式、SIM卡电压等。

35 AT+WCFM 商业特性管理。是否允许Wavecom特殊特性。

36 AT+WMIR 允许从当前存储的参数值创建定制的存储镜像。

37 AT+WCDP 改变旋律的缺省播放器。

38 AT+WMBN 设置SIM卡中的不同邮箱号码。

十三、SIM卡工具箱命令

1 AT+STSF 配置工具箱实用程序。

2 AT+STIN 工具箱指示。

3 AT+STGI 获得从SIM卡发来的预期命令的信息。

4 AT+STCR 主动提供的结果:工具箱控制反应。

5 AT+STGR 给出响应。允许程序或用户从主菜单上选择项目,或响应某些命令

常用的与SMS有关的GSM AT指令(GSM07.05)如表1所示:

AT 指令

AT+CMGC

Send an SMS command(发出一条短消息命令)

AT+CMGD

Delete SMS message(删除SIM卡内存的短消息)

AT+CMGF

Select SMS message formate(选择短消息信息格式:0-PDU;1-文本)

AT+CMGL

List SMS message from preferred store(列出SIM卡中的短消息PDU/text: 0/"REC UNREAD"-未读,1/"REC READ"-已读,2/"STO UNSENT"-待发,3/"STO SENT"-已发,4/"ALL"-全部的)

AT+CMGR

Read SMS message(读短消息)

AT+CMGS

Send SMS message(发送短消息)

AT+CMGW

Write SMS message to memory(向SIM内存中写入待发的短消息)

AT+CMSS

Send SMS message from storage(从SIN|M内存中发送短消息)

AT+CNMI

New SMS message indications(显示新收到的短消息)

AT+CPMS

Preferred SMS message storage(选择短消息内存)

AT+CSCA

SMS service center address(短消息中心地址)

AT+CSCB

Select cell broadcast messages(选择蜂窝广播消息)

AT+CSMP

Set SMS text mode parameters(设置短消息文本模式参数)

AT+CSMS

Select Message Service(选择短消息服务)

以实例来说明这些指令的使用方法:
  先用手机数据线将手机连接到电脑串口,并将串口的波特率设置为19200,可以开始了。
  1、首先测试你的连接及手机是否支持AT指令,请在你的串口调试程序中输入:
  AT<回车>
  屏幕上返回"OK"表明计算机与手机连接正常,那样我们就可以进行其它的AT指令测试了
  2、设置短信发送格式
  AT+CMGF=1<回车>
  屏幕上返回"OK"表明现在短信的发送方式为PDU方式,如果是设置为TEXT方式,则,AT+CMGF=0<回车>
  3、 发送短信
  发送内容及手要号仍旧同上面在编码中的一样,编码后,得到要发送的数据如下
0891683108705505F011000D91683117352446F<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2000800124" unitname="F">2000800124F</chmetcnv>60597D<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2" unitname="C">002C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="480065006" unitname="C">00480065006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="C">006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="F">006F</chmetcnv>0021
  我们用如下指令来发送
  AT+CMGS=33<回车>
  如果返回"",就把上面编码数据输入,并以CTRL+Z结尾,稍等一下,你就可以看到返回OK啦。

  说明一下,为什么AT+CMGS=33呢,是这样得来的:
11000D91683117352446F<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2000800124" unitname="F">2000800124F</chmetcnv>60597D<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2" unitname="C">002C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="480065006" unitname="C">00480065006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="C">006C</chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="6" unitname="F">006F</chmetcnv>0021
  这一段字符串的长度除以2得到的结果,上面的字符串,短信中心号加上短信内容得到的,怎么得到的,请回顾一下解码部份
  在我们前面的讨论中,一条完整的短信发送,只要执行三条AT指令,ATAT+CMGS=?、AT+CMGS=?就可以了。由于篇幅,我只能在这里提到这么多,大家要是想了解更多,可以向各手机厂商索取AT指令白皮书,里面很详细的。

串口通信

C#实现
    通常,在C#中实现串口通信,我们有四种方法:
  第一:通过MSCOMM控件这是最简单的,最方便的方法。可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册,不在本文讨论范围。可以访问http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=320
  第二:微软在.NET新推出了一个串口控件,基于.NETP/Invoke调用方法实现,详细的大家可以访问微软网站http://msdn.microsoft.com/msdnmag/issues/02/10/NETSerialComm/default.aspx,方便得到更多资料。
  第三:就是用第三方控件

第四:自己用API写串口通信

Vc++API调用串口非多线程

一、设置串口相关工作

#define MAXBLOCK 2048

#define XON 0x11

#define XOFF 0x13

BOOL SetCom(HANDLE &m_hCom, const char *m_sPort, int

BaudRate, int Databit, CString parity, CString stopbit)

{

COMMTIMEOUTS TimeOuts; ///串口输出时间 超时设置

DCB dcb; ///与端口匹配的设备

m_hCom=CreateFile(m_sPort, GENERIC_READ |

GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |

FILE_FLAG_OVERLAPPED,

NULL); // 以重叠方式打开串口

if(m_hCom==INVALID_HANDLE_VALUE)

{

AfxMessageBox("设置串口部分,串口打开失败"); /重叠方式

异步通信(INVALID_HANDLE_VALUE)函数失败。

return FALSE;

}

SetupComm(m_hCom,MAXBLOCK,MAXBLOCK); //设置缓冲区

memset(&TimeOuts,0,sizeof(TimeOuts));

TimeOuts.ReadIntervalTimeout=MAXDWORD; //

把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作

TimeOuts.ReadTotalTimeoutMultiplier=0; //读时间系数

TimeOuts.ReadTotalTimeoutConstant=0; //读时间常量

TimeOuts.WriteTotalTimeoutMultiplier=50;

//总超时=时间系数*要求读/写的字符数+时间常量

TimeOuts.WriteTotalTimeoutConstant=2000;

//设置写超时以指定WriteComm成员函数中的

SetCommTimeouts(m_hCom, &TimeOuts);

//GetOverlappedResult函数的等待时间*/

if(!GetCommState(m_hCom, &dcb))

串口打开方式、端口、波特率 与端口匹配的设备

{

AfxMessageBox("GetCommState Failed");

return FALSE;

}

dcb.fParity=TRUE; //允许奇偶校验

dcb.fBinary=TRUE;

if(parity=="NONE")

dcb.Parity=NOPARITY;

if(parity=="ODD")

dcb.Parity=ODDPARITY;

if(parity=="EVEN")

dcb.Parity=EVENPARITY;

if(stopbit=="1")//设置波特率

dcb.StopBits=ONESTOPBIT;

//if(stopbit=="0")//设置波特率

// dcb.StopBits=NONESTOPBIT;

if(stopbit=="2")//设置波特率

dcb.StopBits=TWOSTOPBITS;

BOOL m_bEcho=FALSE; ///

int m_nFlowCtrl=0;

BOOL m_bNewLine=FALSE; ///

dcb.BaudRate=BaudRate; // 波特率

dcb.ByteSize=Databit; // 每字节位数

// 硬件流控制设置

dcb.fOutxCtsFlow=m_nFlowCtrl==1;

dcb.fRtsControl=m_nFlowCtrl==1

?RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;

// XON/XOFF流控制设置(软件流控制!)

dcb.fInX=dcb.fOutX=m_nFlowCtrl==2;

dcb.XonChar=XON;

dcb.XoffChar=XOFF;

dcb.XonLim=50;

dcb.XoffLim=50;

if(SetCommState(m_hCom, &dcb))

return TRUE; com的通讯口设置

else

{

AfxMessageBox("串口已打开,设置失败");

return FALSE;

}

}

二、读串口操作:

int ReadCom(HANDLE hComm, BYTE inbuff[], DWORD

&nBytesRead, int ReadTime)

{

DWORD lrc; ///纵向冗余校验

DWORD endtime; /jiesuo

static OVERLAPPED ol;

int ReadNumber=0;

int numCount=0 ; //控制读取的数目

DWORD dwErrorMask,nToRead;

COMSTAT comstat;

ol.Offset=0; ///相对文件开始的字节偏移量

ol.OffsetHigh=0;

///开始传送数据的字节偏移量的高位字,管道和通信时调用进程可忽略。

ol.hEvent=NULL; ///标识事件,数据传送完成时设为信号状态

ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)

for(int i=0;i<2000;i++)

inbuff[i]=0;

Sleep(ReadTime);

ClearCommError(hComm,&dwErrorMask,&comstat);

nToRead=min(2000,comstat.cbInQue);

if(int(nToRead)<2)

goto <place w:st="on">Loop</place>;

if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,&ol))

{

if((lrc=GetLastError())==ERROR_IO_PENDING)

{

///

endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)

while(!GetOverlappedResult(hComm,&ol,&nBytesRead,FALSE))//该函数取回重叠操作的结果

{

if(GetTickCount()>endtime)

break;

}

}

}

return 1;

<place w:st="on"><span lang="EN-US" style="font-size: 8pt; font-family: 宋体;">Loop</span></place>: return 0;

}

三、写串口命令

int WriteCom(HANDLE hComm, BYTE Outbuff[], int size, int

bWrite[])

{

DWORD nBytesWrite,endtime,lrc;

static OVERLAPPED ol;

DWORD dwErrorMask,dwError;

COMSTAT comstat;

ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ol.Offset=0;

ol.OffsetHigh=0;

ol.hEvent=NULL; ///标识事件,数据传送完成时,将它设为信号状态

ClearCommError(hComm,&dwErrorMask,&comstat);

if(!WriteFile(hComm,Outbuff,size,&nBytesWrite,&ol))

{

if((lrc=GetLastError())==ERROR_IO_PENDING)

{

endtime=GetTickCount()+1000;

while(!GetOverlappedResult(hComm,&ol,&nBytesWrite,FALSE))

{

dwError=GetLastError();

if(GetTickCount()>endtime)

{

AfxMessageBox("写串口时间过长,目前串口发送缓冲区中的数据数目为空");

break;

}

if(dwError=ERROR_IO_INCOMPLETE)

continue; //未完全读完时的正常返回结果

else

{

// 发生错误,尝试恢复!

ClearCommError(hComm,&dwError,&comstat);

break;

}

}

}

}

FlushFileBuffers(hComm);

PurgeComm(hComm,PURGE_TXCLEAR);

bWrite=0;

return 1;

}

四、调用方法很简单,只需要将你的串口参数进行简单的设置就可以了。比如:

BOOL OpenCom()//设置COM

{

int Boundrate=9600;//波特率

CString StopBits="1";//停止位

int DataBits=8;//数据位

CString Parity="ODD";//奇偶校验

CString m_Port="COM1";

Return SetCom(m_hCom1,m_Port,Boundrate,DataBits,Parity,StopBits);

}

void <place w:st="on">Main</place>()

{

int SIZE;

DWORD BytestoRead=52*Count+6;//11个字节

int BWRITE[2];

int ReadTime=2000;

BYTE Outbuff[12]={0xff,0x00,0xea,0xff,0xea,0xff,0,0,0,0,0,0};

SIZE=sizeof(Outbuff);

WriteCom(m_hCom,Outbuff,SIZE,BWRITE);

ReadCom(m_hCom,m_Inbuff,BytestoRead,ReadTime);

//进行相应的解包处理

}

简单的Vb使用TEXT模式

使用Text模式发送短信其实很简单,对于简单的应用来说,该方法也不失于一种不错的选择.

先在项目中添加Mscomm控件,一般的部件栏中可能没有列出Mscomm控件,可以过右击部件栏,选择”部件”,或是通过在菜单中的”工程”选择”部件”,然后选中Microsoft

Comm Control 6.0即可.添加了Mscomm控件后,可以设置一些基本的参数.如果你使用Nokia的手机,你还必须安装data

suite(可以到Nokia的开发论坛上去下载一个),然后Mscommcommport选择3;如果你使用其他手机,采用红外线接口,你必须安装红外线驱动程序.选择相应的端口.下面的代码是一些基本参数的设置:

Mscomm1.Settings=9600,N,8,<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="”">1<span lang="EN-US"><span lang="EN-US">”</span></span></chmetcnv> 9600波特,无奇偶校验,8位数据,一个停止位

Mscomm1.InputLen=0 ‘读入整个缓冲区

Mscomm1.Portopen=True ‘打开端口

发送短消息的代码如下:

MSComm1.Output = "AT+CMGF=1" + vbCr ‘设置发送的模式,注意:一定要加上

vbCr

MSComm1.Output = "AT+CSCA=" & Chr$(34) & "8613010341500" &

Chr$(34) & ",129" + vbCr 8613010341500是短消息中心,各地的号码不一样,必须设置当地的短消息号码

MSComm1.Output = "AT+CMGS=" & Chr$(34) & "13057575064" &

Chr$(34) & ",129" + vbCr 13057575064是对方手机号

MSComm1.Output = "test" & Chr$(26) chr$(26)Ctr+ Z

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
短信内容的存储类 /*** * CommonSms 短信用于全局变量 */ public class CommonSms{ /** id */ private int id; /**短信内容*/ private String smstext; /**短信发送方*/ private String sender;//短信发送方 /**短信接收发*/ private String recver;//短信接收发 /**时间*/ private Date date; public String getSmstext() { return smstext; } public void setSmstext(String smstext) { this.smstext = smstext; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public int getId() { return id; } public void setId(Integer id) { this.id = id; } public String getSender() { return sender; } public void setSender(String sender) { this.sender = sender; } public String getRecver() { return recver; } public void setRecver(String recver) { this.recver = recver; } } 串口操纵实现类 /*** * 串口操纵实现类 */ public class Port { private CommPortIdentifier portId; private SerialPort serialPort; private OutputStreamWriter out; private InputStreamReader in; private String COMname; private static char symbol1 = 13; public String getCOMname() { return COMname; } public void setCOMname(String mname) { COMname = mname; } public CommPortIdentifier getPortId() { return portId; } public void setPortId(CommPortIdentifier portId) { this.portId = portId; } public SerialPort getSerialPort() { return serialPort; } public void setSerialPort(SerialPort serialPort) { this.serialPort = serialPort; } public OutputStreamWriter getOut() { return out; } public void setOut(OutputStreamWriter out) { this.out = out; } public InputStreamReader getIn() { return in; } public void setIn(InputStreamReader in) { this.in = in; } public boolean isused =true; public boolean isIsused() { return isused; } public void setIsused(boolean isused) { this.isused = isused; } /** * 打开com口 * @param portName * @return */ public Port(String portName) { try { portId = CommPortIdentifier.getPortIdentifier(portName); if (portId == null) { System.out.println("port is null"); } try { serialPort = (SerialPort) portId.open(portName,100000); } catch (PortInUseException e) { System.gc(); e.printStackTrace(); } // 下面是得到用于和COM口通讯的输进、输出流。 try { in = new InputStreamReader(serialPort.getInputStream()); out = new OutputStreamWriter(serialPort.getOutputStream()); } catch (IOException e) { System.gc(); System.out.println("IOException"); } // 下面是初始化COM口的传输参数,如传输速率:9600等。 try { serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); setCOMname(portId.getName()); setIsused(true); } catch (UnsupportedCommOperationException e) { e.printStackTrace(); System.gc(); } } catch (NoSuchPortException e) { e.printStackTrace(); System.gc(); } } /** * 检查SIM是否存在 * @return */ public boolean chakanPort() { try { String atCommand = "AT+ccid"; String strReturn = sendAT(atCommand); if (strReturn.indexOf("OK", 0) != -1) { return true; } return false; } catch (Exception ex) { System.gc(); ex.printStackTrace(); return false; } } /** * 封闭COM口 * @return boolean */ public void close() { try { in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } serialPort.close(); System.gc(); setIsused(false); } /** * 向串口中写进字符串命令 * @param s 字符串命令 * @throws Exception 异常 */ public void writeln(String s) throws Exception { out.write(s); out.write('\r'); out.flush(); } /** * 读取COM命令的返回字符串 * @return 结果字符串 * @throws Exception */ public String read() throws Exception { int n, i; char c; String answer = ""; for (i = 0; i < 100; i++) { while (in.ready()) { n = in.read(); if (n != -1) { c = (char) n; answer = answer + c; Thread.sleep(1); } else break; } if (answer.indexOf("OK") != -1) { break; } Thread.sleep(100); } return answer; } /** * 向串口发送AT指令 * @param atcommand 指令内容 * @return 指令返回结果 * @throws java.rmi.RemoteException */ public String sendAT(String atcommand) throws java.rmi.RemoteException { String s = ""; try { Thread.sleep(100); writeln(atcommand); Thread.sleep(80); s = read(); Thread.sleep(100); } catch (Exception e) { System.gc(); System.out.println("ERROR: send AT command failed; " + "Command: " + atcommand + "; Answer: " + s + " " + e); } return s; } } 短信操纵类 /*** * 短信操纵类 */ public class Sms{ private CommonSms commonsms; private static char symbol1 = 13; private static String strReturn = "", atCommand = ""; public boolean SendSms(Port myport) { if(!myport.isIsused()) { System.out.println("COM通讯端口未正常打开!"); return false; } setMessageMode(myport,1); // 空格 char symbol2 = 34; // ctrl~z 发送指令 char symbol3 = 26; try { atCommand = "AT+CSMP=17,169,0,08" + String.valueOf(symbol1); strReturn = myport.sendAT(atCommand); System.out.println(strReturn); if (strReturn.indexOf("OK", 0) != -1) { atCommand = "AT+CMGS=" + commonsms.getRecver() + String.valueOf(symbol1); strReturn = myport.sendAT(atCommand); atCommand = StringUtil.encodeHex(commonsms.getSmstext().trim()) + String.valueOf(symbol3) + String.valueOf(symbol1); strReturn = myport.sendAT(atCommand); if (strReturn.indexOf("OK") != -1 && strReturn.indexOf("+CMGS") != -1) { System.out.println("短信发送成功..."); return true; } } } catch (Exception ex) { ex.printStackTrace(); System.out.println("短信发送失败..."); return false; } System.out.println("短信发送失败..."); return false; } /** * 设置消息模式 * @param op * 0-pdu 1-text(默认1 文本方式 ) * @return */ public boolean setMessageMode(Port myport,int op) { try { String atCommand = "AT+CMGF=" + String.valueOf(op) + String.valueOf(symbol1); String strReturn = myport.sendAT(atCommand); if (strReturn.indexOf("OK", 0) != -1) { System.out.println("*************文本方式设置成功************"); return true; } return false; } catch (Exception ex) { ex.printStackTrace(); return false; } } /** * 读取所有短信 * @return CommonSms集合 */ public List RecvSmsList(Port myport) { if(!myport.isIsused()) { System.out.println("System Message: COM通讯端口未正常打开!"); return null; } List listMes = new ArrayList(); try { atCommand = "AT+CMGL=\"ALL\""; strReturn = myport.sendAT(atCommand); listMes = StringUtil.analyseArraySMS(strReturn); } catch (Exception ex) { ex.printStackTrace(); } return listMes; } /** * 删除短信 * @param index 短信存储的位置 * @return boolean */ public boolean DeleteSMS(int index,Port myport) { if(!myport.isIsused()){ System.out.println("System Message: COM通讯端口未正常打开!"); return false; } try { atCommand = "AT+CMGD=" + index; strReturn = myport.sendAT(atCommand); if (strReturn.indexOf("OK") != -1) { System.out.println("System Message: 成功删除存储位置为" + index + "的短信......"); } } catch (Exception ex) { ex.printStackTrace(); } return true; } /** * 删除短信中所有短信 * @return boolean */ public boolean DeleteAllSMS(Port myport) { List list=RecvSmsList(myport); boolean ret=true; if(list!=null&&!list.equals("")&&list;.size()>0) { for(int i=0;i<list.size();i++) { CommonSms tempcomsms=(CommonSms)list.get(i); if(!DeleteSMS(tempcomsms.getId(),myport)) { ret=false; } } } return ret; } public CommonSms getCommonsms() { return commonsms; } public void setCommonsms(CommonSms commonsms) { this.commonsms = commonsms; } /** * 号码,内容,发送短信息 * @param phone * @param countstring * @throws Exception */ public static void sendmsn(String phone,String countstring){ Sms s = new Sms(); // 发送测试 CommonSms cs=new CommonSms(); cs.setRecver(phone); cs.setSmstext(countstring); s.setCommonsms(cs); Port myort=new Port("COM7"); s.SendSms(myort); myort.close(); } public static void main(String[] args) throws Exception { sendmsn("13265551149","我有一筐的愿看,却等不到一颗流星,闭上眼睛,我看到了我的前途"); } 指令字符串操纵类 /*** * 指令字符串操纵类 */ public class StringUtil { /** * 使用Sms 的RecvSms(int index)的方法时,使用该方法解析MODEM返回的字符串 * 根据MODEM返回的字符串,解析成一个CommonSms对象 * @param str 串口返回的读取短信结果字符串 * @param index 短信索引 * @return */ public static CommonSms analyseSMS(String str, int index) { CommonSms commonSms = new CommonSms(); String mesContent; String[] s = str.split("\""); int len = s.length; commonSms.setId(index); mesContent = s[len - 1]; if (mesContent.indexOf("OK") != -1) { mesContent = mesContent.substring(0, mesContent.indexOf("OK")); } mesContent = mesContent.trim(); commonSms.setSmstext(analyseStr(mesContent)); // 短信有中文时使用 // mes.setMessage(Unicode2GBK(analyseStr(mesContent))); SimpleDateFormat df = new SimpleDateFormat("yy/MM/dd hh:mm:ss"); String datestring = s[len - 2].substring(0, s[len - 2].length() - 3) .replace(',', ' ');// 短信时间格式09/09/09 20:18:01+32 Date date = null; try { date = df.parse(datestring); System.out.println(date.toLocaleString()); } catch (Exception ex) { System.out.println(ex.getMessage()); } commonSms.setDate(date); if (s[1].equals("REC READ")) { commonSms.setState("已读"); } else { commonSms.setState("未读"); } commonSms.setSender(s[3]); return commonSms; } /** * 使用Sms 的RecvSmsList()方法时,通过该方法解析MODEM返回来的字符串 * 根据MODEM返回的字符串,解析成一个CommonSms的集合对象 * @param str MODEM返回的字符串 * @return */ public static List analyseArraySMS(String str) { List mesList = new ArrayList(); CommonSms cs; String[] messages; String temp; String[] t; if (str.indexOf("CMGL: ") == -1) return null; str = str.substring(0, str.indexOf("OK")).trim(); messages = str.split("\n"); if (messages.length < 2) return null; for (int i = 1; i 5) { cs.setId(Integer.parseInt(t[0].trim())); temp = t[1].substring(t[1].indexOf('"') + 1, t[1].lastIndexOf('"')).trim(); if (temp.equals("REC READ")) { cs.setState("已读"); } else { cs.setState("未读"); } cs.setSender((t[2].substring(t[2].indexOf('"') + 1, t[2] .lastIndexOf('"')).trim())); SimpleDateFormat df = new SimpleDateFormat("yy/MM/dd hh:mm:ss"); String datestring = t[4].substring(t[4].indexOf('"') + 1) + " " + t[5].substring(0, t[5].indexOf('"'));// 短信时间格式09/09/09 // 20:18:01+32 Date date = null; try { date = df.parse(datestring); } catch (Exception ex) { System.out.println(ex.getMessage()); } cs.setDate(date); i++; cs.setSmstext(analyseStr(messages[i].trim())); mesList.add(cs); } } return mesList; } /** * 将PDU编码的十六进制字符串 如“4F60597DFF01” 转换成unicode "\u4F60\u597D\uFF01" * @param str 要转化的字符串 * @return 转换后的十六进制字符串 */ public static String analyseStr(String str) { StringBuffer sb = new StringBuffer(); if (!(str.length() % 4 == 0)) return str; for (int i = 0; i < str.length(); i++) { if (i == 0 || i % 4 == 0) { sb.append("\\u"); } sb.append(str.charAt(i)); } return Unicode2GBK(sb.toString()); } /** * 将unicode编码 "\u4F60\u597D\uFF01" 转换成中文 "你好!" * @param dataStr 要转化的字符串 * @return 转换后的中文字符串 */ public static String Unicode2GBK(String dataStr) { int index = 0; StringBuffer buffer = new StringBuffer(); while (index < dataStr.length()) { if (!"\\u".equals(dataStr.substring(index, index + 2))) { buffer.append(dataStr.charAt(index)); index++; continue; } String charStr = ""; charStr = dataStr.substring(index + 2, index + 6); char letter = 0; try{letter = (char) Integer.parseInt(charStr, 16);}catch (Exception e) {} buffer.append(letter); index += 6; } return buffer.toString(); } /** * 将中文字符串转换成Unicode * @param str 要转换的中文字符串 * @return 转换后的Unicode */ public static String GBK2Unicode(String str) { StringBuffer result = new StringBuffer(); for (int i = 0; i < str.length(); i++) { char chr1 = (char) str.charAt(i); if (!isNeedConvert(chr1)) { result.append(chr1); continue; } try{result.append("\\u" + Integer.toHexString((int) chr1));}catch (Exception e) {} } return result.toString(); } /** * 在中文字符串转换成Unicode方法中判定是否需要转换 * @param para 要转化的字符 * @return boolean */ public static boolean isNeedConvert(char para) { return ((para & (0x00FF)) != para); } /** * 使用Sms 的 SendSms()方法发送短信时,调用此方法将其短信内容转换成十六进制 * @param msg 短信内容 * @return 转换后的十六进制短信 */ public static final String encodeHex(String msg) { byte[] bytes = null; try { bytes = msg.getBytes("GBK"); } catch (java.io.UnsupportedEncodingException e) { e.printStackTrace(); } StringBuffer buff = new StringBuffer(bytes.length * 4); String b = ""; char a; int n = 0; int m = 0; for (int i = 0; i 0) { buff.append("00"); buff.append(b); n = n + 1; } else { a = msg.charAt((i - n) / 2 + n); m = a; try{b = Integer.toHexString(m);}catch (Exception e) {} buff.append(b.substring(0, 4)); i = i + 1; } } return buff.toString(); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值