我是土匪 发表于 2015-12-2 11:42

boolIRAConvertGsm7Bit(const u8 *iraData, u16 iraLen, u8 *gsmData, u16 *gsmLen, bool dropInconvertible)
{
    bool result = TRUE;
    u8 gsmValue = 0;
    u16 i = 0;

    *gsmLen = 0;
    for (i = 0; i < iraLen; i++)
    {
      gsmValue = ira_to_gsm7[*iraData];
      if (gsmValue != INVALID_CHAR)
      {
            *gsmData++ = gsmValue;
            (*gsmLen)++;
      }
      else if ((gsmValue = ira_to_ext_gsm7[*iraData]) != INVALID_CHAR)
      {
            *gsmData++ = 0x1B;
            *gsmData++ = gsmValue;
            *gsmLen += 2;
      }
      else if (!dropInconvertible)
      {
            result = FALSE;
            break;
      }
      else
      {
            /* Replace inconvertible char with a space */
            *gsmData++ = REPLACEMENT_CHAR;
            (*gsmLen)++;
      }
      iraData++;
    }

    return result;
}

s32 gsmInvertNumbers(const char* pSrc, char* pDst, s32 nSrcLength)
{
        s32 nDstLength;
        u8 ch;
    s32 i;
       
        nDstLength = nSrcLength;
       
        for(i=0; i<nSrcLength;i+=2)
        {
                ch = *pSrc++;   
                *pDst++ = *pSrc++;
                *pDst++ = ch;
        }
       
        if(nSrcLength & 1)
        {
                *(pDst-2) = 'F';
                nDstLength++;
        }
       
        *pDst = '\0';

        return nDstLength;
}

s32 gsmSerializeNumbers(const char* pSrc, char* pDst, s32 nSrcLength)
{
        s32 nDstLength;
    s32 i = 0;
        u8 ch;   
       
        nDstLength = nSrcLength;
       
        for(i=0; i<nSrcLength;i+=2)
        {
                ch = *pSrc++;   
                *pDst++ = *pSrc++;
                *pDst++ = ch;   
        }
       
        if(*(pDst-1) == 'F')
        {
                pDst--;
                nDstLength--;   
        }
       
        *pDst = '\0';
       
        return nDstLength;
}

s32 gsmBytes2String(const u8 *pSrc, char*pDst, s32 nSrcLength)
{
        const u8 tab[]="0123456789ABCDEF";
    s32 i = 0;
       
        for (i=0; i < nSrcLength; i++)
        {
                *pDst++ = tab[*pSrc >> 4];
                *pDst++ = tab[*pSrc & 0x0f];
               
                pSrc++;
        }
       
        *pDst = '\0';
       
        return nSrcLength * 2;
}

s32 gsmString2Bytes(const char* pSrc, u8* pDst, s32 nSrcLength)
{
    s32 i = 0;
   
        for (i=0; i<nSrcLength; i+=2)
        {
                if(*pSrc>='0' && *pSrc<='9')
                {
                        *pDst = (*pSrc - '0') << 4;
                }
                else
                {
                        *pDst = (*pSrc - 'A' + 10) << 4;
                }
               
                pSrc++;
               
                if(*pSrc>='0' && *pSrc<='9')
                {
                        *pDst |= *pSrc - '0';
                }
                else
                {
                        *pDst |= *pSrc - 'A' + 10;
                }
                pSrc++;
                pDst++;
        }
       
        return nSrcLength / 2;
}

s32 gsmEncode8bit(const char* pSrc,u8 *pDst, s32 nSrcLength)
{
    s32 i = 0;
   
        for(i=0; i<nSrcLength; i++)
        {
                *pDst++ = *pSrc++;
        }
       
        return nSrcLength;
}

s32 gsmDecode7bit(const u8* pSrc, char *pDst, s32 nSrcLength)
{
        s32 nSrc;   
        s32 nDst;   
        s32 nByte;   
        u8 nLeft;
       
        nSrc = 0;
        nDst = 0;
       
        nByte = 0;
        nLeft = 0;
       
        while(nSrc<nSrcLength)
        {
                *pDst = ((*pSrc << nByte) | nLeft) & 0x7f;
                nLeft = *pSrc >> (7-nByte);
               
          pDst++;
          nDst++;
               
                nByte++;
               
                if(nByte == 7)
                {
                        *pDst = nLeft;
                       

                     pDst++;
                       nDst++;
                       
                       nByte = 0;
                       nLeft = 0;
                }
               
                pSrc++;
                nSrc++;
        }
       
        *pDst = 0;
       
        return nDst;
}

s32 gsmEncode7bit(const char* pSrc, u8* pDst, s32 nSrcLength)
{
        s32 nSrc;   
        s32 nDst;   
        s32 nChar;   
        u8nLeft = 0;
        u8cSrc;
       
        nSrc = 0;
        nDst = 0;
       
        while(nSrc<nSrcLength)
        {
                nChar = nSrc & 7;
                cSrc = *pSrc;
                if(nChar == 0)
                {
                        nLeft = cSrc;
                }
                else
                {
                        *pDst++ = (cSrc << (8-nChar)) | nLeft;
                       
                        nLeft = cSrc >> nChar;
                        nDst++;
                }
               
                pSrc++; nSrc++;
        }
       
        return nDst;
}

s32 gsmDecode8bit(const u8* pSrc, char * pDst, s32 nSrcLength)
{
    s32 i = 0;
   
        for(i=0; i<nSrcLength; i++)
        {
                *pDst++ = *pSrc++;
        }
       
        return nSrcLength;
}

u8 gsmDecodeSmsValidity(const u8 *data,SmsValidityFormatType validityFormat)
{
    u8 pos = 0;

    if (data == NULL )
    {
       return 0;
    }
    else
    {
      switch(validityFormat)
      {
         case SMS_VALIDITY_NONE:
         break;

         case SMS_VALIDITY_RELATIVE:
         pos ++;
         break;

         case SMS_VALIDITY_ABSOLUTE:
         pos += 7;
         break;

         case SMS_VALIDITY_ENHANCED:
         break;
       }
    }
   
    return pos*2;
}

u8 SmsDecodeDcs(const u8*data, SmsDcsType*dcs)
{
    u8 pos = 0;
    u8 i;

   if (data == NULL || dcs == NULL)
   {
         return 0;
   }

   dcs->msgClass          = SMS_MSG_CLASS_NONE;
   dcs->msgWaiting    =   SMS_MSG_WAITING_NONE;
   dcs->alphabet       = SMS_ALPHABET_7_BIT_DEFAULT;
   dcs->isCompressed= FALSE;


   /* bits 7-6 */
   i = ( data & 0xC0 ) >> 6;
   switch( i )
   {
         case 0:
          /* pattern 00xx xxxx */
         dcs->isCompressed = data & 0x20;
         if( data & 0x10 )
         {
            dcs->msgClass = (SmsMsgClassType) (data & 0x03);
         }
         else
         {
         /* no class information */
         dcs->msgClass = SMS_MSG_CLASS_NONE;
      }
      dcs->alphabet = (SmsAlphabetType) (( data & 0x0C ) >> 2);
      break;

      case 3:
      /* bits 5-4 */
      if( (data & 0x30) == 0x30 )
      {
         /* pattern 1111 xxxx */

          /* bit 3 is reserved */

          /* bit 2 */
          dcs->alphabet = (data & 0x04 ) ? SMS_ALPHABET_8_BIT:
                                       SMS_ALPHABET_7_BIT_DEFAULT;

          /* bits 1-0 */
          dcs->msgClass = (SmsMsgClassType) (data & 0x03);

          /* set remaining fields */
          dcs->isCompressed= FALSE;
          dcs->msgWaiting    = SMS_MSG_WAITING_NONE_1111;
       }
       else
       {
         /* Message waiting groups
         */
          dcs->isCompressed= FALSE;
          dcs->msgClass          = SMS_MSG_CLASS_NONE;

          /* bits 5-4 */
          if( (data & 0x30) == 0x00 )
          {
             dcs->msgWaiting= SMS_MSG_WAITING_DISCARD;
             dcs->alphabet   = SMS_ALPHABET_7_BIT_DEFAULT;
          }
          else if( (data & 0x30) == 0x10 )
          {
             dcs->msgWaiting= SMS_MSG_WAITING_STORE;
             dcs->alphabet   = SMS_ALPHABET_7_BIT_DEFAULT;
          }
          else
          {
             dcs->msgWaiting= SMS_MSG_WAITING_STORE;
             dcs->alphabet   = SMS_ALPHABET_UCS2;
          }

          /* bit 3 */
          dcs->msgWaitingActive = ( data & 0x08 ) ? TRUE : FALSE;

          /* bit 2 is reserved */

          /* bits 1-0 */
         dcs->msgWaitingKind = (SmsMsgWaitingKindType) (data & 0x03);
      }
      break;

      default:
      dcs->alphabet       = SMS_ALPHABET_7_BIT_DEFAULT;
      dcs->isCompressed= FALSE;
      dcs->msgWaiting    = SMS_MSG_WAITING_NONE;
      dcs->msgClass          = SMS_MSG_CLASS_NONE;
      break;
    }

    if ( dcs->alphabet > SMS_ALPHABET_UCS2 )
    {
       dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
    }

    dcs->rawDcsData = data;

    pos ++;

    return pos;
}

boolgsmEncodePdu( SM_PARAM* pSrc, char* pDst, u16 *dstLen)
{
#define MAX_GSM7BIT_SMS_LEN   160
    s32nDstLength = 0;   
        u8buf = { 0 };
    bool result = TRUE;
        s32 nLength;      

        /* SMSC address field */
        nLength = strlen(pSrc->SCA);

        if( nLength )
    {
                buf = (s8)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1;
                buf = 0x81;   
                nDstLength = gsmBytes2String(buf, pDst, 2);   
                nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst, nLength);
        }
        else
    {
                pDst='0';
                pDst='0';
        }
       
        nLength = strlen(pSrc->TPA);
        buf = 0x11;      
        buf = 0;      

        if( '+' == pSrc->TPA )
    {
                memmove( pSrc->TPA, pSrc->TPA+1, nLength );
                nLength -= 1;
                buf = 0x91;   
        }
        else
    {
                buf = 0x81;
        }

        buf = (s8)nLength;
        nDstLength += gsmBytes2String(buf, &pDst, 4);
        nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst, nLength);
       
        nLength = strlen(pSrc->TP_UD);
        buf = pSrc->TP_PID;   
        buf = pSrc->TP_DCS;   

/*
        VP Value Validity period value
        0-143 (VP + 1) x 5 minutes (i.e 5 minutes intervals up to 12 hours)
        144-167 12 hours + ((VP-143) x 30 minutes)
        168-196 (VP-166) x 1 day
        197-255 (VP - 192) x 1 week
*/
        buf = g_sms_vp;   /* 4 days */

        if(pSrc->TP_DCS == GSM_7BIT)
        {
                chartmpGsm;
      s32 nSrcLength;

      nSrcLength = strlen((char *)pSrc->TP_UD);
      IRAConvertGsm7Bit((const u8 *)(pSrc->TP_UD), nSrcLength, (u8 *)tmpGsm, (u16 *)&nLength,TRUE);
                buf = nLength;   
                nLength = gsmEncode7bit(tmpGsm, &buf, nLength+1) + 4;
        }
        else if (pSrc->TP_DCS == GSM_8BIT)
        {
                buf = gsmEncode8bit(pSrc->TP_UD, &buf, nLength);
                nLength = buf + 4;   
        }
    else if (pSrc->TP_DCS == GSM_UCS2)
    {
      *dstLen = 0;
      return FALSE;
    }
      
        nDstLength += gsmBytes2String(buf, &pDst, nLength);
    *dstLen = nDstLength;
       
        return result;
}

bool gsmDecodePdu(const char* pSrc, SM_PARAM* pDst, u16 *dstLen)
{
    SmsValidityFormatType validityFormat;
    SmsDcsTypedcs;
    bool result = TRUE;
        u16 nDstLength;
        u8tmp;   
        u8 buf;
        u8 TP;

    *dstLen = 0;
        memset( pDst, 0, sizeof(SM_PARAM) );

        gsmString2Bytes(pSrc, &tmp, 2);
        if (tmp)
        {
                tmp = (tmp - 1) * 2;
                pSrc += 4;      
                gsmSerializeNumbers(pSrc, pDst->SCA, tmp);
                pSrc += tmp;
        }
        else
        {
                pSrc += 2;
        }
       
        gsmString2Bytes(pSrc, &TP, 2);
        pSrc += 2;

        validityFormat = (SmsValidityFormatType) (( TP & 0x18 ) >> 3); /* bits 3, 4 */

        if( TP & 0x1 )
    {
                pSrc += 2;   
        }

    /* the long sms.Discard it */
    if (TP & 0x40)
    {
      return FALSE;
    }

    /* the status reprt.Discard it */
    if (( TP & 0x3 ) == 0x2)
    {
      return FALSE;
        }
   
    gsmString2Bytes(pSrc, &tmp, 2);
    if(tmp & 1)
    {
      tmp += 1;
    }
    pSrc += 2;      

    gsmString2Bytes(pSrc, &pDst->TPATP, 2);
    pSrc += 2;

        if( 0x91 == pDst->TPATP )
    {
      pDst->TPA = '+';
                gsmSerializeNumbers(pSrc, pDst->TPA+1, tmp);
        }
        else if( 0xD0 == pDst->TPATP)
    {
             nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4);
               nDstLength = tmp *4 /7;
             gsmDecode7bit(buf, pDst->TPA, nDstLength);
    }
    else
    {
          gsmSerializeNumbers(pSrc, pDst->TPA, tmp);
    }
        pSrc += tmp;   

        gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2);
        pSrc += 2;   
        gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2);

        SmsDecodeDcs( (unsigned char*)&pDst->TP_DCS, &dcs );
        pSrc += 2;   


        if( TP & 0x1 )
    {
                pSrc += gsmDecodeSmsValidity( (u8 *)pSrc, validityFormat);
        }
        else
    {
                gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);   
                pSrc += 14;
        }

        gsmString2Bytes(pSrc, &tmp, 2);
        pSrc += 2;

        if (dcs.alphabet == SMS_ALPHABET_7_BIT_DEFAULT)
        {
                char tmpGsm = { 0 };
      u16 gsmLen = 0;

          nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (s32)tmp * 7 / 4 + 2 : (s32)tmp * 7 / 4);
          gsmDecode7bit(buf, tmpGsm, nDstLength);
                tmpGsm = '\0';
   
      gsmLen = strlen(tmpGsm);
      gsm7BitConvertIRA((const u8 *)tmpGsm, gsmLen, (u8 *)pDst->TP_UD, &nDstLength, TRUE);
                pDst->TP_UD = '\0';
        }
    else if (dcs.alphabet == SMS_ALPHABET_8_BIT)
    {
      nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);
          nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength);
      *dstLen = nDstLength;
    }
        else if(dcs.alphabet == SMS_ALPHABET_UCS2)
        {
      result = FALSE;
        }
       
        return result;
}

我是土匪 发表于 2015-12-10 17:13

本帖最后由 我是土匪 于 2015-12-10 17:14 编辑

TCPIP学习
TCPIP目前使用非常广泛,参照官方的《AN_SIM900_TCPIP_V1.01.pdf》实现。
本人在DTU项目中,采用TCPIP方式,可以稳定的实现数据的链接和传输。
下面介绍TCPIP流程。

我是土匪 发表于 2015-12-10 17:42

本帖最后由 我是土匪 于 2015-12-10 18:00 编辑

下面罗列出几种常用的URC的返回值(URC不局限于此)。代码上处理如下:void Deal_URCStrHandle(char*urcstr){   char *p = (char *) urcstr;   s16urcType = -1;   u8    i= 0;static char count_pdp = 0;         char *UrcTable[ ] = {                                       "CONNECT OK",                                       "ALREADY CONNECT",                                        "CONNECT FAIL",                                       "CLOSED",                                       "+PDP: DEACT", //PDP DEACT                                       "+CIPRXGET:1",                                       "OK",                                       "+CPIN:NOT READY"                                     };
    while ('\r' == *p || '\n'== *p)    {       p++;    }
   for (i = 0; i < sizeof(UrcTable) /sizeof(UrcTable); i++)    {      if (strstr(p, UrcTable))      {         urcType = i;         break;      }    }
   switch (urcType)    {       case 0:/* CONNECT OK */       {         tcpConnConnect = TRUE;         tcpRetryNum = 0;         InitParams( );
//停止数据发送相关的动作            TimerStop(REMOTE_SEND_DATA_TIMER_ID);         TimerStop(REMOTE_SEND_DATA_DELAY_TIMER_ID);         TimerStop(RECV_REMOTE_DATA_TIMER_ID);
         SendDataToSerial((char *)"CONNECT SERVER OK\r\n",strlen((constchar *)"CONNECT SERVER OK\r\n"));
       }       break;       case 1:/* ALREADY CONNECT */       {         ;       }             break;       case 2: /* CONNECT FAIL */       {          //关闭移动场景       }       break;       case 3:       {               SendDataToSerial((char*)"\r\nCONNECT SERVER FAIL\r\n",strlen((const char*)"\r\nCONNECT SERVER FAIL\r\n")); //modified by ds for connectstatus's URC      
                TimerStop(REMOTE_SEND_DATA_TIMER_ID);                TimerStop(REMOTE_SEND_DATA_DELAY_TIMER_ID);               TimerStop(RECV_REMOTE_DATA_TIMER_ID);            //关闭移动场景
       }       break;       case 4: /* +PDP: DEACT */       {
SendDataToSerial((char*)"\r\nCONNECT SERVER FAIL\r\n",strlen((const char*)"\r\nCONNECT SERVER FAIL\r\n")); //modified by ds for connectstatus's URC      
       tcpConnConnect= FALSE;
          //重启模块      }
       break;       case 5:    /* +CIPRXGET: 1 */       {         char *pStr = NULL;
         pStr = strstr(p, UrcTable);
            TimerStart(RECV_REMOTE_DATA_TIMER_ID);//启动读数据
       }      break;

            case7:    //+CPIN: NOT READY       {            simCardStatusOk= FALSE;
                //掉卡,重启模块      
       }       break;       default:       break;    }

}

我是土匪 发表于 2015-12-10 17:59

上电会检查是否注册商网络,成功后就会发起连接服务器操作,连接成功后靠心跳维持靠心跳维持长连接。
如果中途出现发送失败会重新发送,超过一定次数仍旧失败,需要断开连接,重连服务器,
通常网络变化,以及连接失败等会有URC上报。根据URC针对性的处理,重连即可。

windows100 发表于 2015-12-11 08:53

mark

cliffboy 发表于 2015-12-11 09:44

我是土匪 发表于 2015-8-24 18:00
6、如何主动控制重启?
      复位引脚。听说SIM900该引脚不足够可靠。
      AT命令:AT+CFUN=1,1 ...

串口倒灌引起的有电,弱弱问句软件方面是怎么处理的?

我是土匪 发表于 2015-12-11 10:55

cliffboy 发表于 2015-12-11 09:44
串口倒灌引起的有电,弱弱问句软件方面是怎么处理的?

这种情况指的是,单片机跑起来了,但是GPRS没有上电,但是电流通过MCU的串口串电给GPRS,导致一定概率的GPRS开机失败。
解决办法:
GPRS没上电的时候,单片机串口配置输出0电平,这样就不会串电。当GPRS供电后,再将串口引脚配置为串口模式。

cliffboy 发表于 2015-12-11 13:29

我是土匪 发表于 2015-12-11 10:55
这种情况指的是,单片机跑起来了,但是GPRS没有上电,但是电流通过MCU的串口串电给GPRS,导致一定概率的GPR ...

这个在单片机启动过程中无法保证,还是有一定风险,最好还是硬件上来处理

我是土匪 发表于 2015-12-11 13:48

本帖最后由 我是土匪 于 2015-12-11 14:13 编辑

cliffboy 发表于 2015-12-11 13:29
这个在单片机启动过程中无法保证,还是有一定风险,最好还是硬件上来处理 ...
逻辑上完全能处理,
保证模块上电前没有被串电即可。

当然硬件处理更好,否则软件代码可读性就会差一点。

sun1238898 发表于 2015-12-11 17:33

收藏一下,后续慢慢品味。。。

cliffboy 发表于 2015-12-11 17:34

我是土匪 发表于 2015-12-11 13:48
逻辑上完全能处理,
保证模块上电前没有被串电即可。



单板机启动过程中在逻辑上是无法来控制的,因为此过程串口是不受控的

我是土匪 发表于 2015-12-11 17:42

cliffboy 发表于 2015-12-11 17:34
单板机启动过程中在逻辑上是无法来控制的,因为此过程串口是不受控的

不是说设备上电的过程。
设备上电-》串口配置为GPIO输出0-》GPRS上电-》GPRS开机-》单片机串口引脚配置为串口模式

只要我开机之前模块是断电的就好。
这个教训血淋淋,十万RMB的代价。

cliffboy 发表于 2015-12-14 15:33

我是土匪 发表于 2015-12-11 17:42
不是说设备上电的过程。
设备上电-》串口配置为GPIO输出0-》GPRS上电-》GPRS开机-》单片机串口引脚配置为 ...

你这是设备起来稳定后正常的流程,当然没有问题,我是说设备在上电启动稳定前的这一个过程中,你这流程是根本无法实现的,只能通过硬件电路实现

我是土匪 发表于 2015-12-14 15:54

cliffboy 发表于 2015-12-14 15:33
你这是设备起来稳定后正常的流程,当然没有问题,我是说设备在上电启动稳定前的这一个过程中,你这流程是 ...

其实上电过程,不关心串电等状态的。
我这里描述的串电指的是,GPRS模块电源被MOS切断的状态下,测量GPRS的vbat,电压不是0而为1.8V左右(单片机串口初始化后引脚为高电平),基于这个状态,模块供电,再拉powerkey会出现千分之几概率的无法开机。

当然硬件解决是最理想的,软件只是后来弥补的办法。

zuoxuqi 发表于 2015-12-21 22:46

楼主能否分享一下第三章AT架构部分的完整工程代码,基础太差,有些地方实在搞不定

cliffboy 发表于 2015-12-25 17:29

我是土匪 发表于 2015-9-24 14:18
n      架构二:中断方式

个人喜欢用的方式。

这块能不详细讲一下架构,定时中断与接收中断时如何配合来工作的?

我是土匪 发表于 2015-12-30 14:43

zuoxuqi 发表于 2015-12-21 22:46
楼主能否分享一下第三章AT架构部分的完整工程代码,基础太差,有些地方实在搞不定 ...

思路交流可以,思想交流欢迎,整个完整代码,只能说抱歉了,望理解。

我是土匪 发表于 2015-12-30 14:44

cliffboy 发表于 2015-12-25 17:29
这块能不详细讲一下架构,定时中断与接收中断时如何配合来工作的?

接收中断,实际就是字符串中断,设置成超时中断是很不错的办法。

定时中断和超时中断是没有冲突的。

我是土匪 发表于 2016-1-7 14:48

因为项目需求,要画个最小系统板。
最近SIM900A停产了,所以计划做一块兼容的板子,SIM900A&SIM800A&SIM2000C.

今天评估了资料,马上动手,及时分享。

wrr360661326 发表于 2016-1-11 11:20

刚开始接触GPRS,买了模块使用串口测试了一下,TCPIP短信功能都用到了,后面用单片机去做。感觉好大的工作量。解析、发送好复杂的赶脚
页: 1 2 3 4 5 6 [7] 8 9
查看完整版本: 【原创连载】+和土匪一起玩GPRS模块