📄 scominterrupt.c
字号:
/*#######################################################################################//
文件名: ScomInterrupt.c
功能: 串行口232接收中断服务函数定义
单位: 浙江工商大学-信电学院
创建日期:2004-09-24
创建人: Houseivan
修改人: Houseivan
修改日期:2005-03-11
########################################################################################*/
#include "Includes.h"
/*检测是否配置了网络操作功能*/
#if _SCOM_TASK>0
extern uchar data SlaveAddr; //本地主机地址
extern uchar data MasterAddr; //远程主机地址
//#######################智能温湿度监控仪串行通讯协议简要:##############################//
//#数据帧帧头:0xEB 0x90 0xEB 0x90 0xEB 0x90
//#有效数据块:主机地址 Datas(数据或命令) 数据长度 FrameNumHigh FrameNumLow CRCHigh CRCLow#
//#数据帧帧尾:0x7E /*SCOM空闲时保持Mark状态即逻辑'1'*/
//#######################################################################################//
//#######################################################################################//
//#Name : RecUpFlg
//#Purpose : 接收数据结构控制标志标志
//#InitialValue : 0
//#ValueRange : 0->255
//#Used By : 中断服务函数
//#Notice : 文件级共享
//#######################################################################################//
extern uchar data RecUpFlg;
//#######################################################################################//
//#Name : UartHead
//#Purpose : 帧头数据存放单元
//#InitialValue : 0
//#ValueRange : 0->255
//#Used By : 中断服务函数
//#Notice : 文件级共享
//#######################################################################################//
extern uchar data UartHead;
//#######################################################################################//
//#Name : DataBlockCount
//#Purpose : 数据块长度计数器
//#InitialValue : 0
//#ValueRange : 0->255
//#Used By : 中断服务函数
//#Notice : 文件级共享
//#######################################################################################//
extern uchar data DataBlockCount;
//#######################################################################################//
//#Name : UpLeng
//#Purpose : 帧实际数据长度单元
//#InitialValue : 0xff
//#ValueRange : 0->255
//#Used By : 中断服务函数
//#Notice : 文件级共享
//#######################################################################################//
extern uchar data UpLeng;
//#######################################################################################//
//#Name : UartRecBuf
//#Purpose : 串行通讯数据交换缓冲器
//#InitialValue : 0
//#ValueRange : 0->255
//#Used By : 中断服务函数
//#Notice : 文件级共享
//#######################################################################################//
extern uchar data UartRecBuf[];
#if(_SCOM_TEST>0)
extern uchar data TestCom;
#endif
extern bit RecReady; //正确的数据接收完成标志
//bit FrameFlg=0; //接收到帧标志
/*
UartHead, DataBlockCount, UpLeng, UartRecBuf[], CrcLeng, ParaBuf, SendBuf, WriteE2prom()
*/
//#######################################################################################//
//#######################################################################################//
//#Function: UartService(void)
//#Description: 串口0中断处理程序(RS485)
//#Input: 无
//#Output: 无
//#Return: 无
//#Others: 文件级公共函数适用于51内核处理器UartHead:头标志存放单元
/*#使用到的全局变量: 帧由命令和数据构成、有些命令可能不带任何数据
RecUpFlg-帧结构标志 ; UartHead-帧头数据存放单元 ;
UpLeng-帧实际数据长度单元 ; UartRecBuf[MaxSize]-串行通讯数据交换缓冲器
DataBlockCount-数据块长度计数器;
*/
//#######################################################################################//
//_USART0_VECT
void UartService() interrupt _USART0_VECT //由于51的收发中断地址相同所以在服务函数里最好不要发送
{
uchar UartReg; //UartReg读端口暂存变量Count:临时计数器变量
uchar Count;
if(RI) //检测是否是因为接收到数据产生中断
{
CloseScom();
RI=0; //清除中断标志
UartReg=SBUF; //接收一个字符
if(RecUpFlg<7) //当帧结构标志RecUpFlg<10时收到数据才有可能为帧头
{
if(UartReg==UartHead) //比较是否为帧头,如果此时帧结构标志为0则认为是头否则忽略
{ //eb 90 eb 90 eb 90 ... 7e
RecUpFlg++; //接收数据各部分标志字节<0x10表示头=0x10表示主机地址0x20表示数据
Count=(RecUpFlg&0x0f);
if(Count==0x06) //检测是否收到六个字节的头
{
RecUpFlg=0x10; //设定帧数据标志为接收主机地址
}
if (UartHead==0x90) //收到0x90就准备接收0xeb
UartHead=0xeb;
else
UartHead=0x90;
}
else //不等表示该数据不是头数据而是控制数据
{
RecUpFlg=RecUpFlg&0xf0; //把低位清0
UartHead=0xeb; //恢复通讯模式到初始化模式
}
}
else //0x10之后接收的数据全部为合法数据
{
//检测接收通讯有效数据
switch(RecUpFlg&0xf0) //根据计数器值来判断当前帧的数据类型
{
case 0x10: //RecUpFlg=0x10接收主机地址并初始化好接收缓冲器UartRecBuf
UartRecBuf[0]=UartReg; //UartRecBuf将获取有效数据的第一个字节
RecUpFlg=0x20; //下一个字节开始为有效数据RecUpFlg=0x20即切换到case 0x20
break;
case 0x20: //RecUpFlg=0x10接收主机地址并初始化好接收缓冲器UartRecBuf
UartRecBuf[1]=UartReg; //UartRecBuf将获取有效数据的第一个字节
DataBlockCount=2; //DataBlockCount有效数据计数器初始化为1
UpLeng=0xff; //数据长度初始化为255
RecUpFlg=0x30; //下一个字节开始为有效数据RecUpFlg=0x20即切换到case 0x20
break;
case 0x30: //接收真正的通讯数据到缓冲器UartRecBuf[]
UartRecBuf[DataBlockCount]=UartReg;
DataBlockCount++; //对有效数据进行计数
UpLeng=UpLeng-1;
switch(UpLeng) //根据UpLeng的值确定数据是否收完
{
case 0: //当UpLeng为0时表示数据帧接收完毕可以对当前帧响应
if( ( ( UartRecBuf[0]==MasterAddr )&&( UartRecBuf[1]==SlaveAddr ) )
||( ( UartRecBuf[0]==_DEFAULT_PC_IP )&&( UartRecBuf[1]==_DEFAULT_MCU_IP ) ) )
{
//if(CRCverify(UartRecBuf,UartRecBuf[3]+_F_RECV_ADD)==0)
RecReady=1;
//SendByte(0x30);
}
else
{
RecReady=0;
RecUpFlg=0;
UartHead=0xeb;
}
break;
case 0xfd: //根据协议规定定位到数长字节并将其复制到UpLeng=UartReg;
UpLeng=UartReg; //收到的第三个有效数据为实际数据长度Len=253+3+UartReg=UartReg
break;
default:
break;
} //switch(UpLeng)
break; //case 0x30
default:
break;
} //switch(RecUpFlg&0xf0)
} //if(RecUpFlg<10)
OpenScom();
}
}
//#######################################################################################//
//#######################################################################################//
#endif //#ifdef _SCOM_EN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -