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

📄 modbus.c

📁 富士通单片机MB90F387上实现MODBUS
💻 C
📖 第 1 页 / 共 5 页
字号:
            	  		}              	  		      	  		      	  		        	  		
            	  } 
            	  return(1);         	  	
        	  } 
        	  else  //CRC校验不一致;可重新发送请求或作其他处理
        	  {
        	  		Rx_Buffer[2] = 0x09;
        	  		FaultProcess();
        	  		return(0);
        	  }                    	
        }        
        else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
        {
						FaultProcess();
						return(0);
        }  
        */     
    }
    else //通信异常
    {
    	  Rx_Buffer[2] = 255;//异常码填充(测试用)
				FaultProcess();
				return(0);
    }     
}

/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :cmd04_ReadAnlogIn()  
* 功能  :读取模拟量输入(ASCII模式):CMD == 4 
* 返回  :成功返回1,否则返回0
* 备注  :Tested
请求命令:[设备地址] [命令号04] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
设备响应:[设备地址] [命令号04] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位] [CRC校验的高8位]
*********************************************************************************************************/
uchar cmd04_ReadAnlogIn(uchar DeviceID, uint start_address, uint lenth) 
{
    uchar tmp[256], tmp_lenth;
    
    tmp[0] = DeviceID;//从设备地址
    tmp[1] = 0x04;  //命令
    tmp[2] = wordHByte(start_address);//起始地址 高字节
    tmp[3] = wordLByte(start_address);//起始地址 低字节
    tmp[4] = wordHByte(lenth);//读取数据量 高字节
    tmp[5] = wordLByte(lenth);//读取数据量 低字节 
    tmp_lenth = 6;
    if(Modbus_mode)
    {
    		construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串    
    		TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
  	}
  	else
  	{
    		construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);  	
    		TxBytes = tmp_lenth+2;
  	}
  	comSend();//发送请求
  	if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
    {    		             
        if(Rx_Buffer[1] == 0x04) //通信正常,数据处理
        {
        	  if(CheckCRC(Rx_Buffer,RxBytes))
        	  {
            	  switch(Rx_Buffer[2])//返回字节数
            	  {     
            	  		case 0x02:
            	  		{        
            	  					             	  			 		
            	  				break;	
            	  		}
            	  		case 0x04:
            	  		{        	  			
            	  				break;	
            	  		}
            	  		case 0x06:
            	  		{        	  			
            	  				break;	
            	  		}  
            	  		case 0x08:
            	  		{        	
            	  			    para_val = Rx_Buffer[3]*256 + Rx_Buffer[4];	         	  			  			
            	  				break;	
            	  		} 
            	  		default:
            	  		{          						    									
    										break;         	  			
            	  		}              	  		      	  		      	  		        	  		
            	  }  
            	  return(1);        	  	
        	  } 
        	  else  //CRC校验不一致;可重新发送请求或作其他处理
        	  {
        	  		Rx_Buffer[2] = 0x09;
        	  		FaultProcess();
        	  		return(0);
        	  }                    	
        }
        else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
        {
						FaultProcess();
						return(0);
        }       
    }
    else //通信异常
    {
    	  Rx_Buffer[2] = 255;//异常码填充
				FaultProcess();
				return(0);
    } 
}


/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :cmd05_SetCoil()  
* 功能  :设置继电器(ASCII模式):CMD == 5 
* 返回  :成功返回1,否则返回0
* 备注  :Tested
* 请求命令:[设备地址] [命令号05] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
* 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
*********************************************************************************************************/
uchar cmd05_SetCoil(uchar DeviceID, uint start_address, uint value)
{
    uchar tmp[256], tmp_lenth;
    
    tmp[0] = DeviceID;//从设备地址
    tmp[1] = 0x05 ;//命令  
    tmp[2] = wordHByte(start_address);//起始地址 高字节
    tmp[3] = wordLByte(start_address);//起始地址 低字节
    tmp[4] = wordHByte(value);//待写数据 高字节
    tmp[5] = wordLByte(value);//待写数据 低字节
    tmp_lenth = 6;
    
    if(Modbus_mode)
    {
    		construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串    
    		TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
  	}
  	else
  	{
    		construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);  	
    		TxBytes = tmp_lenth+2;
  	}
  		
  	comSend();//发送请求
  	if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
    {    		             
        if(Rx_Buffer[1] == 0x05) //通信正常,数据处理
        {
        	  if(CheckCRC(Rx_Buffer,RxBytes))
        	  {
      	  			if(Rx_Buffer[2]!=Tx_Buffer[2]) return(0);
      	  			if(Rx_Buffer[3]!=Tx_Buffer[3]) return(0);
      	  			if(Rx_Buffer[4]!=Tx_Buffer[4]) return(0);
      	  			if(Rx_Buffer[5]!=Tx_Buffer[5]) return(0);	
      	  			return(1);
        	  } 
        	  else  //CRC校验不一致;可重新发送请求或作其他处理
        	  {
        	  		Rx_Buffer[2] = 0x09;
        	  		FaultProcess();
        	  		return(0);
        	  }                    	
        }
        else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
        {
						FaultProcess();
						return(0);
        }       
    }
    else //通信异常
    {
    	  Rx_Buffer[2] = 255;//异常码填充
				FaultProcess();
				return(0);
    } 
}
/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :cmd06_SetHldreg() 
* 功能  :设置单保持寄存器(ASCII模式):CMD == 6 
* 返回  :成功返回1,否则返回0
* 备注  :Tested
* 请求命令:[设备地址] [命令号06] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
* 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
*********************************************************************************************************/
uchar cmd06_SetHldreg(uchar DeviceID, uint start_address, uint value)
{
    uchar tmp[256], tmp_lenth;
    
    tmp[0] = DeviceID; //地址
    tmp[1] = 0x06;//命令
    tmp[2] = wordHByte(start_address);//写数据的起始地址 高字节
    tmp[3] = wordLByte(start_address);//写数据的起始地址 低字节
    tmp[4] = wordHByte(value);//待写数据 高字节
    tmp[5] = wordLByte(value);//待写数据 低字节
    tmp_lenth = 6;//有效数据长度
    if(Modbus_mode)
    {
    		construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
    		TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
  	}
  	else
  	{
    		construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);  	
    		TxBytes = tmp_lenth+2;
  	}
  		
  	comSend();//发送请求
  	if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
    {    		             
        if(Rx_Buffer[1] == 0x06) //通信正常,数据处理
        {
        	  if(CheckCRC(Rx_Buffer,RxBytes))
        	  {
      	  			if(Rx_Buffer[2]!=Tx_Buffer[2]) return(0);
      	  			if(Rx_Buffer[3]!=Tx_Buffer[3]) return(0);
      	  			if(Rx_Buffer[4]!=Tx_Buffer[4]) return(0);
      	  			if(Rx_Buffer[5]!=Tx_Buffer[5]) return(0);	
      	  			return(1);
        	  } 
        	  else  //CRC校验不一致;可重新发送请求或作其他处理
        	  {
        	  		Rx_Buffer[2] = 0x09;
        	  		FaultProcess();
        	  		return(0);
        	  }                    	
        }
        else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
        {
						FaultProcess();
						return(0);
        }       
    }
    else //通信异常
    {
    	  Rx_Buffer[2] = 255;//异常码填充
				FaultProcess();
				return(0);
    }   
}

/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :cmd15_setcoils() 
* 功能  :对多个线圈进行强制(ASCII模式):CMD == 15 
* 返回  :成功返回1,否则返回0
* 备注  :Tested
* 请求格式:从站地址 0x0F 第一个位首地址 所写位数 值占用的字节数 值
         (例如,置从站5的位12至17为1,则:05 0F 000C 0006 01 3F CRC)
*********************************************************************************************************/
uchar cmd15_setcoils(uchar DeviceID, uint Startbit_Add, uint Bit2Write, uchar ByteValue, uchar *Values)
{
    uchar tmp[256], tmp_lenth,i;
    
    tmp[0] = DeviceID;
    tmp[1] = 0x0f ;  
    tmp[2] = wordHByte(Startbit_Add);
    tmp[3] = wordLByte(Startbit_Add);
    tmp[4] = wordHByte(Bit2Write);
    tmp[5] = wordLByte(Bit2Write);
    tmp[6] = ByteValue;
    for(i=0;i<ByteValue;i++)
   		 tmp[7+i] = Values[i];

    tmp_lenth = 7+ByteValue;
    
    if(Modbus_mode)
    {
    		construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
    		TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
  	}
  	else
  	{
    		construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);  	
    		TxBytes = tmp_lenth+2;
  	}
  		
  	comSend();//发送CMD请求
  	if(comReceive())//获取应答;对应答数据分析
    {
    	//rtu_data_anlys();
    }
    return 18;
}


/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :cmd16_SetMultiHldreg()
* 功能  :设置多个保持寄存器(ASCII模式):CMD == 16 
* 返回  :成功返回1,否则返回0
* 备注  :Tested
*********************************************************************************************************/
uchar cmd16_SetMultiHldreg(uchar DeviceID, uint start_address, uint WNum, uchar BNum, uint *values)
{
    uchar tmp[256], tmp_lenth;
    uchar i=0;
    uint j;
    
    tmp[0] = DeviceID; //地址
    tmp[1] = 0x10;      //命令
    tmp[2] = wordHByte(start_address);//写数据的起始地址 高字节
    tmp[3] = wordLByte(start_address);//写数据的起始地址 低字节
    tmp[4] = wordHByte(WNum); //待写寄存器数量
    tmp[5] = wordLByte(WNum); //待写寄存器数量
    tmp[6] = BNum;        //待写数据的字节数
    for(j=0;j<WNum;j++)      //填充数据
    {    		
    		tmp[i+7] = wordHByte(values[j]);//待写数据 高字节    
    		tmp[i+8] = wordLByte(values[j]);//待写数据 低字节  
    		i=i+2;     		
    }
    tmp_lenth = 7+i;//有效数据长度
    
    if(Modbus_mode)
    {
    		construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
    		TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
  	}
  	else
  	{
    		construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);  	
    		TxBytes = tmp_lenth+2;
  	}
  		
  	comSend();//发送CMD请求
  	if(comReceive())//获取应答;对应答数据分析
    {
    	//rtu_data_anlys();
    }
    return 18;
}

/********************************************************************************************************
* 作者  :冯子龙
* 日期  :200709
* 名称  :Master_process_rtu()
* 功能  :RTU模式  接收分析
* 返回  :1,CMD_ERR
* 备注  :
*********************************************************************************************************/
char process_Master_RTU( int  *dest, uchar *src,uint start_address, uint fr_lenth)
{
    uint crc_result, crc_tmp;
    uchar i, j, shift;

⌨️ 快捷键说明

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