jackjie 发表于 2011-4-9 22:10:51

关于TC35i短信发送的问题

最近忙于做自己的毕业设计,是关于单片机通过GSM收发短信的。我现在遇到了这样一个问题:
      就是,我基本上编程实现了短信的PDU编码发送,但是我发现有时短信成功发送后,对方手机能成功收到,有时就不能了。
程序我没做改动。
      我用串口同时在电脑上看观看,单片机和GSM模块串口通信数据情况,具体如下拖:我是PDU编码发送中文“中国!”,我
发现,一个规律:就是我用CMGS命令发送出去的PDU,(1)若其只返回OK,没有返回+CMGS: <MR>消息参考值时,对方不能收到短信
                                             (2)若其返回OK,同时有+CMGS: <MR>消息参考值时,对方能收到数据。                                 
出现上面两种,情况是在我程序,完全没变的情况下出现的。我确定不了是哪里出现了问题。我觉得有可能是自己在发送错误信息是
改变了他的一些参数,因为我出现上面(1)。情况时,用网上找的一个手机上位机初始化下就又可以回复到(2)。但是我不知道到底
是那个参数变了。因为短信相关的参数主要好像就:CSCA,CMGF,CSMS样。但是这些好像都没变的。还请大侠们,帮忙分析下。谢了。
http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_629653Q7BB5A.jpg
(1)情况没有返回消息参考值,只返回OK;(2)情况消息参考值和OK都返回了 (原文件名:1.jpg)

http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_629654WKKBVO.jpg
我就用下这个软件红色圈的按键,初始化下就好了 (原文件名:2.jpg)

studykaka 发表于 2011-4-10 09:35:00

#include "main.h"
#include "SysTick.h"
#include "Serial.h"
#include "Delay.h"
#include "Watchdog.h"
#include "eeprom.h"
#include "GSM_V1.h"
#include "Ex_Isr.h"
#include "Sms.h"

const unsigned char code *SCA_FO_MR_DA = "0011000D9168";
const unsigned char code *SMS_parameter = "0008FF";
const char code Ctrl_z[] = {0x1A, 0x00};

const unsigned char code ASIIC[]=
{       
        '0', '1', '2', '3',
        '4', '5', '6', '7',
        '8', '9', 'A', 'B',
        'C', 'D', 'E', 'F'
};

// 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补'F'凑成偶数
// 如:"8613851872468" --> "683158812764F8"
// pSrc:                 待转换的源字符串指针
// pDst:                 转换后的目标字符串指针
// nSrcLength:         等转换的源字符串长度
// 返回:                 转换后的目标字符串长度,包含了字符串结束符'\0'的长度
unsigned char GsmInvertNumbers(unsigned char *pSrc, unsigned char *pDst, unsigned char nSrcLength)
{
    unsigned char nDstLength;                           // 目标字符串长度
    unsigned char ch;                                  // 用于保存一个字符
        unsigned char i;
   
        nDstLength = nSrcLength;                // 复制串长度
   
        for (i=0; i<nSrcLength; i+=2)        // 两两颠倒
        {
      ch = *pSrc++;                      // 保存先出现的字符
      *pDst++ = *pSrc++;                   // 复制后出现的字符
      *pDst++ = ch;                      // 复制先出现的字符
        }
   
    if (nSrcLength & 1)                        // 源串长度是奇数吗?
    {
      *(pDst-2) = 'F';           // 补'F'
      nDstLength++;              // 目标串长度加1
    }
   
    *pDst = '\0';                                // 输出字符串加个结束符
        return nDstLength;                        // 返回目标字符串长度,加上了'\0'的长度
}
   
/*
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 测试ok
// 字节数据转换为可打印字符串
// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
// pSrc:                 待转换的源数据指针
// pDst:                 转换后存放目标字符串指针
// nSrcLength:         待转换的源数据长度,数据长度不能大于256个字节,从1开始
// 返回:                 转换后的目标字符串长度 <=0xffff,带字符串结束符'\0'。
unsigned char GsmBytes2String(const unsigned char *pSrc, unsigned char *pDst, unsigned char nSrcLength)
{
        unsigned char i;
    const unsigned char code tab[] = "0123456789ABCDEF";            // 0x0-0xf的字符查找表
        for (i=0; i<nSrcLength; i++)
        {       
                *pDst = tab >> 4];                                        // 输出高4位
                pDst++;
                *pDst = tab & 0x0f];                                // 输出低4位
                pDst++;                                                                                // 转换下一个十六进制字节
    }
        pDst++;
        *pDst = '\0';                                                                        // 输出字符串加个结束符
        return (nSrcLength * 2 + 1);                                        // 返回目标字符串长度,带字符串结束符'\0'
}
*/



请注意:
const unsigned char code *SCA_FO_MR_DA = "0011000D9168";
const unsigned char code *SMS_parameter = "0008FF";
const char code Ctrl_z[] = {0x1A, 0x00};

例子:
AT+CMGF=0

OK
AT+CSCS="UCS2"

OK
AT+CMGS=065

> 0011000D91685192659365F90008FF325C0A656C76845BA26237FF0C60A876848F668F7D65FA65FA5DF288AB89E653D1FF0C8BF75C3D5FEB524D5F8067E5770BFF01
+CMGS: 98

OK

bangbangji 发表于 2011-4-10 10:23:16

看看是不是发送那一长串的时候多了一个换行符

jackjie 发表于 2011-4-10 10:29:30

楼上的,谢谢你的回复。呵呵 看你编写的大体模块好像是参照 基于GSM和单片机的远程家电控制系统(毛慧琴)论文编写的的哈 我也是参照她那个自己编写的。目前实现了发短信。
但是我出现了一个情况:就是用CMGS发送短信,TC35i的返回值:
                                          有时只返回了OK,而没有返回+CMGS: <MR>;同样的程序:
                                          有时又可以返回 +CMGS: <MR> 以及OK。
+CMGS: <MR> 和 OK 都返回的短信,对方能成功收到
只返回OK的短信:对方不能收到

今天上午来了,有仔细想了半天。还是没弄明白是怎么回事。还请论坛大虾指导下哈。谢谢

jackjie 发表于 2011-4-10 10:44:28

回复【2楼】bangbangji
-----------------------------------------------------------------------
用串口调试助手看了 两种情况发送的源PDU串是相同的。只是TC35i返回的不同:1)、OK   ; 2、+CMGS: <MR> + OK

bangbangji 发表于 2011-4-10 10:52:00

回复【4楼】jackjie
-----------------------------------------------------------------------

建议你再试试,比如你发送0011000D91685192659365F90008FF325C0A656C76845BA26237FF0C60A876848F668F7D65FA65FA5DF288AB89E653D1FF0C8BF75C3D5FEB524D5F8067E5770BFF01
最后没有换行符,有换行符是发不出去的,但也会返回OK。拷贝上去的代码在串调里发送之前也看看最后有没有换行。

studykaka 发表于 2011-4-10 11:00:20

判断短信发送成功请以
"+CMGS:" 字符串为准。

至于你说的那个《毛慧琴》论文,我还没有看见过。可否发上来看看。

yaodp 发表于 2011-4-10 11:05:54

【楼主位】 jackjie

SendString("AT+CMGS=", 0);
SendString(tmp, 0);
SendString("\r\n", 0);
GetGsmResponseValue(0, 1, "OK"); //在此处串口收到的有可能是+CMS ERROR而不是>
SendString(SMS_Buffer, 0);
GetGsmResponseValue(1, 10, "OK");
-------------------------------------------------
这里有问题,看看AT+CMGS命令解释
发送完数据长度后发送0x0d,再检测接收‘>'字符,然后再发送信息,再发送0x1A,再检测接收OK,才算完成。
两位你的模块使用流程有问题,看你的流程好像是检测到来电后才设置GSM的SMS命令,然后才发送短信,然后再挂断电话的。
这样做问题很严重。

建议你看看我的开源:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4657079&bbs_page_no=3&bbs_id=9999

jackjie 发表于 2011-4-10 11:10:22

回复【5楼】bangbangji
-----------------------------------------------------------------------

刚刚用串口调试助手试了:还是只返回了OK,我将你的然后试的字符串在串口你也试了

0011000D91685122381706F10008FF325C0A656C76845BA26237FF0C60A876848F668F7D65FA65FA5DF288AB89E653D1FF0C8BF75C3D5FEB524D5F8067E5770BFF01

http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_629693FBRX8P.jpg
(原文件名:3.jpg)

studykaka 发表于 2011-4-10 11:11:17

while ((!bSentSuccessfully) && (++i <= 8))

短信发送并不一定是一次就可以发送成功的,你要学会找AT命令返回值的关键字

jackjie 发表于 2011-4-10 11:15:32

回复【9楼】studykaka
-----------------------------------------------------------------------

谢谢你的回复,你的意思是:并不是每次短信都能成功的发送,若果遇到上面只返回OK的情况,就需要我们自己判断出来,再次重新发送,对吗?

studykaka 发表于 2011-4-10 11:22:44

【楼主位】 jackjie

SendString("AT+CMGS=", 0);
SendString(tmp, 0);
SendString("\r\n", 0);
GetGsmResponseValue(0, 1, "OK"); //在此处串口收到的有可能是+CMS ERROR而不是>
SendString(SMS_Buffer, 0);
GetGsmResponseValue(1, 10, "OK");
-------------------------------------------------
这里有问题,看看AT+CMGS命令解释
发送完数据长度后发送0x0d,再检测接收‘>'字符,然后再发送信息,再发送0x1A,再检测接收OK,才算完成。
两位你的模块使用流程有问题,看你的流程好像是检测到来电后才设置GSM的SMS命令,然后才发送短信,然后再挂断电话的。
这样做问题很严重。

建议你看看我的开源:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4657079&bbs_page_no=3&bbs_id=9999


/////////////////////////////////////////////////////////////////////////////////////////////////////////

呵呵,你只看到是一个表面的茫茫。
SendString("\r\n", 0);
GetGsmResponseValue(0, 1, "OK"); //在此处串口收到的有可能是+CMS ERROR而不是>

以上语句可以这样写
SendString("\r\n", 0);
GetGsmResponseValue(0, 1, ">"); //在此处串口收到的有可能是+CMS ERROR而不是>
也可以这样写:
SendString("\r\n", 0);
GetGsmResponseValue(0, 1, "我要发送短信了"); //在此处串口收到的有可能是+CMS ERROR而不是>

studykaka 发表于 2011-4-10 11:23:39

回复【9楼】studykaka
-----------------------------------------------------------------------

谢谢你的回复,你的意思是:并不是每次短信都能成功的发送,若果遇到上面只返回OK的情况,就需要我们自己判断出来,再次重新发送,对吗?

呵呵,你开悟了

studykaka 发表于 2011-4-10 11:25:04

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//针对短信息部分
smsDispatchMessage(void)
{
}

studykaka 发表于 2011-4-10 11:38:06

在最后发送短信的过程中,“OK”是没有意义的。

最后只有发送成功,失败,及干拢数据。
所以你要学会解述命令。
懂了这一点,GSM之类的东东可以做到通杀。

jackjie 发表于 2011-4-10 12:46:27

回复【14楼】studykaka
-----------------------------------------------------------------------

谢谢你的回复:你的意思我基本已经明白了,就是发送完AT+CMGS = <Len> + <回车后>;判断TC35i的返回值是不是 >,是的话:发送源PDU编码;发送完后,再次检测TC35i有没有返回:+CMGS: <MR> 和 OK (这里主要是检测返回没返回+CMGS:<MR>:若没返回,则继续回到开始从新发送,以确保发送的成功)

还有你说的要毛慧琴的论文,我是nh格式的,上传不了。你要的话留个邮箱。我给你哈

studykaka 发表于 2011-4-10 12:51:05

//>,提示发送SMS数据
        else if (strstr((char*)GSM_V1_Receive.GSM_V1_Responses_Receive_Buffer, ">") != NULL)
        {        //表示对卡操作OK
               
        }

07GPS@163.com
页: [1]
查看完整版本: 关于TC35i短信发送的问题