📄 scomservice.c
字号:
/*#######################################################################################//
文件名: 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 + -