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

📄 gr47.c

📁 gr47的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/ 

/******************************************************************************/ 
			  

/******************************************************************************/ 
/******************************************************************************/ 

// 用户信息编码方式 
#define GSM_7BIT 0 
#define GSM_8BIT 4 
#define GSM_UCS2 8 
// 短消息参数结构,编码 / 解码共用 

UCHAR	xdata	PhoneNum[32]; // 目标号码或回复号码 (TP-DA 或 TP-RA)  
UCHAR	xdata	TP_DCS; // 用户信息编码方式 (TP-DCS)  
bit	    	   	message_ture = 0;	//回执确认	

/******************************************************************************/ 

/******************************************************************************/

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

	return (nSrcLength - nSrcLength/8); 	 // 返回目标编码串长度
}

/******************************************************************************/
// 7-bit 解码 
// pSrc: 源编码串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源编码串长度 
// 返回 : 目标字符串长度 
UCHAR DecodeBit7(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst, UCHAR nSrcLength)
{ 
	UCHAR nDst; // 目标编码串的计数值 
	UCHAR nByte; // 当前正在处理的组内字符字节的序号,范围是 0-7 
	UCHAR nLeft; // 上一字节残余的数据 

	// 计数值初始化 
	nDst = 0; // 组内字节序号和残余数据初始化 
	nByte = 0; 
	nLeft = 0; 

	// 将源数据每 7 个字节分为一组,解压缩成 8 个字节 
	// 循环该处理过程,直至源数据被处理完 
	// 如果分组不到 7 字节,也能正确处理 
	while(nDst<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++; 		    // 修改源串的指针和计数值
	} 
	*pDst = 0; 
	return (nSrcLength); 		  // 返回目标串长度 
}

/******************************************************************************/
// BetyChange 编码 
// pSrc: 源字符串指针 
// pDst: 目标编码串指针 
// nSrcLength: 源字符串长度 
// 返回 : 目标编码串长度 
UINT EncodeBetyChange(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst, UCHAR nSrcLength) 
{ 
	UCHAR	i; 	
	UINT	xdata	len; 
	UCHAR	code	tab[]={"0123456789ABCDEF"}; // 0x0-0xf 的字符查找表  

	for(i=0; i<nSrcLength; i++) 
	{  
		*pDst++ = tab[*pSrc >> 4]; // 输出高 4 位 
		*pDst++ = tab[*pSrc & 0x0f];// 输出低 4 位 
		pSrc++; 
	}  
	len = ((UINT)nSrcLength) * 2;
	return (len); 	 // 返回目标编码串长度
}

/******************************************************************************/ 
// BetyChange 解码 	
// pSrc: 源编码串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源编码串长度 
// 返回 : 目标字符串长度 
UCHAR	DecodeBetyChange(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst, UCHAR nSrcLength) 
{ 	
	UCHAR	i;
		
	for(i=0; i<nSrcLength; i++) 
	{ 
		if(*pSrc>='0' && *pSrc<='9') 	   // 输出高 4 位 
		{ 
			*pDst = (*pSrc - '0') << 4; 
		} 
		else 
		{ 
			*pDst = (*pSrc - 'A' + 10) << 4; 
		} 
		pSrc++; 
		
		if(*pSrc>='0' && *pSrc<='9') 	   // 输出低 4 位 
		{ 
			*pDst |= *pSrc - '0'; 
		} 
		else 
		{ 
			*pDst |= *pSrc - 'A' + 10; 
		} 
		pSrc++; 
		pDst++; 
	}				  				 								  	

	return (nSrcLength); 	   // 返回目标字符串长度
}

/******************************************************************************/  
// 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补 'F' 凑成偶数 
// 如: "8613851872468" --> "683158812764F8" 
// pSrc: 源字符串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源字符串长度 
// 返回 : 目标字符串长度 
UCHAR InvertNumbers(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst,UCHAR nSrcLength) 
{ 
	UCHAR nDstLength; // 目标字符串长度 
	UCHAR ch,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
	}
	 
	return(nDstLength); 	  // 返回目标字符串长度 
} 

/******************************************************************************/ 
// 两两颠倒的字符串转换为正常顺序的字符串 
// 如: "683158812764F8" --> "8613851872468" 
// pSrc: 源字符串指针 
// pDst: 目标字符串指针 
// nSrcLength: 源字符串长度 
// 返回 : 目标字符串长度 
UCHAR Invert_Return(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst,UCHAR nSrcLength) 
{ 
	UCHAR nDstLength; // 目标字符串长度 
	UCHAR ch,i;
	 
	nDstLength = nSrcLength; 

	for(i=0; i<nSrcLength;i+=2)    // 两两颠倒 
	{ 
		ch = *pSrc++; // 保存先出现的字符 
		*pDst++ = *pSrc++; // 复制后出现的字符 
		*pDst++ = ch; // 复制先出现的字符 
	}  

	if(*(pDst-1) == 'F') 
	{ 
		pDst--; 
		nDstLength--; // 目标字符串长度减 1 
	}

	return(nDstLength); 	  // 返回目标字符串长度 
} 

/******************************************************************************/ 

// 以下是 PDU 全串的编解码模块。为简化编程,有些字段用了固定值。 
// PDU 编码,用于编制、发送短消息 
// pSrc: 源 PDU 参数指针 
// pDst: 目标 PDU 串指针 
// 返回 : 目标 PDU 串长度 
UINT gsmEncodePdu(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst) 
{ 
	UINT 	xdata		nDstLength; // 目标 PDU 串长度 
	UCHAR 	xdata		code_char[160];	  //编码字符缓冲区
	UCHAR	xdata 		buf[5]; // 内部用的缓冲区 	  
	UCHAR	xdata 		m; 
	
	buf[0] = 0x00;								 //默认中心号码
	nDstLength = EncodeBetyChange(buf, pDst, 1); // 转换 1 个字节到目标 PDU 串 
	 	
	if(message_ture == 1)
		buf[0] = 0x31; //需要回执
	else	
		buf[0] = 0x11;	  // 是发送短信 (TP-MTI=01) , TP-VP 用相对格式 (TP-VPF=10) 

	buf[1] = 0x00; // TP-MR=0 
	m = strlen(PhoneNum);
	buf[2] = m; // 目标地址数字个数 (TP-DA 地址字符串真实长度 ) 
	if((PhoneNum[0] == '8')&&(PhoneNum[1] == '6'))
		buf[3] = 0x91; //用国际格式号码
	else
		buf[3] = 0x81; //用国内格式号码 

	nDstLength += EncodeBetyChange(buf, pDst + nDstLength, 4); // 转换 4 个字节到目标 PDU 串 

	nDstLength += InvertNumbers(PhoneNum, pDst + nDstLength, m); // 转换 TP-DA 到目标 PDU 串 
	
	// TPDU 段协议标识、编码方式、用户信息等	
	buf[0] = 0; // 协议标识 (TP-PID) 
	buf[1] = TP_DCS; // 用户信息编码方式 (TP-DCS) 
	buf[2] = 255; // 有效期 (TP-VP)=0 为 5 分钟 ; =255为最长。
	buf[3] = strlen(pSrc);  //信息长度

	if(data_gsm == 1)
		buf[3] = data_len;

	if(buf[1] == GSM_7BIT)
	{
		buf[4] = EncodeBit7(pSrc, code_char, buf[3]);
	}
	else	if(buf[1] == GSM_8BIT)
	{
	   	buf[4] = buf[3];
		memcpy(code_char, pSrc, buf[3]); 
	}

	nDstLength += EncodeBetyChange(buf, pDst + nDstLength, 4); // 转换 4 个字节到目标 PDU 串 

	nDstLength += EncodeBetyChange(code_char, pDst + nDstLength, buf[4]); // 转换信息内容到目标 PDU 串	

	*(pDst + nDstLength) = 0x1a; // 以 Ctrl-Z 结束	
	nDstLength++;
							  	 
	return (nDstLength); 		   // 返回目标字符串长度
} 

/******************************************************************************/ 

// PDU 解码,用于接收、阅读短消息 
// pSrc: 源 PDU 串指针 
// pDst: 目标 PDU 参数指针 
// 返回 : 用户信息串长度 
UCHAR gsmDecodePdu(UCHAR	xdata	*pSrc,UCHAR	xdata	*pDst) 	 
{ 
	UCHAR 	nDstLength; // 目标 PDU 串长度 
	UCHAR 	xdata	code_char[165];	  //解码字符缓冲区
	UCHAR 	code	receive_ture[] = {"ok"};	  //解码字符缓冲区
	UCHAR	xdata	i,m;

	m=(*(pSrc+1))&0xf; // 取SMSC 号码串长度 	 
	pSrc += m*2 + 2;   // 指针后移 	
  
	DecodeBetyChange(pSrc,&m,1);		  // 基本参数
	pSrc += 2; // 指针后移 	

	if((m & 0x02) == 0x02)		//短信接受确认信息
	{			 		
		pSrc += 2;

		DecodeBetyChange(pSrc, &m, 1);	// 取长度
		pSrc += 4;			// 指针后移,忽略了回复地址(TP-RA)格式

		nDstLength = Invert_Return(pSrc,pDst,(m+1)&0xfe);	 // 取 TP-RA 号码 
		pSrc +=	(m+1)&0xfe;		// 指针后移

		*(pDst+nDstLength) = ',';
		nDstLength++;

		pSrc += 14;
		nDstLength += Invert_Return(pSrc,pDst+nDstLength,12);	// 服务时间戳字符串
		
		*(pDst+nDstLength) = ',';
		nDstLength++; 		
		
		memcpy(pDst+nDstLength, receive_ture, 2);
		nDstLength += 2; 

		return  (nDstLength);
	}   
	//08 91683108505905F0 06 1D 0D 91683158703261F6 505021908480 23 505021908411 23 00 FF  //回执PDU

	//08 91683108200505F0 24    0D 91683158714209F8 00 00 400152803535 00 04 D4F29C0E	   //接受PDU
	DecodeBetyChange(pSrc,code_char,1);	
	m = code_char[0];						//回复地址信息长度 (TP-UDL)
   	
	pSrc += 4; // 指针后移
	 
	nDstLength = Invert_Return(pSrc,pDst,(m+1)&0xfe);	 // 取 TP-RA 号码 
	pSrc +=	(m+1)&0xfe;

	*(pDst+nDstLength) = ',';
	nDstLength++;

	pSrc += 2; 
	 
	TP_DCS = *(pSrc+1) & 0x0f; 								   //编码方式
	pSrc += 2; 
		
	nDstLength += Invert_Return(pSrc,pDst+nDstLength,12);	// 服务时间戳字符串
	pSrc += 14;

	*(pDst+nDstLength) = ',';
	nDstLength++;

	DecodeBetyChange(pSrc,code_char,1);	
	m = code_char[0];						// 用户信息长度 (TP-UDL)
   	pSrc += 2; 

	DecodeBetyChange(pSrc,code_char,m);					// 格式转换

	if(TP_DCS == GSM_7BIT)
	{
		nDstLength += DecodeBit7(code_char,pDst+nDstLength,m);				// 7-bit 解码 
	}		 
	else	if(TP_DCS == GSM_8BIT)
	{
		memcpy(pDst+nDstLength, code_char, m); 					   	// 8-bit 解码
	   	nDstLength += m;
	}	
	else	if(TP_DCS == GSM_UCS2)
	{
		for(i = 0; i < m;  )
		{
			*(pDst+nDstLength) = *(code_char + i + 1); 					   	// 16-bit 解码
		   	nDstLength ++;
			i += 2;
		}
	}			
								 
	*(pDst+nDstLength) = '\n';
	nDstLength++;		   
	*(pDst+nDstLength) = '\0';
	nDstLength++;
					
	return (nDstLength); 
}

/******************************************************************************/ 
	
	// 发送短消息 
	// pSrc: 源 PDU 参数指针 
bit	SendMessage(UCHAR	xdata	*pSrc) 
{ 
	UINT  xdata	PduLength; // PDU 串长度 
	UCHAR xdata	SmsLength; // SMS 串长度 
	UINT  xdata	r_len;	 // 串口收到的数据长度  	
	UCHAR m,i,j;				  
	UCHAR code	cmd0[9]={"AT+CMGS="}; // 命令串 
	UCHAR xdata	cmd[9]; // 命令串 
	UCHAR xdata	pdu[500]; // PDU 串 
	UCHAR xdata ans[64]; // 应答串 

	while(gsm_busy)
		os_wait(K_TMO,1,0);

	gsm_busy = 1;

	PduLength = gsmEncodePdu(pSrc, pdu); // 根据 PDU 参数,编码 PDU 串 		 

	SmsLength = (PduLength - 2)/2; // 取 PDU 串中的 SMS 信息长度 
	
	for(i=0;i<8;i++)
		cmd[i]=cmd0[i];

 	get_string_clear1( );				//清空缓冲区

	put_string1(cmd, 8);
		
	i = SmsLength/100;
	if(i != 0)
		put_char1(i +0x30);		   //发送指令
		   	
	SmsLength = SmsLength%100;
	m = SmsLength/10;
	if((m != 0)||(i != 0))
		put_char1(m +0x30);		   //发送PDU长度

	put_char1((SmsLength%10)+0x30);
	put_char1(0x0d);
	put_char1(0x0a);

	for(i = 2; i>0; i--)
	{
		r_len = get_string1(ans);	 // 读应答数据
		if(r_len != 0)	
		{
			break;
		}
	}
	if(r_len == 0)	
	{	
		gsm_busy = 0;
		return(FALSE);				
	}	  
											 
	if(ans[r_len-2] != '>')
	{	
		gsm_busy = 0;
		return(FALSE);				
	}
	put_string1(pdu,PduLength);		//发送PDU
			
	for(j=0; j<4; j++)
	{
		for(i=0; i<25; i++)
		{
			memset(ans,0x00,64);
			r_len = get_string1(ans);	 // 读应答数据
			if(r_len > 0)
			{					
				break;
			}
		}
		
		ans[r_len] = '\0';	
			
		if((r_len > 3) && (strstr(ans,"OK") != NULL))  	 //查找OK
		{		 			
			gsm_busy = 0;
			day_inc = 0;
			return(TRUE);
		}
	}
	gsm_busy = 0;
	return(FALSE);	 
} 
	 
/******************************************************************************/ 
// 删除短消息  
// index: 短消息序号,从 1 开始 
void DeleteMessage(UCHAR index) 
{ 
	UCHAR m,i; 
	UCHAR code	cmd0[9]={"AT+CMGD="}; // 命令串 
	UCHAR xdata	cmd[9]; 			// 命令串 

	for(i=0;i<8;i++)
		cmd[i]=cmd0[i];

 	get_string_clear1( );				//清空缓冲区

	put_string1(cmd, 8);
	m = index/10;
	if(m != 0)
		put_char1(m +0x30);
	put_char1((index%10)+0x30);	 
	put_char1(0x0d);
	put_char1(0x0a);
	
 	get_string_clear1( );				//清空缓冲区
}
	
/******************************************************************************/ 

// 读取短消息 
// 用CMGL
//一次读出一条短消息
// pDrc 返回字符串指针
// index 短信序号 
//返回:字符串长度  
UCHAR ReadMessage(UCHAR	xdata	*pDrc)
{  	
	UCHAR m,i,index;				  
	UINT  xdata	r_len; 		 // 串口收到的数据长度  
	UCHAR code	cmd0[16]={"AT+CMGL=4\r\n"}; // 命令串 
	UCHAR xdata	cmd[16]; 			// 命令串 
	UCHAR xdata	buf[500]; // 接受缓冲 	
	UCHAR xdata	*ptr;  			
		 	
	while(gsm_busy)
		os_wait(K_TMO,1,0);

	ptr = buf;
	gsm_busy = 1;

	for(i=0;i<12;i++)
		cmd[i]=cmd0[i];

 	get_string_clear1( );				//清空缓冲区

	put_string1(cmd, 11);  

	for(i = 8; i>0; i--)
	{
		r_len = get_string1(buf);	 // 读应答数据
		if(r_len > 30)
			break;
	}
							  
	if(r_len < 30)
	{	
		gsm_busy = 0;
		return(0); 
	}

	buf[r_len] = '\0';

	if((ptr = strstr(buf, "CMGL:")) != NULL)
	{	
			ptr = strchr(buf,',');		// 跳过"+CMGL:"
			index = ((*(ptr-2))&0x0f)*10 + ((*(ptr-1))&0x0f);	// 读取序号	  

			ptr = strstr(ptr, "\r\n");	// 找下一行
			ptr += 2;		// 跳过"\r\n"
			
			m = gsmDecodePdu(ptr, pDrc);	// PDU串解码   		   	
			
			DeleteMessage(index);

			gsm_busy = 0;
			return(m);	 	
	}
	gsm_busy = 0;
	return (0);
}

/******************************************************************************/   
void read_storage(UCHAR	n)
{  	
	UCHAR code	cmd0[]={"AT+CPMS= ME , SM , SM \r\n"}; // 命令串 
	UCHAR code	cmd1[]={"AT+CPMS= SM , SM , SM \r\n"}; // 命令串 
	UCHAR xdata	cmd[25]; 			// 命令串 
	UCHAR i; 		

	while(gsm_busy)
		os_wait(K_TMO,1,0);	
	gsm_busy = 1;

	if(n == 1)
	{
		for(i=0;i<24;i++)

⌨️ 快捷键说明

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