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

📄 f280x_modbusprotocol.c

📁 MODBUS完整原代码,很好的东西
💻 C
📖 第 1 页 / 共 2 页
字号:
//###########################################################################
//
// FILE:	F280x_ModbusProtocol.c
//
// TITLE:	F280x ModbusProtocol Application Functions.
//
//###########################################################################
//
//  Ver | dd mmm yyyy | Who  | Description of changes
// =====|=============|======|===============================================
//  1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha)
//      |             |      | Changed USER0-USER11 to USER1-USER12 to match the CPU guide
//###########################################################################
#include "F280x_Application.h"     // F280x Headerfile Include File
#include "F280x_EMC.h"             // F280x Examples Include File
#include "F280x_CommDefault.h"             // F280x Examples Include File

/*CRC 高位字节值表*/
const unsigned int auchCRCHi[] = {
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0,
	0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041, 
	0x00C1, 0x8140, 0x00C1, 0x8140, 0x01C0, 
	0x8041, 0x01C0, 0x8041, 0x00C1, 0x8140, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x00C1, 
	0x8140, 0x01C0, 0x8041, 0x01C0, 0x8041, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x00C1, 
	0x8140, 0x00C1, 0x8140, 0x01C0, 0x8041, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0, 
	0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140, 
	0x01C0, 0x8041, 0x01C0, 0x8041, 0x00C1, 
	0x8140, 0x01C0, 0x8041, 0x00C1, 0x8140, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0, 
	0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140, 
	0x01C0, 0x8041, 0x00C1, 0x8140, 0x01C0, 
	0x8041, 0x01C0, 0x8041, 0x00C1, 0x8140, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0, 
	0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041, 
	0x00C1, 0x8140, 0x00C1, 0x8140, 0x01C0, 
	0x8041, 0x00C1, 0x8140, 0x01C0, 0x8041, 
	0x01C0, 0x8041, 0x00C1, 0x8140, 0x01C0, 
	0x8041, 0x00C1, 0x8140, 0x00C1, 0x8140, 
	0x01C0, 0x8041, 0x01C0, 0x8041, 0x00C1, 
	0x8140, 0x00C1, 0x8140, 0x01C0, 0x8041, 
	0x00C1, 0x8140, 0x01C0, 0x8041, 0x01C0, 
	0x8041, 0x00C1, 0x8140 
} ; 
/*CRC低位字节值表*/
const unsigned int auchCRCLo[] = {
	0x00C0, 0xC101, 0xC303, 0x02C2, 0xC606, 
	0x07C7, 0x05C5, 0xC404, 0xCC0C, 0x0DCD, 
	0x0FCF, 0xCE0E, 0x0ACA, 0xCB0B, 0xC909, 
	0x08C8, 0xD818, 0x19D9, 0x1BDB, 0xDA1A, 
	0x1EDE, 0xDF1F, 0xDD1D, 0x1CDC, 0x14D4, 
	0xD515, 0xD717, 0x16D6, 0xD212, 0x13D3, 
	0x11D1, 0xD010, 0xF030, 0x31F1, 0x33F3, 
	0xF232, 0x36F6, 0xF737, 0xF535, 0x34F4, 
	0x3CFC, 0xFD3D, 0xFF3F, 0x3EFE, 0xFA3A, 
	0x3BFB, 0x39F9, 0xF838, 0x28E8, 0xE929, 
	0xEB2B, 0x2AEA, 0xEE2E, 0x2FEF, 0x2DED, 
	0xEC2C, 0xE424, 0x25E5, 0x27E7, 0xE626, 
	0x22E2, 0xE323, 0xE121, 0x20E0, 0xA060, 
	0x61A1, 0x63A3, 0xA262, 0x66A6, 0xA767, 
	0xA565, 0x64A4, 0x6CAC, 0xAD6D, 0xAF6F, 
	0x6EAE, 0xAA6A, 0x6BAB, 0x69A9, 0xA868, 
	0x78B8, 0xB979, 0xBB7B, 0x7ABA, 0xBE7E, 
	0x7FBF, 0x7DBD, 0xBC7C, 0xB474, 0x75B5, 
	0x77B7, 0xB676, 0x72B2, 0xB373, 0xB171, 
	0x70B0, 0x5090, 0x9151, 0x9353, 0x5292, 
	0x9656, 0x5797, 0x5595, 0x9454, 0x9C5C, 
	0x5D9D, 0x5F9F, 0x9E5E, 0x5A9A, 0x9B5B, 
	0x9959, 0x5898, 0x8848, 0x4989, 0x4B8B, 
	0x8A4A, 0x4E8E, 0x8F4F, 0x8D4D, 0x4C8C, 
	0x4484, 0x8545, 0x8747, 0x4686, 0x8242, 
	0x4383, 0x4181, 0x8040 
};

//const Uint16 bd_485_delay[]={26667,13333,6667,3333,1666,833,417};//延时1个字符时限
const Uint16 bd_485_delay[]={36667,18333,9167,4583,2292,1146,573};//延时1个字符时限

void GetSoe(Uint16 no);
//-------------------------------------------------------------------
//
//Modbus网络协议子程序
//

//CRC校验函数
Uint16 CRC16(Uchar * p_crc_msg, Uint16 crc_len)
{
	unsigned char crc_lo=0xff;
	unsigned char crc_hi=0xff;
	unsigned char crc_index;
	unsigned int  crc_value;
	while(crc_len--)
	{
		crc_index=crc_hi^((*p_crc_msg++)&0xff);//080409crc_index=crc_hi^*p_crc_msg++;
		//crc_hi=crc_lo^auchCRCHi[crc_index];
		//crc_lo=auchCRCLo[crc_index];		
		if(crc_index==crc_index/2*2)
		{//偶数位取其高字节
			crc_hi=crc_lo^(auchCRCHi[crc_index/2]>>8);
			crc_lo=auchCRCLo[crc_index/2]>>8;		
		}
		else
		{//奇数位取其低字节
			crc_hi=crc_lo^(auchCRCHi[crc_index/2]&0xff);
			crc_lo=auchCRCLo[crc_index/2]&0xff;		
		}

	}
	crc_value=crc_hi<<8|crc_lo;
	return crc_value;
}
//Modbus协议初始化
void InitSerModbus(Uchar flag)
{
    if(flag==0x55)//因保存定值的退出不再进行初始化
      return;  
    SerModbus.Access=0;   
    SerModbus.Busy=0;
    SerModbus.receive_count=0;
    SerModbus.send_count=0;
    SerModbus.send_head=0;
    SerModbus.crc_len=0;
    SerModbus.enable_flag=0,
    SerModbus.start_flag=0;
    SerModbus.end_flag=0;
	SerModbus.ck_count=0;
	SerModbus.ck_point=0;
	SerModbus.ck_flag=0;
	SerModbus.event_report=0;
	SerModbus.receive_flag=0;//接收帧计时
	SerModbus.send_flag=0;//发送帧计时
	SerModbus.r_timer=0;//接收帧计时
	SerModbus.s_timer=0;//发送帧计时
	/*
	soe_no=0;
	soe_id=0;
	soe_count=0;
	soe_flag=0;
	*/

}
//Modbus异常应答返回
void ErrorResponse(Uchar err)
{//err-异常码 1-非法功能,2-非法数据地址,3-非法数据值
	///unsigned char com_type;
	unsigned int  crc_result;
    SerModbus.Busy=0xff;//置通讯状态忙标志
	SerModbus.send_msg[1]=SerModbus.send_msg[1]|0x80;
	SerModbus.send_msg[2]=err;//异常码
	SerModbus.crc_len=3;
	crc_result=CRC16((Uchar *)&SerModbus.send_msg[0],SerModbus.crc_len);
	SerModbus.send_msg[3]=crc_result&0xff;
	SerModbus.send_msg[4]=(crc_result>>8)&0xff;
	SerModbus.send_count=SerModbus.crc_len+2;		
	SerModbus.s_timer=0;//发送记时清零	          
	SerModbus.send_flag=0xff;//置发送标志
	//com_type=COM_SER;  
	//ComSendCtrl(com_type);//通讯口发送控制
	ComSendCtrl(Com.port_typ);
}
//Modbus接收通信帧控制
void ModbusFrameCtrl(void)
{	
	Uint16 crc_result,crc_receive;
	//发送帧处理	
	if(SerModbus.send_flag)
	{
	 	//if(SerModbus.s_timer>(Uint32)bd_485_delay[dzbd]*7*SAMPLEPOINT/20000+1)
	 	if(SerModbus.s_timer>((Uint32)bd_485_delay[dzbd]*7*SAMPLEPOINT>>14)-1)
		{//判断发送间隔停顿时限大于7字符时限
		   SerModbus.enable_flag=0;
		   SerModbus.send_flag=0;//发送标志清零
	       SerModbus.send_count=0;
	       SerModbus.send_head=0;       
	       SerModbus.Access=0;//释放命令
	       SerModbus.Busy=0;
		   Ser.port_right=0;//释放通讯口
		   com1_reset_cnt=0;
	       com1_de=0;//关闭422发送使能端
		}
	}
	//接收帧处理	
	if(SerModbus.receive_flag && SerModbus.start_flag)
	{
		//if(SerModbus.r_timer>(Uint32)bd_485_delay[dzbd]*4*SAMPLEPOINT/20000+1)
		if(SerModbus.r_timer>((Uint32)bd_485_delay[dzbd]*4*SAMPLEPOINT>>14)-1)
		{//判断接收间隔停顿时限大于3.5字符时限
			SerModbus.start_flag=0;
			SerModbus.receive_flag=0;
			SerModbus.end_flag=0x55;//置帧结束标志
		}
	}

	if(SerModbus.end_flag!=0x55)
	{//帧接收处理过程中
		return;
	}
				
	//帧接收完成	
    Ser.port_right=0x55;//控制串口通讯口
	if(SerModbus.receive_count>2)
	    SerModbus.crc_len=SerModbus.receive_count-2;//CRC16校验长度
	else
		SerModbus.crc_len=0;
    SerModbus.receive_count=0;
	SerModbus.enable_flag=0;
	SerModbus.receive_flag=0;	
	SerModbus.start_flag=0;	
	SerModbus.end_flag=0;			
    SerModbus.send_msg[0]=dzid;
    SerModbus.send_msg[1]=SerModbus.receive_msg[1];
	//地址域解析
	if((SerModbus.receive_msg[0]!=dzid && SerModbus.receive_msg[0]!=0) || SerModbus.crc_len==0)
	{//帧接收解析地址域不匹配
		Ser.port_right=0;
		return;	
	}
		
    //CRC16校验
	crc_result=CRC16((Uchar *)&SerModbus.receive_msg[0],SerModbus.crc_len);
	crc_receive=SerModbus.receive_msg[SerModbus.crc_len]*256+SerModbus.receive_msg[SerModbus.crc_len+1];
	if(crc_result!=crc_receive)
	{//CRC校验不成功,非法数据
		Ser.port_right=0;
        return;    
	}
    SerModbus.Access=0xff;//校验成功置命令启动标志				

}
void RemoteCtrl()//开出监视控制
{
	Uint16* p_kc_time;
    if (SerModbus.ck_flag==0 || bittst((Uint16 * )&SerModbus.event_report,0)==0)
    {
       return;
    }
    p_kc_time=(Uint16*)&dzkc1_t;  
	if(SerModbus.ck_point<2) SerModbus.ck_point=2;
    if (SerModbus.ck_count>(*(p_kc_time+SerModbus.ck_point-2))*MACROSAMPLE_TIMES)
    {
	   bitclr(&kc_value,SerModbus.ck_point);
	   SerModbus.ck_count=0;
	   SerModbus.ck_flag=0;
	   SerModbus.ck_point=0;
	   bitclr((Uint16 * )&SerModbus.event_report,0);
	}
    else
	   SerModbus.ck_count++;
}		        

//Modbus消息控制
void SerModbusCtrl(void)
{
	Uchar   broad_flag,opcode,flag;
	Uint16  offset,s_addr,d_num,ctrl_point,byte,id,crc_result,value,i,j,k;
	Uint16* p_addr;
	ModbusFrameCtrl();//MODBUS通讯帧控制
	RemoteCtrl();//开出监视控制		        
    //--无接收命令或者通讯忙状态程序立即返回
    if ((SerModbus.Access!=0xff || Ser.port_right!=0x55) || SerModbus.Busy==0xff) 
    { //--无接收命令或者通讯忙状态程序立即返回
    	return;
    }
    SerModbus.Busy=0xff;//置通讯状态忙标志
    SerModbus.send_count=0;
    //com_type=Com.port_typ;
    //com_type=COM_SER;    
    broad_flag=0;
    if(SerModbus.receive_msg[0]==0)
    {//广播命令
	    broad_flag=0xff;
    }
    opcode=SerModbus.receive_msg[1];//解析功能码
    if (opcode<1 || opcode>24)
    {//功能码异常
		ErrorResponse(1);
        return;    
    }    
    switch(opcode)
    {
	case 1://Read Coil Status
			SerModbus.send_count=SerModbus.crc_len+2;
			break;   
	case 2://Read Input Status--遥信量
            ///offset=SerModbus.receive_msg[2]*256+SerModbus.receive_msg[3];
            ///d_num=SerModbus.receive_msg[4]*256+SerModbus.receive_msg[5];
            s_addr=SerModbus.receive_msg[2]*256+SerModbus.receive_msg[3];
            d_num=SerModbus.receive_msg[4]*256+SerModbus.receive_msg[5];
			j=0; while((s_addr<DigitalComm[j].start_addr || s_addr>=DigitalComm[j+1].start_addr) && j<DIGITAL_NO-1){j++;}//检索起始地址--地址范围:Start_pre<=x && x<Start_next
			offset = s_addr-DigitalComm[j].start_addr;//起始地址偏移量

			//召唤数据地址检测
            if (d_num<1 || ((d_num-1)>>4)+6 > MACROCOMM_S_NO)
            {
				ErrorResponse(3);//非法数据值
		        return;    
	        }
			//响应数据帧
			//数据类型为BYTE--8bit
	        SerModbus.send_msg[2]=((d_num-1)>>3)+1;//字节数目
	        for(i=0;i<SerModbus.send_msg[2];i++)
	        {
				//响应数据区域索引
				
				/*
				for(k=0;k<8;k++)
				{
					if (offset>=DigitalComm[j].data_num)
					{
						if ((offset+DigitalComm[j].start_addr)>=DigitalComm[j+1].start_addr && j<DIGITAL_NO-1)
						{
							offset = 0;j++;
							if (bittst(DigitalComm[j].p_addr,offset))
								bitset((Uint16*)&value,k);//状态量置1
							else
								bitclr((Uint16*)&value,k);//状态量清0						
						}
						else bitclr((Uint16*)&value,k);//状态量清0
					}
					else
					{ 
						if (bittst(DigitalComm[j].p_addr,offset))
							bitset((Uint16*)&value,k);//状态量置1
						else
							bitclr((Uint16*)&value,k);//状态量清0
					}

⌨️ 快捷键说明

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