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

📄 scomservice.c

📁 带时钟功能温度和湿度测量的仪器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*#######################################################################################//
文件名:  ScomService.c
功能:    串行通信服务函数实现
单位:    浙江工商大学-信电学院
创建日期:2004-09-24
创建人:  Houseivan
修改人:  Houseivan
修改日期:2005-03-11
########################################################################################*/
//##########################智能数据采集系统串行通讯协议简要:############################//
//#数据帧帧头:0xEB 0x90 0xEB 0x90 0xEB 0x90 
//#有效数据块:远程主机地址 本地主机地址 命令 参数和校验数据总长度 命令参数
//#帧序号(FrameNumHigh FrameNumLow) 校验码(CRCHigh CRCLow)#
//#数据帧帧尾:0x7E /*SCOM空闲时保持Mark状态即逻辑'1'*/
//#######################################################################################//
#include"Includes.h"
/*检测是否配置了网络通信功能*/
#if _SCOM_TASK>0

	extern uchar code FrameHead[];				//协议帧头

	extern uchar data TempInteger;				//温度值整数和符号字节
	extern uchar data TempDecimal;				//温度值小数位字节
	extern uchar data HumiInteger;				//湿度值整数和符号字节
	extern uchar data HumiDecimal;				//湿度值小数位字节
	extern uchar data UartRecBuf[];				//数据通讯缓冲器
	extern uchar data ClkLcmBuf[_MAX_LCM_NUM];	//显示和时钟操作缓冲器	
	extern uchar data DataBlockCount;			//接收缓冲中有效数据个数
	extern uchar data RecUpFlg;					//接收数据用标志变量
	extern uchar data UartHead;					//接收检验帧头存放变量
	extern uchar data SystemState;				//当前系统工作状态指示变量
	extern uchar data SlaveAddr;				//本地主机地址
	extern uchar data MasterAddr;				//远程主机地址
	extern uchar data CurRecNum;				//记录计数器 循环队列形式
	extern uchar data LcmMode;					//显示模式选择

	extern bit   RecReady;						//正确的数据接收完成标志
	extern bit	 WorkMode;		
	#if(_SCOM_TEST>0)
		extern uchar TestCom;
	#endif					//根据登陆成功与否确定站点工作的模式
	
#endif
/*检测是否配置了网络通信功能*/
#if _SCOM_TASK>0

//#######################################################################################//
//#include "ScomService.h"								     
//#######################################################################################//
//#Function:		void Uart0Init(void)
//#Description:	51串行口初始化
//#Input:		无
//#Output:		无
//#Return:		无
//#Others:		文件级公共函数
//#SBUF-串行口数据寄存器;TMOD,T2MOD,TCON,T2CON设置波特率发生器的工作方式
//#SCON-串行控制寄存器[7..0]=SM0 SM1 SM2 REN TB8 RB8 TI RI
//#PCON-电源控制寄存器[7..0]=SMOD - - - GF1 GF0 PD ID
//#IE  -中断允许控制寄存器[7..0]=EA -ET2 ES ET1 EX1 ET0 EX0
//#######################################################################################//
void Uart0Init(void)
{	
/*公共属性设置寄存器*/
	ChooseScomMode1();
#if _RATE_ADJUST_EN>0
	#if (_BAUD_TIMER>0)		//52模式可以选择T1或T2作为波特率发生器
		T2CON|=0x30;		//作为波特率发生器RCLK=TCLK=1
		//T2MOD|=;
		TH2   =_T2_HIGH;
		TL2   =_T2_LOW ;
		RCAP2H=_T2_HIGH;
		RCAP2L=_T2_LOW ;
		TR2   =       1;
	#else					//51模式只能采用T1做波特率发生器
		TCON&=0x0f     ;	//清除标志位
		TMOD|=0x20     ;	//mode2 BR=(2^smod)*fsoc/(32*12*(MAX-Ti))
		TH1  =_T1_HIGH  ;
		TL1  =_T1_LOW   ;
		TR1  =        1;
	#endif
#endif
		RecReady=0;
		DataBlockCount=0;
		RecUpFlg=0;
		UartHead=0xeb;
		AllowRx();
		OpenScom();
		EA=1;
}
//##################################################
//#Function:	SendByte
//#Description:51串行口字节发送函数
//#Input:		无
//#Output:		无
//#Return:		无
//#Others:		文件级公共函数
//##################################################
void SendByte(uchar sdata)
{
	AllowTx();
	TI=0;
	SBUF=sdata;
	while(!TI);
	TI=0;
	AllowRx();
}

//##################################################
//#Function:	LoginMaster
//#Description:登陆到系统服务器
//#Input:		无
//#Output:		无
//#Return:		无
//#Others:		文件级公共函数
//##################################################
bit	LoginMaster(void)
{
	bit rel=0;
	CallMaster(_CMD_LOG_IN);						//发送帧到PC	
	/*等待PC响应的登陆成功反馈信息*/
	DelayTime(2,1000);							//等待反馈
	if(ProcessFrameTask()==_CMD_ACK)			//登陆成功标志
		rel=_NET_MODE;
	return rel;	
}

//##################################################
//#Function:	SendFrame(uchar *UartRecBuf,uchar Len)
//#Description:带上头对数据进行校验计算,按协议打包数据发送帧到PC
//#Input:		数据存储缓冲首地址,数据长度
//#Output:		无
//#Return:		无
//#Others:		文件级公共函数UartRecBuf[0]:Cmd,UartRecBuf[1]:Len
//##################################################
void	SendFrame(uchar *UartBuf,uchar Len)
{
	uchar nCount;
	uint  nCrc;

	CloseScom();

	nCrc=CRCverify(UartBuf,Len);
	for(nCount=0;nCount<_F_HEAD_SIZE;nCount++)
		SendByte(FrameHead[nCount]);	//发送固定的头
	for(nCount=0;nCount<Len;nCount++)
	{	
		SendByte(UartBuf[nCount]);   	//发送数据
		UartBuf[nCount]=0x00;		    //然后清空单元
	}
	SendByte(nCrc/256);
	SendByte(nCrc%256);

	SendByte(_CMD_END);					//发送固定尾

	OpenScom();
}

//##################################################
//#Function:	CallMaster
//#Description:主动呼叫主机发送命令和数据进行通讯
//#Input:		呼叫类型
//#Output:		无
//#Return:		无
//#Others:		文件级公共函数,它负责将要发送的数据整合到缓冲中
//##################################################
void	CallMaster(uchar nCmd) 
{
	uchar	nCount;
	#if ((_DETECT_TASK>0)&&(_E2PROM_TASK>0))
		uchar	i;
	#endif

	CloseScom();								//禁止中断保护共享缓冲
	nCount=0;
	UartRecBuf[nCount++]=SlaveAddr;				//发送人
	UartRecBuf[nCount++]=MasterAddr;
	UartRecBuf[nCount++]=nCmd;
	switch(nCmd)
		{
	 		case	_CMD_WR_TEMP:				//LENG == 2
			#if _DETECT_TASK>0
				UartRecBuf[nCount++]=2+_F_EXTRA_LEN;
				UartRecBuf[nCount++]=TempInteger;
				UartRecBuf[nCount++]=TempDecimal;
				UartRecBuf[nCount++]=_F_SINGLE_NUM;
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif	
			break;
	 		case	_CMD_WR_HUMI: 				//LENG == 2
			#if _DETECT_TASK>0
				UartRecBuf[nCount++]=2+_F_EXTRA_LEN;
				UartRecBuf[nCount++]=HumiInteger;
				UartRecBuf[nCount++]=HumiDecimal;
				UartRecBuf[nCount++]=_F_SINGLE_NUM;
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_TIME:				//LENG == 3
			#if _CLOCK_TASK>0
				ReadClock(ClkLcmBuf);
				UartRecBuf[nCount++]=3+_F_EXTRA_LEN;
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_HOUR];
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_MINUTE];
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_SECOND];
				UartRecBuf[nCount++]=_F_SINGLE_NUM;
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_ALARM:						//该命令目前保留没有使用
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			break;
	 		case	_CMD_WR_DATE:						//LENG == 3
			#if _CLOCK_TASK>0
				ReadClock(ClkLcmBuf);
				UartRecBuf[nCount++]=3+_F_EXTRA_LEN;
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_YEAR];
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_MONTH];
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_DAY];
				UartRecBuf[nCount++]=_F_SINGLE_NUM;
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_WEEK:						//LENG == 1
			#if _CLOCK_TASK>0
				ReadClock(ClkLcmBuf);
				UartRecBuf[nCount++]=1+_F_EXTRA_LEN;
				UartRecBuf[nCount++]=ClkLcmBuf[_ID_WEEKLY];
				UartRecBuf[nCount++]=_F_SINGLE_NUM;
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_RECORD:						//LENG == 10
			#if ((_DETECT_TASK>0)&&(_E2PROM_TASK>0))
				UartRecBuf[nCount++]=10+_F_EXTRA_LEN;
				if(CurRecNum>_MIN_REC_NUM)
				{
					ReadOneRecord(ClkLcmBuf,CurRecNum);		//从24c02中读一条记录
					for(i=0;i<10;i++)
						UartRecBuf[nCount++]=ClkLcmBuf[i];
					UartRecBuf[nCount++]=CurRecNum--;
					UartRecBuf[nCount++]=CurRecNum;		//It's a single frame
				}
				else
				{
					for(i=0;i<10;i++)
						UartRecBuf[nCount++]=_EMPTY_DATA;
					UartRecBuf[nCount++]=_MIN_REC_NUM;
				}
				WriteOneChar(_CUR_REC_ADDR,CurRecNum);	//同步更新计数器单元
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
			case	_CMD_WR_RECNUM:						//LENG == 10
			#if ((_DETECT_TASK>0)&&(_E2PROM_TASK>0))
				UartRecBuf[nCount++]=1+_F_EXTRA_LEN;
				CurRecNum=ReadOneChar(_CUR_REC_ADDR);
				UartRecBuf[nCount++]=CurRecNum;
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_MCUID:
			#if _SCOM_TASK>0
				UartRecBuf[nCount++]=1+_F_EXTRA_LEN;	//表示数据长度0一个序号和Crc常数
				SlaveAddr=ReadOneChar(_LOCAL_ID);
				UartRecBuf[nCount++]=SlaveAddr;			//ReadOneChar(_LOCAL_ID)
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_PCID:
			#if _SCOM_TASK>0
				UartRecBuf[nCount++]=1+_F_EXTRA_LEN;	//表示数据长度0一个序号和Crc常数
				MasterAddr=ReadOneChar(_REMOTE_ID);
				UartRecBuf[nCount++]=MasterAddr;		//ReadOneChar(_REMOTE_ID)
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
			#endif
			break;
	 		case	_CMD_WR_PCUSER:						//保留的命令
			#if ((_SCOM_TASK>0)&&(_E2PROM_TASK>0))
				UartRecBuf[nCount++]=1+_F_EXTRA_LEN;	//表示数据长度0一个序号和Crc常数
				//UartRecBuf[nCount++]=MasterUser;
				UartRecBuf[nCount++]=ReadOneChar(_REMOTE_USER);
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame
		    #else
				UartRecBuf[nCount++]=_F_EXTRA_LEN;		//表示数据长度0一个序号和Crc常数
				UartRecBuf[nCount++]=_F_SINGLE_NUM;		//It's a single frame

⌨️ 快捷键说明

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