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

📄 scomservice.c

📁 带时钟功能温度和湿度测量的仪器
💻 C
📖 第 1 页 / 共 2 页
字号:
			#endif
			break;
			default:		  							//默认情况当作无参数命令处理
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			break;	
		}
	//SendFrame(UartRecBuf,UartRecBuf[_F_LENGTH_POS]+_F_SEND_ADD);
	SendFrame(UartRecBuf,nCount);

	OpenScom();
}

//##################################################
//#Function:	ProcessFrameTask(void)
//#Description:51串行口数据帧处理服务函数
//#Input:		无
//#Output:		无
//#Return:		返回相关的帧命令
//#Others:		文件级公共函数
//##################################################
uchar	ProcessFrameTask(void)
{
	uchar cmd;
	#if(_SCOM_TEST>0)
		uchar i;
	#endif
/*进行Crc校验4是(addr cmd len fh fl crh crl)此处应放置主机地址核对程序
	经过验证是有一个合法帧收到了
*/										
	if (RecReady)
	{	
		RecReady=0;
		CloseScom();
		if(CRCverify(UartRecBuf,UartRecBuf[3]+_F_RECV_ADD)==0)
		{	
			#if(_SCOM_TEST>0)
				for(i=0;i<DataBlockCount;i++)  			//DataBlockCount
					SendByte(UartRecBuf[i]);
			#endif
			SystemState=_CMD_CTRL_RUN;  				//表示收到一个命令进入命令响应模式
			cmd= UartRecBuf[2];
			/*此处放置实际的数据帧响应代码*/	
			switch(cmd) 					
			{
					case	_CMD_END:
						SystemState=_CMD_NORMAL_RUN;	//返回正常的温湿度显示模式
					break;
					case	_CMD_LOG_IN:
						CallMaster(_CMD_LOG_IN);
						WorkMode=_NET_MODE;
					break;
					case	_CMD_LOG_OUT:
						CallMaster(_CMD_LOG_OUT);
						WorkMode=_SITE_MODE;		
					break;
					case	_CMD_ACK:					//不动作
						//CallMaster(_CMD_ACK);
						WorkMode=_NET_MODE;
					break;
					case	_CMD_ERROR:					//不动作
						//CallMaster(_CMD_ERROR);
						LcmMode=_ERROR_RUN;
					break;
					case	_CMD_REAL_GET:
						#if	_DETECT_TASK>0		    
							SensorTaskRun();
						#endif
						#if _CLOCK_TASK >0
							ReadClock(ClkLcmBuf);		//获取当前时钟
						#endif
						CloseScom();
						UartRecBuf[0]=SlaveAddr;
						UartRecBuf[1]=MasterAddr;
						UartRecBuf[2]=_CMD_WR_RECORD;
						UartRecBuf[3]=10+_F_EXTRA_LEN;
						UartRecBuf[4]=TempInteger;
						UartRecBuf[5]=TempDecimal;
						UartRecBuf[6]=HumiInteger;
						UartRecBuf[7]=HumiDecimal;
						UartRecBuf[8]=ClkLcmBuf[_ID_YEAR];
						UartRecBuf[9]=ClkLcmBuf[_ID_MONTH];
						UartRecBuf[10]=ClkLcmBuf[_ID_DAY];
						UartRecBuf[11]=ClkLcmBuf[_ID_HOUR];
						UartRecBuf[12]=ClkLcmBuf[_ID_MINUTE];
						UartRecBuf[13]=ClkLcmBuf[_ID_SECOND];
						UartRecBuf[14]=_F_SINGLE_NUM;		//It's a single frame
						SendFrame(UartRecBuf,15);
						OpenScom();
					break;
					case	_CMD_RD_TEMP:
						CallMaster(_CMD_WR_TEMP);
					break;
					case	_CMD_RD_HUMI:
						CallMaster(_CMD_WR_HUMI);
					break;
					case	_CMD_RD_TIME:
						CallMaster(_CMD_WR_TIME);
					break;
					case	_CMD_RD_ALARM:				//保留的命令
						//CallMaster(_CMD_WR_ALARM);
					break;
					case	_CMD_RD_DATE:
						CallMaster(_CMD_WR_DATE);
					break;
					case	_CMD_RD_WEEK:
						CallMaster(_CMD_WR_WEEK);
					break;
					case	_CMD_RD_RECORD:
						CallMaster(_CMD_WR_RECORD);
					break;
					case	_CMD_RD_RECNUM:
						_CallMaster(_CMD_WR_RECNUM);
					break;
					case	_CMD_RD_MCUID:
						CallMaster(_CMD_WR_MCUID);
					break;
					case	_CMD_RD_PCID:				//保留的命令
						CallMaster(_CMD_WR_PCID);
					break;
					case	_CMD_RD_PCUSER:				//保留的命令
						CallMaster(_CMD_WR_PCUSER);
					break;
				/*--------以下开始为带参数命令----------*/
					//case	_CMD_SITE_INIT:
							//系统状态初始化
					//		break;
					case	_CMD_WR_PCUSER:				//保留的命令
						//MasterUser=UartRecBuf[4];
						//WriteOneChar(_REMOTE_USER,MasterUser);
					break;
					case	_CMD_WR_PCID:
		   		    #if ((_DETECT_TASK>0)&&(_E2PROM_TASK>0))
						MasterAddr=UartRecBuf[4];
						WriteOneChar(_REMOTE_ID,MasterAddr);
					#endif
					break;
					case	_CMD_WR_MCUID:
					#if ((_DETECT_TASK>0)&&(_E2PROM_TASK>0))
						SlaveAddr=UartRecBuf[4];
						WriteOneChar(_LOCAL_ID,SlaveAddr);
				    #endif
					break;
					case	_CMD_WR_RECNUM:
						CurRecNum=UartRecBuf[4];
						WriteOneChar(_CUR_REC_ADDR,CurRecNum);
					break;
					case	_CMD_WR_DATE:
					#if _CLOCK_TASK>0
						ReadClock(ClkLcmBuf);
						ClkLcmBuf[_ID_YEAR] =UartRecBuf[4];
						ClkLcmBuf[_ID_MONTH]=UartRecBuf[5];
						ClkLcmBuf[_ID_DAY]  =UartRecBuf[6];
						ClockInitialize(ClkLcmBuf);
						LcmMode=_DATE_RUN;
				    #endif
					break;
					case	_CMD_WR_TIME:
					#if _CLOCK_TASK>0
						ReadClock(ClkLcmBuf);
						ClkLcmBuf[_ID_HOUR] =UartRecBuf[4];
						ClkLcmBuf[_ID_MINUTE]=UartRecBuf[5];
						ClkLcmBuf[_ID_SECOND]  =UartRecBuf[6];
						ClockInitialize(ClkLcmBuf);
						LcmMode=_TIME_RUN;
					#endif
					break;
					case	_CMD_WR_ALARM:				//保留的命令
						//;
					break;
					case	_CMD_WR_WEEK:
					#if _CLOCK_TASK>0
						ReadClock(ClkLcmBuf);
						ClkLcmBuf[_ID_WEEKLY] =UartRecBuf[4];
						ClockInitialize(ClkLcmBuf);
						LcmMode=_WEEKLY_RUN;
					#endif
					break;
/*--------------------------------------*/
					default:
					break;		
			}
			//CallMaster(_CMD_ACK);
		}
		else
		{
			cmd=0;
		}
		/*恢复通讯口的初始化状态*/
		RecReady=0;
		DataBlockCount=0;
		RecUpFlg=0;
		UartHead=0xeb;
		//SystemState=_CMD_NORMAL_RUN;
		//#if	_SCOM_TEST>0
		//	SendByte(cmd);
		//#endif
		OpenScom();
	}
		return cmd;
}

//#if  _CRC_EN>0
#define _GOLD_CRC	0	//1:采用gold的CRC
/*#######################################################################################//
  Function:     CRCverify()
  Description:  计算CRC常数
  Input:        CrcLeng、 :有效数据个数
		uchar *Ptr:校验数据缓冲
  Output:       Null
  Return:       uint 返回余码
  Others:       CRC16-CCITT 按字节方式计算
  
  注:
  1.将一组数据进行CRC16运算后得到的CrcResult放在该序列后组成
  一个新组;接收方收到该组数据后在进行CRC16运算CrcResult=0表示
  无错误否则有错误!移位链的长度与CRC常数的长度相同!两次异或值
  还原;求得的CrcResult高字节在前低字节在后;
  2.只要移位链最高位出现一个1就要进行一次异或运算而移位链的值
  又来自序列所以要判断出序列中的1;
  CRC 根据”权”(即多项表达式)的不同而相应的源代码也有稍有不同,
  各种常用的权:
	CRC8=X8+X5+X4+1			//0x0031=1 0011 0001
	CRC-CCITT=X16+X12+X5+1		//0x1021=1 0001 0000 0010 0001
	CRC16=X16+X15+X5+1		//0x8021=1 1000 0000 0010 0001
	CRC12=X12+X11+X3+X2+1		//0x080D=1 1000 0000 1101
	CRC32=X32+X26+X23+X22+X16+X12	//0x04C11DB7=1 0000 0100 1100 
	+X11+X10+X8+X7+X5+X4+X2+X1+1	//0001 0001 1101 1011 0111
  r1<-----------r2<---------------------|<------DataIn
  |					|
  ◎------------------------------------◎
#########################################################################################*/
uint CRCverify( uchar *Ptr,uint CrcLeng )	//本函数采用的方式速度最慢
{
#if  _GOLD_CRC >0				//这种实现方式需要为序列空余出两个字节空间 后填充0
	uchar  Crc_j;				//循环计数用变量
	uint   Crc_i;				//循环计数用变量
	uchar  r1,r2,r3,r4;			//临时本地变量r3,r4;移位链r1,r2
	uint   CrcResult;			//CRC计算结果存放单元

	*(Ptr+CrcLeng)=0;			//在序列最后添加两个单元为0
	*(Ptr+CrcLeng+1)=0;			//
	r1=*Ptr;				//将首两个数据复制到r1、r2
	Ptr++;					//CrcResult=(r1<<8)|r2
	r2=*Ptr;				//先将前两个数据放入移位链中
	Ptr++;
	for (Crc_i=0;Crc_i<CrcLeng;Crc_i++)	//从最高位开始移位
	{	
		r3=*Ptr;			//取出序列中的一个数据进行运算
		Ptr++;
		for (Crc_j=0;Crc_j<8;Crc_j++)	//r1(High),r2(Low)作为移位寄存器
		{	
			r4=r1;			//保存上一次的r1到r4
			
			/*将16位移位链低字节r2移动一位到高字节r1中*/
			r1=(r1<<1);		//移掉最高为等待低位移入
			if ((r2&0x80)!=0)
				r1++;
			
			/*把新数的最高位移入移位链低字节r2中*/
			r2=(r2<<1);		//移掉最高为等待低位移入
			if ((r3&0x80)!=0)
				r2++;
			r3=(r3<<1);
			
			/*移位操作完成等待判断是否进行异或运算*/
			if ((r4&0x80)!=0)	//如果上一次移位链最高位是1则异或
			{	
				r1=r1^0x10;	//CRCConstant=0x1021
				r2=r2^0x21;	//将移位链与CRC常数进行异或
			}
		}
	}
	CrcResult=r1;
	CrcResult<<=8;
	CrcResult|=r2;
	return (CrcResult);
#else	//采用另外一种实现方式:序列不需要进入移位链 先填充0
	uchar i;
	uint CrcResult=0;
	while(CrcLeng--)
	{
		for(i=0x80; i!=0; i>>=1)
		{
		/*	只要移位链中最高位为1则移动一次再异或否则只移动*/	
			if((CrcResult&0x8000)!=0) 
			{
				CrcResult<<=1; 
				CrcResult^=0x1021;	//两次异或值还原;
			} 				//1-1
			else 
				CrcResult<<=1; 		//1-2
		/*	只要序列中出现一个1就要进行一次异或运算
			以下这句程序可以避免方法一中多余的两个字节	*/	
			if((*Ptr&i)!=0) 
				CrcResult^=0x1021; 	//1-3
		}
		Ptr++;
	}
	return(CrcResult);
#endif
}	


//#######################################################################################//
//#######################################################################################//
#endif //#ifdef _SCOM_TASK

⌨️ 快捷键说明

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