/*******************************************************************************
 **作者：SwanDesign
 **内容：GSM模块发送短信全过程
 **网址：http://swantech.taobao.com
 *******************************************************************************/ 
 
首先我们要确保模块开发板已经正常通电并开机，串口线已经和电脑连接。

第一步：关于短消息中心
    命令：短消息中心设置与获取的命令是(AT+CSCA)
    作用：短消息中心负责转播和存储转发短消息。
    设置：命令格式为"AT+CSCA=<SCA>[,<TOSCA>]"
    获取：命令格式为"AT+CSCA?"
    下面我们演示一下，首先进行AT命令的握手，如果握手成功返回，那么说明已经正确的和
    模块进行了连接。+CSCA: "+8613010112500",145
    这个就是我们读取到的存储于SIM卡内部的短消息中心号码，下面我们设置一下，设置成功
    之后返回OK。
    注意：一般情况下我们不需要读取或者设置短消息中心号码就可以实现短信的发送，因为
    短消息中心号码已经存储于SIM卡内部了，具体的操作步骤，我们将在下面介绍。

第二步：设置短消息格式
    命令：短消息格式设置(AT+CMGF)
    作用：短消息分为两种格式-第一种是英文字符短消息，第二种是中文短消息。根据不同的
          需要，我们要在发短信之前进行设置。
    设置：命令格式为"AT+CMGF<MODE>", 如果是要发送中文短消息，那么应该发送"AT+CMGF=0"
          如果要发送英文字符短消息，那么应该发送"AT+CMGF=1"
    获取：命令格式为"AT+CMGF?"
    下面我们来演示一下+CMGF: 0 这个就是我们刚才设置好，然后又读取出来的，同样，我们
    刚才又设置了AT+CMGF=1，然后读取到了+CMGF: 1

第三步：短消息发送
    命令：发送命令（AT+CMGS）
    作用：发送一条中文或者英文短消息。
    说明：如果我们要发送的短信为英文字符短信，那么此时的命令格式为"AT+CMGS=<收件人手机号码>"
          例如收件人手机号码为15313513513，那么我们的命令就是AT+CMGS="15313513513"
          如果我们要发送中文短消息，那么此时的命令格式为"AT+CMGS=<PDU_Length>"
          至于PDU_Length如何计算，我们也将在下面进行描述。

第四步：尝试发送一条英文字符短消息
    首先，我们需要设置短消息中心号码（注意，其实我们在第一步里面已经介绍过短消息中心的概念
          了，也就是说我们可以不对短消息中心号码进行任何设置，因为它已经存储在SIM卡里面了，
          我们那就忽略这一步吧）
    然后，我们设置短消息格式，因为我们要发送的是英文字符短消息，那么我们需要执行第二步里面
          所讲到的AT+CMGF=1命令，这个命令告诉模块我们下面要发送的是一条英文字符短信。
    下面我们来演示一下，我们的目的手机号是15313513513，短消息的内容我们就随便输入了。
    我们刚才输入了我们要发送的内容，但是模块并没有显示发送已经成功，这是为什么呢？其实原因
    很简单，因为我们没有告诉模块我们的输入已经完成，怎么告诉模块我们已经完成了输入了呢？
    答案就是我们要在发送完内容之后，再发送一个十六进制的0x1A告诉模块，输入已经完成，可以发送
    了。下面我们再演示一下
    AT+CMGS="15313513513"
    > http://swantech.taobao.com/
    +CMGS: 226
    OK
    看到了吧，我们发送完http://swantech.taobao.com/之后，又用十六进制发送了一个0x1A，这个之后
    模块启动了短信的发送，最后给我们返回了发送成功的标志。
    
第五步：如何发送中文短信
    要发送中文短信我们需要用到PDU格式，一个PDU包的组成包含好多部分，下面我们哪一个例子过来看一下
    /*******************************************************************************************************|
     * |----------------------------------------------------------------------------------------------------|
     * |SCA  |PDUType |MR |DA                 |PID |DCS |VP    |UDL |UD                       |END          |
     * |----------------------------------------------------------------------------------------------------|
     * |1-12 |1       |1  |2-12               |1   |1   |0,1,7 |1   |0-140                    |1            |
     * |----------------------------------------------------------------------------------------------------|
     * |00   |11      |00 |0D91685113533151F3 |00  |08  |AA    |0C  |9E3F9E4475355B5079D16280 |CTRL+z (0x1A)|
     * |----------------------------------------------------------------------------------------------------|
     *******************************************************************************************************/
    这是我们的一个PDU包的实例，我们可以看到，它分为好多部分，每个部分都有自己的含义。下面我们详细的分析一下
    SCA：这个是短消息中心的部分，默认我们设置为"00"，那么就告诉模块用SIM卡内部存储的短消息中心号码来发送这条
         短信。但是为了让您更加详细的了解SCA的组成，我们还是在下面具体的分析一下吧。
         例如我们的短消息中心号码为+8613010112500，那么它对应的SCA就为
         |------------------------------------|
         |SCA_Len  |SCA_Type  |SCA_ADDR       |
         |08       |91        |683110102105F0 |
         |------------------------------------|
         SCA_Len: 这个数值指的是(SCA_Type + SCA_ADDR)的长度，这里需要注意的是，我们看到SCA_Type的长度是2个字符
                  而SCA_ADDR的长度是14个字节，而实际的SCA_Len的计算公式是SCA_Len=(2+14)/2=8
                  您可能要问，为什么要除以2呢？ 原因就在于我们发送过去的数据是以一种可见的十六进制的格式来发送
                  的，比如我们发送的SCA_Len=08，模块接收之后，要将其转换为只用一个字符来存储的0x08。其实大家也
                  只需要了解一下就行了，不必细究，就按照上面这个公式SCA_Len=(SCA_Type + SCA_ADDR)/2 来计算就可
                  以了。对应到C语言的语句大概就是SCA_Len=(strlen(SCA_Type)+strlen(SCA_ADDR))/2。
         SCA_Type：这个表示的是短消息中心的类型，具体含义大家可以不必了解，只需要用"91"就可以了，如果想要详细
                  的了解，那么可以去参考《SMS_PDU_格式参考手册.doc》。
         SCA_ADDR: 这个就是短消息中心的地址了，那么这个地址是如何计算出来的呢？ 8613010112500 大家数一下这个
                  短消息中心的号码的长度，应该是13个字节的长度，是一个奇数，按照规定，如果这个号码是一个奇数
                  那么我们需要在其后面补一个字符F，把它变为偶数才可以的，8613010112500F ，这还没有完，我们还
                  需要将这个号码的字节顺序调转一下
                  调转之前：86 13 01 01 12 50 0F
                  调转之后：68 31 10 10 21 05 F0
                  结果    : 683110102105F0
                  其实就是以每两个字符为单位进行调转，最后的结果就是683110102105F0 看到了吧 这就是我们的短消息
                  中心号码了。
                  看到这里是不是发现很罗嗦，折腾了半天，而且有点让人很烦，没办法，这都是制定协议的人弄出来的东西
                  我们只能去遵守了，你要问我为什么要这么来操作，我也没法说，呵呵。。。。。大家照做就是了。
                  
    PDUType: 这个字段说起来比较麻烦，每一位都有特定的含义，还好我们不必去细究它，只需要设置一个固定值就可以了
             这里呢我们将它设置为11，具体每一位代表什么含义，大家可以去参考《SMS_PDU_格式参考手册.doc》。
    
    MR：这个字符按就填默认的00就可以了。
    
    DA: 这个就是接受此条短消息的手机号了，它的格式和SCA类似，但是又是有区别的，我们同样以一个例子来进行解析。
        例如我们的目的手机号码是：8615313513513，我刚才加了一个86，这是因为这个手机号码是国内的，每个国家都
        有一个自己的区号的。
        那么对应的表就是
        |-----------------------------------|
        |DA_Len  |DA_Type  |DA_ADDR         |
        |0D      |91       |685113533151F3  |
        |-----------------------------------|
        DA_Len: 这个数值指的是8615313513513这个手机号码的长度，这一点就和SCA不一样了，一定不要弄混了啊。我们数一下
                它的长度是13，那么对应的十六进制就是0D。
        DA_Type:这个和SCA_Type所表示的意思是一样的，不再进行介绍了。
        DA_ADDR:这个也是和SCA_ADDR一样的，同样是奇数长度后面补F变为偶数长度，然后进行调转。
        调转之前：86 15 31 35 13 51 3F
        调转之后：68 51 13 53 31 15 F3
        结果    : 685113533115F3
        
    PID: 这个字符按就填默认的00就可以了。
    
    DCS: 这个是编码类型字段，我们以PDU格式发送中文短信，需要用到UCS2格式的编码，那么就将此字段设置为08就可以了。
    
    VP:  这个字段的含义是短消息的有效期，如果细究起来，也是非常繁琐的，我们一般就将它设置为一个固定的值就可以了。
         我们这里设置为AA。
         
    UDL：这个字符按指的是短消息内容经过编码后的长度。我们同样以一个例子来进行说明，比如我们要发送的中文为
         "鸿鹄电子科技", 因为我们大部分中文程序源码都是以GBK编码来存储的，而我们要发送的是以UCS2编码的字符串，
         所以就需要加一个编码转换，这里呢 我们就用本店的STModem软件里面所提供的一个编码转换工具来实现就行了。
         大家看到，对应的UCS2编码就是"9E3F9E4475355B5079D16280", 我们来数一下这个编码后的长度，长度为24，
         因为这都是可见的十六进制的字符串表示方法，举个例子来说1A，这个用十六进制的可见方式来表示那就是2个字符
         但是最终存储的时候却只占用了一个字节，这个就和我们用串口调试助手一样，看到了吧 虽说我们输入的是1A，
         因为我们采用的是十六进制的格式，所以最终也就只发送了一个字节。
         上面讲的是不是很让人头疼，其实我也不知道该如何表达才能更让人清楚，还好我们不必要去深究这些，只需要按照
         固定的公式来计算UDL就可以了，这里我们的UDL=24/2=12 对应的十六进制就是0C 而对应的C语言语句大概就是
         UDL = strlen("9E3F9E4475355B5079D16280")/2;   就是这么简单，就这样用就行了。
         
   UD： 这个就是短消息的内容了，上面我们已经在UDL里面生成了一个了，我们就用它了："9E3F9E4475355B5079D16280"
        
   END：这个就是结尾的标志了，我们在发送英文短信里面讲到过的，也就是那个十六进制的1A，这里呢 我们将它放在PDU
        字符串里面，其实也是为了方便，而且也是为了防止这个结尾标志漏发，因为某些模块在发送完PDU之后 如果没有
        发送这个标志，模块就会一直等待这个标志，你之后发送给模块的任何AT命令都将得不到回应，模块就像是死机了
        一样，所以要切记，这个结尾标志一定要发送给模块啊。

第六步：上面讲了一大堆，下面我们发送一条中文短信，我们将上面的每个部分都复制下来
        0011000D91685113533151F30008AA0C9E3F9E4475355B5079D16280
        这个就是我们生成的PDU字符串了，在第三步里面我们讲到过AT+CMGS=<PDU_Length>
        这个PDU_Length是如何计算出来的呢？
        首先呢，我们要去掉SCA所占用的长度，大家可以看到，我们上面没有去掉SCA的PDU的长度是56个字节，
        那么去掉之后的长度就是56-2=54 那么我们的PDU_Length=(56-2)/2=27
        好，我们的发送命令就有了，那就是AT+CMGS=27
        下面我们发送以下试试。先要设置为中文PDU格式，用到命令：AT+CMGF=0
        这就是提示我们发送成功了
        AT+CMGS=27

        > 0011000D91685113533151F30008AA0C9E3F9E4475355B5079D16280
        +CMGS: 227

        OK
        切记，最后这个十六进制的1A一定不要忘记，而且大家可以看到最后这个1A是一个小方块，说明他并不是一个可见
        字符，有些同学的1A并不是以十六进制来发送，他们的结果大概就是这个样子的
        AT+CMGS=27

        > 0011000D91685113533151F30008AA0C9E3F9E4475355B5079D162801A
        +CMGS: 227

        OK
        大家看一下，最后的这个1A如果是这种样子，那么你的短信是不能成功发送的。
        
结束语：感谢大家耐心的看完这个教程，教程的时间已经很长了，这个也是我尽量将一些不必要将的问题都去掉之后的结果了
        其实发送短信的过程如果细究，还有好多问题和细节，不过对于一般的应用来说，上面讲的已经足够了，如果想要
        更深入的去了解，那么可以去参考《SMS_PDU_格式参考手册.doc》这个手册，这个手册并不是本人编写的，在这里
        感谢原作者，尊重编写人的辛苦劳动。谢谢大家，祝你成功！！！