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

📄 f280x_modbusprotocol.c

📁 MODBUS完整原代码,很好的东西
💻 C
📖 第 1 页 / 共 2 页
字号:
					offset++;
				}
				*/

				if (offset>=DigitalComm[j].data_num)
				{
					if ((offset+DigitalComm[j].start_addr)>=DigitalComm[j+1].start_addr && j<DIGITAL_NO-1)
					{
						offset = 0;j++;
						value = *(DigitalComm[j].p_addr+offset);
					}
					else value=0;//状态量清0
				}
				else
				{ 
					value = *(DigitalComm[j].p_addr+(offset>>4));
					if ( ((offset>>4)<<1) != offset>>3 ) { value >>=8;}//(offset/16*2 !=offset/8) is high--8bit of 16bit
				}
				offset +=8;
	            SerModbus.send_msg[i+3]=value&0xff;
	        }	        	        	        
	        SerModbus.crc_len=SerModbus.send_msg[2]+3;
			SerModbus.send_count=SerModbus.crc_len+2;
			break;   
	case 3://Read Holding Registers
            ///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<AnalogComm[j].start_addr || s_addr>=AnalogComm[j+1].start_addr ) && j<ANALOG_NO-1){j++;}//检索起始地址--地址范围:Start_pre<=x && x<Start_next
			offset = s_addr-AnalogComm[j].start_addr;
						
			if (j>=ANALOG_NO-1)
			{
				j=ANALOG_NO-1;				
				if (s_addr>=CommSoeEventAddr && s_addr < CommSoeEventAddr+CommSoeEventNum)
				{//召唤SOE---!!!ThinkRoad special function
					id=(s_addr-CommSoeEventAddr)/(MACROFAULT_BYTE>>1); offset = 0;
					GetSoe(id); //soe_id:0~127
					bitclr(&soe_status[0],id);//召SOE成功则清SOE状态标志//080414
				}
				else
				{
					ErrorResponse(3);//非法数据值
					return;    
				}
			}			
			//召唤数据地址检测
            if (d_num<1 || d_num+5>MACROCOMM_S_NO)
            {
				ErrorResponse(3);//非法数据值
				return;    
 	        }

			//响应数据帧
			//数据类型为WORD--16bit
	        SerModbus.send_msg[2]=2*d_num;
	        for(i=0;i<d_num;i++)
	        {
				//响应数据区域索引
				if (offset>=AnalogComm[j].data_num)
				{					
					if ((offset+AnalogComm[j].start_addr)>=AnalogComm[j+1].start_addr && j<ANALOG_NO-1)
					{
						offset = 0;j++;
						value=*(AnalogComm[j].p_addr+offset);
					}
					else value=0;
				}
				else value=*(AnalogComm[j].p_addr+offset);
				/*********定值控制字逻辑变量**********/
				if ((AnalogComm[j].p_addr+offset)>=(Uint16 *)&dzkg1 && (AnalogComm[j].p_addr+offset)<((Uint16 *)&dzkg1+(MACROSETDZKG_NO<<4)) && AnalogComm[j].start_addr>=CommSetDz1Addr)//!!!控制字寄存器变量设置区域
				{
					k=AnalogComm[j].p_addr+offset-(Uint16 *)&dzkg1;
					if (bittst((Uint16 *)&dzkg1,k))
						value = 1;
					else
						value = 0;
				}
				/************************************/
				offset++;
				SerModbus.send_msg[2*i+3]=(value>>8)&0xff;//数据高位字节
				SerModbus.send_msg[2*i+4]=value&0xff;//数据低位字节
	        }
	        SerModbus.crc_len=SerModbus.send_msg[2]+3;	
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 4://Read Input Registers--遥测量
			SerModbus.send_count=SerModbus.crc_len+2;
			break;   
	case 5://Force Single Coil
            ctrl_point=SerModbus.receive_msg[2]*256+SerModbus.receive_msg[3];//--主机修改定值点号
	        value=SerModbus.receive_msg[4]*256+SerModbus.receive_msg[5];
            if(ctrl_point>CONTROL_NO-1)
            {
				ErrorResponse(3);//非法数据值
				return;    
 	        }
			if(ctrl_point<8 && dzyk_s == 1)
			{//遥控出口
				if(value)//value == 0xFF00
				{
					SerModbus.ck_point=ctrl_point;
					bitset(&kc_value,ctrl_point);
					bitset((Uint16 * )&SerModbus.ck_flag,ctrl_point);
				}
				else
				{
					SerModbus.ck_point=ctrl_point;
					bitclr(&kc_value,ctrl_point);
					bitclr((Uint16 * )&SerModbus.ck_flag,ctrl_point);
				}
				bitset((Uint16 * )&SerModbus.event_report,0);
			}
			else CommSelCtrl(ctrl_point);

		    SerModbus.send_msg[2]=SerModbus.receive_msg[2];//定值通道号高位字节
		    SerModbus.send_msg[3]=SerModbus.receive_msg[3];//定值通道号低位字节
		    SerModbus.send_msg[4]=SerModbus.receive_msg[4];//数据高位字节
		    SerModbus.send_msg[5]=SerModbus.receive_msg[5];//数据低位字节
	        SerModbus.crc_len=6;
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 6://Preset Single Resister--遥控量
		    SerModbus.send_count=SerModbus.crc_len+2;		
		    break;   
	case 7://Read Exception Status
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 8://Reserve 回送诊断校验,把诊断校验报文送从机,以对通信处理进行评鉴
			SerModbus.send_count=0;
			break;   
	case 9://编程(只用于484)使主机模拟编程器作用,修改PC从机逻辑
			SerModbus.send_count=0;
			break;   
	case 10://控询(只用于484)
			SerModbus.send_count=0;
			break;   
	case 11://Fech Comm Event Ctr
			SerModbus.send_count=SerModbus.crc_len+2;
			break;   
	case 12://Fech Comm Event Log
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 13://编程(只用于484)使主机模拟编程器作用,修改PC从机逻辑
			SerModbus.send_count=0;
			break;   
	case 14://控询(只用于484)
			SerModbus.send_count=0;
			break;   
	case 15://Force Mutiple Coils
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 16://Preset Multiple Regs--遥调量
            ///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];//数据个数
			byte=SerModbus.receive_msg[6];//字节长度
			j=0; while((s_addr<AnalogComm[j].start_addr || s_addr>=AnalogComm[j+1].start_addr) && j < ANALOG_NO-1 ){j++;}//检索起始地址--地址范围:Start_pre<=x && x<Start_next
			offset = s_addr-AnalogComm[j].start_addr;

			if (d_num<1 || d_num+5>MACROCOMM_S_NO /*|| d_num!=byte/2*/)
            {
				ErrorResponse(3);//非法数据值
		        return;    
	        }
	        	        
            for(i=0;i<d_num;i++)
            {
	        	value=(SerModbus.receive_msg[i*2+7])*256+SerModbus.receive_msg[i*2+8];
				//响应数据区域索引
				if (offset>=AnalogComm[j].data_num)
				{					
					if ((offset+AnalogComm[j].start_addr)>=AnalogComm[j+1].start_addr && j<ANALOG_NO-1)
						{offset = 0;j++; }
					else
						break;		
				}
	       		*(AnalogComm[j].p_addr+offset)=value;

				//定值类型检测
				if ((AnalogComm[j].p_addr+offset)>=(Uint16*)&clockrade && (AnalogComm[j].p_addr+offset)<((Uint16*)&clockrade+0x06))
				{//时钟区域
					p_addr = (Uint16 *)&clockwrite;
					*(p_addr+ (AnalogComm[j].p_addr+offset-(Uint16*)&clockrade)) = value;
					flag = 0x01;
				}
				else if ((AnalogComm[j].p_addr+offset)>=(Uint16*)&nvdd_accu && (AnalogComm[j].p_addr+offset)<((Uint16*)&nvdd_accu+0x0e))
				{//电度区域
					flag = 0x02;
				}
				else if ((AnalogComm[j].p_addr+offset)>=(Uint16* )&DzDat0.Point[0] && (AnalogComm[j].p_addr+offset)<((Uint16* )&DzDat0.Point[0]+0x40) && AnalogComm[j].start_addr<CommSetDz1Addr)
				{//用户区域
					flag = 0x03;
				}				
				else if ((AnalogComm[j].p_addr+offset)>=(Uint16*)&dzkg1 && (AnalogComm[j].p_addr+offset)<((Uint16*)&dzkg1+(MACROSETDZKG_NO<<4)) && AnalogComm[j].start_addr>=CommSetDz1Addr)//!!!控制字寄存器变量设置区域
				{//控制字逻辑变量区域
					flag = 0x04;
					k=AnalogComm[j].p_addr+offset-(Uint16*)&dzkg1;
					if(value)
						bitset((Uint16 *)&dzkg1,k);
					else
						bitclr((Uint16 *)&dzkg1,k);
				}
				else if ((AnalogComm[j].p_addr+offset)>=(Uint16* )DDRAM_DAT_ABS && (AnalogComm[j].p_addr+offset)<((Uint16* )DDRAM_DAT_ABS+0x40))
				{//其它参数区域
					flag = 0x05;
				}
				else if ((AnalogComm[j].p_addr+offset)>=(Uint16* )&DzDat1.Point[0] && (AnalogComm[j].p_addr+offset)<((Uint16* )&DzDat1.Point[0]+0x40))
				{//调试区域
					flag = 0x06;
				}
				else {ErrorResponse(3);return;}//非法数据值
				offset++;

            }

			//定值类型检测
			if (flag==0x01)
				ClockSet();//时钟设置
			else if(flag==0x02)
				read_energy();//电度设置(将nvdd值写入DDRAM)
			else if(flag==0x03 || flag==0x04)
				bitset(&save_event_flag,0);//用户定值
			else if(flag==0x06)
				bitset(&save_event_flag,1);//调试定值
			else if(flag==0x05)
				;//其它参数(自动保存)

		    SerModbus.send_msg[2]=SerModbus.receive_msg[2];//定值通道号高位字节
		    SerModbus.send_msg[3]=SerModbus.receive_msg[3];//定值通道号低位字节
		    SerModbus.send_msg[4]=SerModbus.receive_msg[4];//数据高位字节
		    SerModbus.send_msg[5]=SerModbus.receive_msg[5];//数据低位字节
            SerModbus.crc_len=6;
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 17://Report Slave
			SerModbus.send_count=0;
			break;   
	case 18://(884和MICRO84)
			SerModbus.send_count=0;
			break;   
	case 19://重置通信链路
			SerModbus.send_count=0;
			break;   
	case 20://Read Gerenal Reference
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 21://Write General Reference
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 22://Mask Write 4X Register
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 23://Read/Write 4X Registers
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	case 24://Read FIFO Queue
			SerModbus.send_count=SerModbus.crc_len+2;		
			break;   
	default:
			SerModbus.send_count=0;
			break;   
    }
    
    //广播命令或者发送字节为0立即返回
    if(broad_flag==0xff || SerModbus.send_count==0)
    {
       SerModbus.Busy=0;
       SerModbus.Access=0;
       SerModbus.send_count=0;
       Ser.port_right=0;     
       return;     
    }         
    // 发送数据校验                      
	crc_result=CRC16((Uchar *)&SerModbus.send_msg[0],SerModbus.crc_len);
	SerModbus.send_msg[SerModbus.crc_len]=(crc_result>>8)&0xff;	
	SerModbus.send_msg[SerModbus.crc_len+1]=crc_result&0xff;
	SerModbus.s_timer=0;//发送记时清零	          
	SerModbus.send_flag=0xff;//置发送标志
	//com_type=COM_SER;            
	//ComSendCtrl(com_type);//通讯口发送控制
	ComSendCtrl(Com.port_typ);
}
/*
void GetSoe(Uint16 no)
{		
	Uint16 * p_data;
	Uint16 start,size;
	p_data=(Uint16*)&fault_soe;
	size=FAULT_BYTE_NO/MACROFAULT_PAGE;
	start=FAULTAREA_ADDR+size*no;
	ReadFm24cl((Uint16*)p_data,start,size,1,FM2416_ID);//共保存7120字节故障记录    64条故障记录
}
*/
void GetSoe(Uint16 no)
{		
	Uint16 *p_data,*p_fault;
	Uint16 start,size;
	Uint16 id,i;
	p_data=(Uint16*)&fault_soe;
	if ((no+1) != soe_id)
	{//主机主动召唤SOE
		start=FAULTAREA_ADDR+MACROFAULT_BYTE*no;
		ReadFm24cl((Uint16*)p_data,start,MACROFAULT_BYTE,1,FM2416_ID);//共保存7120字节故障记录    64条故障记录
	}
	else
	{//从机请求召唤SOE
		///id = soe_id-1-fault_block_wr*MACROFAULT_PAGE;
		id = no-no/MACROFAULT_PAGE*MACROFAULT_PAGE;
		p_fault = (Uint16* )&fault_record[id];
		for(i=0;i<(MACROFAULT_BYTE>>1);i++) {*(p_data++) = *(p_fault++);}
		if (soe_count>0) 
		{
			soe_count--;
			if(++soe_id>MACROFAULT_SOE) { soe_id=1; }
			bitset(&soe_status[0],soe_id-1);//置SOE状态标志
		}
		if (soe_count==0) {soe_id=0;}//SOE传输完成
	}
}

//===========================================================================
// No more.
//===========================================================================

⌨️ 快捷键说明

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