rs485dri.c

来自「这是一个MODBUS协议的串口接收和发送程序」· C语言 代码 · 共 202 行

C
202
字号


#include "reg52.h"
#include "rs485dri.h"

bit		TiState=0;							//发送寄存器空标志
uchar		Counter=0,FristChar=0;					
uchar		EndFlagLEN;
uchar		xdata *InComBuf;
uchar		InP,OutP;

	//----------------------------------------------//
	//          串行数据发送程序			//
	//----------------------------------------------//
	
void ComSendCh(unsigned char ch)	
{
	while(TiState);       							//等待发送标志空
	SBUF=ch; 					    			//写数据到发送寄存器
	TiState=1;
	while(TiState);
}


	//----------------------------------------------//
	//             串行中断服务程序			//
	//----------------------------------------------//
void serialget(void) interrupt 4 using 2		
{
	
	unsigned char GetChar;
	
	EA=0;
	if(RI)								
		{								//接收中断								
				
		RI=0;	               						//清除中断标志
		GetChar=SBUF;
	          
		if(CommandOK<COMMAND_NUM)
			{
			if(Com1mscounter==0)					//定时清串口缓冲区
				{FristChar=0;}					//清串口缓冲区
			
			switch(FristChar)	
				{
				case 	0:					//得到数据起始命令				
					if(GetChar==0x55)			//数据起始标志0x55 0xaa
						{FristChar=1;}
					//Com1mscounter=0x50;
					Com1mscounter=0x700;			//设定最大指令接受时间
					break;
				
				case 	1:					//数据起始标志							
					if(GetChar==0xaa)	
						{
						FristChar=3;					
						InComBuf=(uchar xdata *)WITHOUT_COMINBUF_AREA+InP*COMMAND_LEN;
						}
					else
						{FristChar=0;}
					break;			
				
				case 	3:					//得到地址								
					Counter=0;
					InComBuf[Counter]=GetChar;				
					Counter++;				
					if(GetChar==ShowInfo.Address)		//地址=本模块地址
						{
						FristChar=4;			//转入处理本模块数据
						}
					else if(GetChar==0)			//地址=0,无条件执行且不用返回参数
						{
						FristChar=4;			//转入处理本模块数据
						}
					else if(GetChar==0xfe)			//地址=0xfe是后门程序。
						{				
						FristChar=4;			//转入处理本模块数据
						}		
					
					else
						{
						FristChar=101;			//转入处理非本模块数据
						}								
					break;				
						//是本模块数据
				case 	4:					//得到功能号及数据长度值				
					InComBuf[Counter]=GetChar;				
					Counter++;				
					if(GetChar==3)				//功能3
						{					
						EndFlagLEN=8;			//功能3的数据长度为8
						FristChar=10;				
						}
					else if(GetChar==6)			//功能6
						{
						EndFlagLEN=8;			//功能6的数据总长度为8	
						FristChar=10;					
						}
					else if(GetChar==16)			//功能16
						{										
						FristChar=5;			//功能16的数据总长度								
						}
					else					//其他功能,等待时间到结束
						{									
						FristChar=0;			//不认识的命令,响应结束
						}				
					break;			
				
				case 	5:					//得到16号功能写入寄存器的位置
					InComBuf[Counter]=GetChar;				
					Counter++;
					if(Counter>=7)
						{
						EndFlagLEN=GetChar+9;
						FristChar=10;
						}
					break;
				case	10:					//正常接受数据并进行结束判定
					InComBuf[Counter]=GetChar;				
					Counter++;
					if(Counter>=EndFlagLEN)			//数据接收完毕,转入接收校验和2位
						{					
						CommandOK++;			//数据接收成功
						FristChar=0;
						InP++;		
						if(InP>=COMMAND_NUM)
							{InP=0;}			
						}
					break;					
				
						//是过路数据,监视
				case 	101:					//得到功能号及数据长度值				
					Counter++;
					if(GetChar==3)				//功能3
						{					
						EndFlagLEN=8;			//功能3的数据总长度为8	
						FristChar=110;					
						}
					else if(GetChar==6)			//功能6
						{
						EndFlagLEN=8;			//功能6的数据总长度为8	
						FristChar=110;					
						}
					else if(GetChar==16)			//功能16
						{										
						FristChar=102;			//转去得到6号功能数据长度						
						}
					else					//其他功能,等待时间到结束
						{									
						FristChar=0;			//不认识的命令,等待一帧指令+响应结束					
						}				
					break;
			
				case 	102:					//得到16号功能的数据长度值				
					Counter++;
					if(Counter>=7)
						{
						EndFlagLEN=GetChar+9;		//总数据量=起始地址,功能号,寄存器起始地址,寄存器数量,
										//	    要写入的字节数量,要设置的字符...n,CRC校验)9+个字节
						FristChar=110;			
						}
					break;	
				case	110:					//正常接受数据并进行结束判定							
					Counter++;
					if(Counter>=EndFlagLEN)			//数据结尾判断
						{					
						FristChar=0;					
						}
					break;						
				}	
			}		
		}	
	
	if(TI)
		{								//发送寄存器空中断
		//TiState=0;							//设发送寄存器空标志
		TI=0;
		TiState=0;
					
		}
	EA=1;
}


















⌨️ 快捷键说明

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