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

📄 sms.c

📁 这是用W77E58编写的控制GSM模块
💻 C
📖 第 1 页 / 共 3 页
字号:
短消息字符串,因为还差一个在可打印字符串和字节数据之间相互转换的环节。可以循环调用sscanf和sprintf函
数实现这种变换。下面提供不用这些函数的算法,它们也适用于单片机、DSP编程环境。
**************************************************************************************************/
// 可打印字符串转换为字节数据 // 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
 // pSrc: 源字符串指针 
 // pDst: 目标数据指针 
 // nSrcLength: 源字符串长度 
 // 返回: 目标数据长度 
 //int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength) 
 int gsmString2Bytes(uchar xdata * pSrc, uchar xdata * pDst, int xdata nSrcLength) 
 {   
 	  int xdata 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++;     
 	  }          
 	  // 返回目标数据长度     
 	  return nSrcLength / 2; 
 }      
 
 
 // 字节数据转换为可打印字符串 // 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"  
 // pSrc: 源数据指针 
 // pDst: 目标字符串指针 
 // nSrcLength: 源数据长度 
 // 返回: 目标字符串长度 
 //int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength) 
 int gsmBytes2String(uchar xdata * pSrc, char xdata* pDst, int xdata nSrcLength) 
 {     
 	//const char tab[]="0123456789ABCDEF";    
 	code char tab[]="0123456789ABCDEF";    
 	
	int xdata i;
	// 0x0-0xf的字符查找表          
 	for(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命令实现方法
*************************************************************************************************/



/**************************************************************************************************
//PDU串中的号码和时间,都是两两颠倒的字符串。利用下面两个函数可进行正反变换:
// 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补''F''凑成偶数 // 如:"8613851872468" --> "683158812764F8" 
// pSrc: 源字符串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源字符串长度 
// 返回: 目标字符串长度 
****************************************************************************************************/
//int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength) 
int gsmInvertNumbers(char xdata* pSrc, char xdata* pDst, int xdata nSrcLength) 
{     


    int xdata nDstLength;   // 目标字符串长度     
	char xdata ch;          // 用于保存一个字符          
	int xdata i;
	// 复制串长度     
	nDstLength = nSrcLength;          
	// 两两颠倒     
	for(i=0; i<nSrcLength;i+=2)     
	{         
	    ch = *pSrc++;        // 保存先出现的字符         
	    *pDst++ = *pSrc++;   // 复制后出现的字符         
	    *pDst++ = ch;        // 复制先出现的字符     
    }          
    // 源串长度是奇数吗?     
    if(nSrcLength & 1)     
    {         
            //*(pDst-2) = ''F'';     // 补''F'' 
            *(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 gsmSerializeNumbers(char xdata* pSrc, char xdata* pDst, int xdata nSrcLength) 
{     
	    int xdata nDstLength;   // 目标字符串长度     
	    char xdata ch;          // 用于保存一个字符      
        int xdata i;
		// 复制串长度     nDstLength = nSrcLength;          
        // 两两颠倒     
        for(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编码,用于编制、发送短消息 
// pSrc: 源PDU参数指针 
// pDst: 目标PDU串指针 
// 返回: 目标PDU串长度 

int gsmEncodePdu(const SM_PARAM* pSrc, char xdata* pDst) 
{     
	int xdata nLength;             // 内部用的串长度     
	int xdata nDstLength;          // 目标PDU串长度     
	unsigned char xdata buf[256];  // 内部用的缓冲区          

	
	// SMSC地址信息段     
	nLength = strlen(pSrc->SCA);    // SMSC地址字符串的长度         
	buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1;  // SMSC地址信息长度     
	buf[1] = 0x91;        // 固定: 用国际格式号码     
	nDstLength = gsmBytes2String(buf, pDst, 2);        // 转换2个字节到目标PDU串     
	nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength);    // 转换SMSC到目标PDU串          
	
	// TPDU段基本参数、目标地址等     
	nLength = strlen(pSrc->TPA);    // TP-DA地址字符串的长度     
	buf[0] = 0x11;                 // 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10)     
	buf[1] = 0;                    // TP-MR=0     
	buf[2] = (char)nLength;        // 目标地址数字个数(TP-DA地址字符串真实长度)     
	buf[3] = 0x91;                 // 固定: 用国际格式号码     
	nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4);  // 转换4个字节到目标PDU串     
	nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 转换TP-DA到目标PDU串          
	
	// TPDU段协议标识、编码方式、用户信息等     
	nLength = strlen(pSrc->TP_UD);    // 用户信息字符串的长度     
	buf[0] = pSrc->TP_PID;            // 协议标识(TP-PID)     
	buf[1] = pSrc->TP_DCS;            // 用户信息编码方式(TP-DCS)     
	buf[2] = 0;                       // 有效期(TP-VP)为5分钟     
	if(pSrc->TP_DCS == GSM_7BIT)         
	{         
		// 7-bit编码方式         
		buf[3] = nLength;                                                // 编码前长度         
		nLength = gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4;    // 转换TP-DA到目标PDU串     
	}     
	else 
	if(pSrc->TP_DCS == GSM_UCS2)     
	{         
	   #if 0
	   // UCS2编码方式         
		buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength);    // 转换TP-DA到目标PDU串         
		nLength = buf[3] + 4;        // nLength等于该段数据长度     
	   #endif
	}     
	else     
	{         
		// 8-bit编码方式         
		buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength);    
		// 转换TP-DA到目标PDU串         
		nLength = buf[3] + 4;        
		// nLength等于该段数据长度     
	}     
	nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength); // 转换该段数据到目标PDU串          
	
	// 返回目标字符串长度     
	return nDstLength; 
}      
 
 

 // PDU解码,用于接收、阅读短消息 
 // pSrc: 源PDU串指针 
 // pDst: 目标PDU参数指针 
 // 返回: 用户信息串长度 
 int gsmDecodePdu(char xdata* pSrc, SM_PARAM* pDst) 
 {     
 	int xdata nDstLength;           // 目标PDU串长度     
	unsigned char xdata tmp;        // 内部用的临时字节变量     
 	unsigned char xdata buf[256];   // 内部用的缓冲区          

   	// SMSC地址信息段     
 	gsmString2Bytes(pSrc, &tmp, 2);    // 取长度     
 	tmp = (tmp - 1) * 2;               // SMSC号码串长度     
 	pSrc += 4;                         //指针后移     

	gsmSerializeNumbers(pSrc, pDst->SCA, tmp);    
 	// 转换SMSC号码到目标PDU串     
 	pSrc += tmp;        
 	// 指针后移          
 	// TPDU段基本参数、回复地址等     
 	gsmString2Bytes(pSrc, &tmp, 2);    
 	// 取基本参数     
 	pSrc += 2;        
 	// 指针后移     

  	
	 if(tmp & 0x80)     
 	 {         
 		// 包含回复地址,取回复地址信息         
 		gsmString2Bytes(pSrc, &tmp, 2);    
 		// 取长度         
 		if(tmp & 1) tmp += 1;    
 		// 调整奇偶性         
 		pSrc += 4;          
 		// 指针后移         
 		gsmSerializeNumbers(pSrc, pDst->TPA, tmp);    
 		// 取TP-RA号码         
 		pSrc += tmp;        
 		// 指针后移     
 	 }          


	 // TPDU段协议标识、编码方式、用户信息等     
 	 gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2);    
 	// 取协议标识(TP-PID)     pSrc += 2;        
 	// 指针后移     
 	 gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2);    
 	 // 取编码方式(TP-DCS)     
 	 pSrc += 2;        // 指针后移     
 	 gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);        
 	 // 服务时间戳字符串(TP_SCTS)      
 	 pSrc += 14;       // 指针后移     
 	 gsmString2Bytes(pSrc, &tmp, 2);    // 用户信息长度(TP-UDL)     
 	 pSrc += 2;        // 指针后移     

 	
	  if(pDst->TP_DCS == GSM_7BIT)         
 	 {         
 		// 7-bit解码         
 		nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4);  
 		// 格式转换         
 		gsmDecode7bit(buf, pDst->TP_UD, nDstLength);    
 		
		// 转换到TP-DU         
 		nDstLength = tmp;     
 	  }     
	  else if(pDst->TP_DCS == GSM_UCS2)     
 	  {         
 	    #if 0
   	     // UCS2解码         
 		  nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);          // 格式转换         
 		  nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength);    // 转换到TP-DU     
 	    #endif

⌨️ 快捷键说明

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