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

📄 sms.c.bak

📁 这是用W77E58编写的控制GSM模块
💻 BAK
📖 第 1 页 / 共 2 页
字号:
#include <w77e58.h>
#include "global.h"
#include "serial.h"
#include "m32.h"


/************************************************************************************************
*                   int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength) 
* 7-bit编码 
* pSrc: 源字符串指针 
* pDst: 目标编码串指针 
* nSrcLength: 源字符串长度 
* 返回: 目标编码串长度
***************************************************************************************/
int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength) 
{   
      int nSrc;               // 源字符串的计数值     
      int nDst;               // 目标编码串的计数值    
      int nChar;              // 当前正在处理的组内字符字节的序号,范围是0-7   
      unsigned char nLeft;    // 上一字节残余的数据    
#if 0
      // 计数值初始化     
      nSrc = 0;     
      nDst = 0;    
      // 将源串每8个字节分为一组,压缩成7个字节 
      // 循环该处理过程,直至源串被处理完  
      // 如果分组不到8字节,也能正确处理  
      while(nSrc<nSrcLength) 
      {        
         // 取源字符串的计数值的最低3位         
         nChar = nSrc & 7;           
         // 处理源串的每个字节      
         if(nChar == 0)        
         {             
           // 组内第一个字节,只是保存起来,待处理下一个字节时使用             
           nLeft = *pSrc;         
         }  
         else  
         {             
           // 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节             
           *pDst = (*pSrc << (8-nChar))   nLeft;             
           // 将该字节剩下的左边部分,作为残余数据保存起来             
           nLeft = *pSrc >> nChar;       
           // 修改目标串的指针和计数值 
           pDst++;             nDst++;          
         }             
         // 修改源串的指针和计数值         
         pSrc++; nSrc++;  
      }          
#endif     
      // 返回目标串长度     
      return nDst;  
}      


/*****************************************************************************************************
*             int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength) 
*
* 7-bit解码 
* pSrc: 源编码串指针 
* pDst: 目标字符串指针 
* nSrcLength: 源编码串长度 
* 返回: 目标字符串长度 
*******************************************************************************************************/
int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength) 
{ 
     int nSrc;               // 源字符串的计数值     
     int nDst;               // 目标解码串的计数值     
     int nByte;              // 当前正在处理的组内字节的序号,范围是0-6     
     unsigned char nLeft;    // 上一字节残余的数据        
#if 0     
     
     // 计数值初始化     
     nSrc = 0;     nDst = 0;    
     // 组内字节序号和残余数据初始化     
     nByte = 0;     nLeft = 0;    
     // 将源数据每7个字节分为一组,解压缩成8个字节     
     // 循环该处理过程,直至源数据被处理完     
     // 如果分组不到7字节,也能正确处理     
     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;          
     // 返回目标串长度     
#endif     
     return nDst; 
} 

/***********************************************************************************************
     需要指出的是,7-bit的字符集与ANSI标准字符集不完全一致,在0x20以下也排布了一些可打印字符,但英文字母、
 阿拉伯数字和常用符号的位置 两者是一样的。用上面介绍的算法收发纯英文短消息,一般情况应该是够用了。
 如果是法语、德语、西班牙语等,含有 “?”、 “é”这一类字 符,则要按上面编码的输出去查表,请参阅GSM 03.38
 的规定。
***********************************************************************************************/



/************************************************************************************************
UCS2编码是将每个字符(1-2个字节)按照ISO/IEC10646的规定,转变为16位的Unicode宽字符。在Windows系统中,特
别是在2000/XP中,可以简单地调用API 函数实现编码和解码。如果没有系统的支持,比如用单片机控制手机模块收
发短消息,只好用查表法解决了。
Windows 用C实现UCS2编码和解码的算法如下:
*************************************************************************************************/


/*************************************************************************************************
// UCS2编码 
// pSrc: 源字符串指针 
// pDst: 目标编码串指针 
// nSrcLength: 源字符串长度 
// 返回: 目标编码串长度 
**************************************************************************************************/
int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength) 
{  
      	   
	   int nDstLength;        // UNICODE宽字符数目     
	   WCHAR wchar[128];      // UNICODE串缓冲区          
#if 0	
	   // 字符串-->UNICODE串     
	   nDstLength = ::MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);  
	  // 高低字节对调,输出     
	  for(int i=0; i<nDstLength; i++)     
	  {         
	    // 先输出高位字节
	    *pDst++ = wchar[i] >> 8;  
	    // 后输出低位字节         
	    *pDst++ = wchar[i] & 0xff;     
	  }          
#endif	
	  // 返回目标编码串长度     
	  return nDstLength * 2; 
}      


/**************************************************************************************************
// UCS2解码 
// pSrc: 源编码串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源编码串长度 
// 返回: 目标字符串长度 
**************************************************************************************************/
int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength) 
{     
	 int nDstLength;        // UNICODE宽字符数目     
	 WCHAR wchar[128];      // UNICODE串缓冲区          
	 // 高低字节对调,拼成UNICODE     
	 for(int i=0; i<nSrcLength/2; i++)     
	 {         
	     // 先高位字节         
	     wchar[i] = *pSrc++ << 8;              
	     // 后低位字节         
	     wchar[i]  = *pSrc++;     
	 }          
	 // UNICODE串-->字符串     
	 nDstLength = ::WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);          
	 // 输出字符串加个结束符         
	 pDst[nDstLength] = '\0';              
	 // 返回目标字符串长度     
	 return nDstLength; 
} 

/*************************************************************************************************
用以上编码和解码模块,还不能将短消息字符串编码为PDU串需要的格式,也不能直接将PDU串中的用户信息解码为
短消息字符串,因为还差一个在可打印字符串和字节数据之间相互转换的环节。可以循环调用sscanf和sprintf函
数实现这种变换。下面提供不用这些函数的算法,它们也适用于单片机、DSP编程环境。
**************************************************************************************************/
// 可打印字符串转换为字节数据 // 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
 // pSrc: 源字符串指针 
 // pDst: 目标数据指针 
 // nSrcLength: 源字符串长度 
 // 返回: 目标数据长度 
 int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength) 
 {   
 	  for(int 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++;     
 	  }          
 	  // 返回目标数据长度     
 	  returnnSrcLength / 2; 
 }      
 // 字节数据转换为可打印字符串 // 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"  
 // pSrc: 源数据指针 
 // pDst: 目标字符串指针 
 // nSrcLength: 源数据长度 
 // 返回: 目标字符串长度 
 int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength) 
 {     
 	const char tab[]="0123456789ABCDEF";    
 	// 0x0-0xf的字符查找表          
 	for(int i=0; i<nSrcLength; i++)     
 	{         
 		// 输出低4位         
 		*pDst++ = tab[*pSrc >> 4];   
 	        // 输出高4位         
 	        *pDst++ = tab[*pSrc & 0x0f];              
 	        pSrc++;     
 	}          
 	// 输出字符串加个结束符     
 	*pDst = '\0';          
 	// 返回目标字符串长度     
 	return nSrcLength * 2; 
 }
 
/************************************************************************************************
*PDU全串的编码和解码过程,以及GSM 07.05的AT命令实现方法
*************************************************************************************************/
//用户信息编码方式 
#define GSM_7BIT        0 
#define GSM_8BIT        4 
#define GSM_UCS2        8      
// 短消息参数结构,编码/解码共用 
// 其中,字符串以0结尾 
typedef struct 
{     
	char SCA[16];       // 短消息服务中心号码(SMSC地址)     
	char TPA[16];       // 目标号码或回复号码(TP-DA或TP-RA) 
	char TP_PID;        // 用户信息协议标识(TP-PID)     
	char TP_DCS;        // 用户信息编码方式(TP-DCS)     
	char TP_SCTS[16];   // 服务时间戳字符串(TP_SCTS), 接收时用到     
	char TP_UD[161];    // 原始用户信息(编码前或解码后的TP-UD)     
	char index;         // 短消息序号,在读取时用到 
} SM_PARAM; 

/**************************************************************************************************
//PDU串中的号码和时间,都是两两颠倒的字符串。利用下面两个函数可进行正反变换:
// 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补''F''凑成偶数 // 如:"8613851872468" --> "683158812764F8" 
// pSrc: 源字符串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源字符串长度 
// 返回: 目标字符串长度 
****************************************************************************************************/
int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength) 
{     
	int nDstLength;   // 目标字符串长度     
	char ch;          // 用于保存一个字符          
	// 复制串长度     
	nDstLength = nSrcLength;          
	// 两两颠倒     
	for(int 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; 
}      
        
// 两两颠倒的字符串转换为正常顺序的字符串 // 如:"683158812764F8" --> "8613851872468" 
// pSrc: 源字符串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源字符串长度 
// 返回: 目标字符串长度 
int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength) 
{     
	int nDstLength;   // 目标字符串长度     
	char ch;          // 用于保存一个字符      
        // 复制串长度     nDstLength = nSrcLength;          
        // 两两颠倒     
        for(int i=0; i<nSrcLength;i+=2)     
        { 
                ch = *pSrc++;        
                // 保存先出现的字符         
                *pDst++ = *pSrc++;   // 复制后出现的字符         
                *pDst++ = ch;        // 复制先出现的字符     
        }          
       
        // 最后的字符是''F''吗?     
        if(*(pDst-1) == ''F'')     
        {         
        	pDst--;         
        	nDstLength--;        // 目标字符串长度减1     
        }          
        // 输出字符串加个结束符     
        *pDst = ''\0'';          
        // 返回目标字符串长度     
        return nDstLength; 
} 
        

//以下是PDU全串的编解码模块。为简化编程,有些字段用了固定值。

// PDU编码,用于编制、发送短消息 

⌨️ 快捷键说明

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