⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdu.c

📁 本实例实现GSM模块的发送短消息
💻 C
字号:
#include "define.h"
#include "USC2GB.h"
#include "pdu.h"

//===================================================
TYP_SM_PARAM msg;
unsigned char textLength;
unsigned char asciiLength;

//编解码方式
#define GSM_7BIT        0
#define GSM_8BIT        4
#define GSM_UCS2        8

//====================================================
void gsmString2Bytes(unsigned char* pSrc, unsigned char* pDst,unsigned int nSrcLength);
void gsmSerializeNumbers(char* pSrc, char* pDst, unsigned char nSrcLength);
void USC2GB(unsigned char* p);    //源和目标都是p,已0x00为结束符。
unsigned int folio_search(unsigned int x); //折半搜索,返回x的位置,失败返回0xFFFF
void Convert2USCII( unsigned char *pSrc, unsigned int *pDst );

//====================================================
// PDU解码,用于接收、阅读短消息
// pSrc: 源PDU串指针
// pDst: 目标PDU参数指针
// 返回: 最后指针的指向
char* gsmDecodePdu(char* pSrc){
    unsigned char tmp;
    
    // SMSC地址信息段
    gsmString2Bytes(pSrc, &tmp, 2); // 取长度
    pSrc += (2 + (unsigned char)(tmp<<1));                // 指针后移,跳过SMSC号码长度
    // TPDU段基本参数、回复地址等
    gsmString2Bytes(pSrc, &tmp, 2);    // 取基本参数
    pSrc += 2;        // 指针后移
    if(tmp & 0x04)   //基本参数(TP-MTI/MMS/RP)有问题。24也有以下3个段
    {
        // 包含回复地址,取回复地址信息
        gsmString2Bytes(pSrc, &tmp, 2);    // 取长度  
        if(tmp & 1) tmp += 1;    // 调整奇偶性
        pSrc += 4;          // 指针后移
        gsmSerializeNumbers(pSrc, msg.TPA, tmp);// 取TP-RA号码,
        pSrc += tmp;
    }
    // TPDU段协议标识、编码方式、用户信息等
    gsmString2Bytes(pSrc, (unsigned char*)&msg.TP_PID, 2);    // 取协议标识(TP-PID)
    pSrc += 2;        // 指针后移
    gsmString2Bytes(pSrc, (unsigned char*)&msg.TP_DCS, 2);    // 取编码方式(TP-DCS)
    pSrc += 16;       // 指针后移
    gsmString2Bytes(pSrc, &tmp, 2);    // 用户信息长度(TP-UDL)
    pSrc += 2;        // 指针后移
    if (tmp > 142)
    {
      return 0;
    }
    if(msg.TP_DCS == GSM_UCS2)
    {  
        // UCS2解码
        gsmString2Bytes(pSrc, msg.RE_TP_UD, (unsigned int)tmp<<1);        //转成二进制
        *(msg.RE_TP_UD+tmp) = '\0';     //0x0000为结束符
        *(msg.RE_TP_UD+tmp+1) = '\0';
        *(msg.RE_TP_UD+tmp+2) = '\0';
        Convert2USCII( msg.RE_TP_UD, read_data );
        USC2GB(msg.RE_TP_UD);              // 转换到GB2312编码
        pSrc += tmp;
        pSrc += tmp;
    }
    //else if(msg->TP_DCS == GSM_7BIT); // 7-bit解码
    //else if(msg->TP_DCS == GSM_8BIT); // 8-bit解码
    else pSrc = 0;   //error
    return pSrc;
}

// 两两颠倒的字符串转换为正常顺序的字符串
// 如:"683158812764F8" --> "8613851872468"
// pSrc: 源字符串指针
// pDst: 目标字符串指针
// nSrcLength: 源字符串长度
void gsmSerializeNumbers(char* pSrc, char* pDst, unsigned char nSrcLength){
    unsigned char i;   // 目标字符串长度
    char ch;          // 用于保存一个字符

    // 两两颠倒
    for(i=0; i<nSrcLength;i+=2)
    {
        ch = *pSrc++;        // 保存先出现的字符
        *pDst++ = *pSrc++;   // 复制后出现的字符
        *pDst++ = ch;        // 复制先出现的字符
    }
    
    // 最后的字符是'F'吗?
    if(*(pDst-1) == 'F')
        pDst--;

    *pDst = '\0';  // 输出字符串加个结束符
}

// 可打印字符串转换为字节数据
// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// pSrc: 源字符串指针
// pDst: 目标数据指针
// nSrcLength: 源字符串长度
void gsmString2Bytes(unsigned char* pSrc, unsigned char* pDst,unsigned int nSrcLength){
int i;
    for(i=0; i<nSrcLength; i+=2)
    {
        // 输出高4位
        if(*pSrc>='0' && *pSrc<='9')
            *pDst = (*pSrc - '0') << 4;
        else
            *pDst = (*pSrc - 'A' + 10) << 4;
        pSrc++;
        // 输出低4位
        if(*pSrc>='0' && *pSrc<='9')
            *pDst |= *pSrc - '0';
        else
            *pDst |= *pSrc - 'A' + 10;
        pSrc++;
        pDst++;
    }
}

void USC2GB(unsigned char* p){
unsigned int temp=1,position;

textLength = 0;
asciiLength = 0;
while (temp)
{
   temp=((unsigned int)*p<<8);  //转成int型
   temp+=*(p+1);
   if (temp>=0x0080)   //非ASCII码要转换
   {
      position=folio_search(temp);   //折半搜索
      if (position<7445) temp=GB2312[position]; //转成GB2312
      else temp=0xA3BF;          //无法识别显示问号
   }
   else
   {
     asciiLength++;
   }
   textLength++;
   *p++ = temp & 0xFF;                    //高低位对调,使*p直接可以int型调用
   *p++ = temp >> 8;
}
asciiLength--;
textLength--;
}

unsigned int folio_search(unsigned int x){
unsigned int high=7444,low=0,mid;
while (low<=high)
{
   mid=(low+high)>>1;
   if (unicode[mid]<x) low=mid+1; //右缩搜索
   else if (unicode[mid]>x) high=mid-1;//左缩搜索
   else return mid;
}
return 0xFFFF;
}

void Convert2USCII( unsigned char *pSrc, unsigned int *pDst )
{
  unsigned int temp = 1;
  unsigned char i;
  //增加朗读开始信息和手机号码.
  //收到13XXXXXXXXX的消息:
  *pDst++ = 25910;//收
  *pDst++ = 21040;//到
  if ((msg.TPA[0]=='8') && (msg.TPA[1]=='6')) i=2;//国际码86不念出来
  else i=0;
  for (; (i<16) && (msg.TPA[i]!='\0'); i++)  
  {
    *pDst++ = msg.TPA[i];
  }
  *pDst++ = 30340;//的
  *pDst++ = 28040;//消
  *pDst++ = 24687;//息
  *pDst++ = 65306;//:
  
  while (temp)
  {
    temp = (unsigned int)(*pSrc++) << 8;
    temp += *pSrc++;
    *pDst++ = temp;
  }
  *(pDst - 1) = 0x1A;    //朗读结束标记 
  *pDst = 0x00;  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -