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

📄 canmodbus.c

📁 CAN 总线上跑的MODBUS程序 支持01、02、03、04、05、06功能码
💻 C
📖 第 1 页 / 共 2 页
字号:
			    MODBUSsendbuf[1]=0x80 | function ;
			    MODBUSsendbuf[2]=0x02;	
                MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验              
	           
	            MODBUSsendlen=4;     //计算CAN发送的数据长度
	            modbusDataToCan();	
	            	            		   			   
		   }   			          			       	     
	       		          			       	     	                
     }





/*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
  函数名称:	 command_03_04()
  函数功能:	 作为MODBUS从设备 应答03 04 功能码
  入口参数:	 function 功能码   *MODBUS_3_4area  MODBUS区域指针
  出口参数:	 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/    
void command_03_04(UINT8 function ,UINT16 *MODBUS_3_4area)
     {  
          UINT16 regaddr;
          UINT16 regcount;
        
          UINT16  crc_1; //2008.7.6
      
          regaddr=MODBUSrecvbuf[2];   //寄存器地址
          regaddr=(regaddr<<8)|((UINT8)(MODBUSrecvbuf[3]));
			                    
		  regcount=MODBUSrecvbuf[4];  //寄存器数
          regcount=(regcount<<8)|((UINT8)(MODBUSrecvbuf[5]));  
         
          MODBUSsendlen=5;
          
			                       
	      if( (regaddr<40) && (regcount==1)  )
		   {
			   MODBUSsendbuf[0]=MODBUSaddr;    //发送本机地址
		       MODBUSsendbuf[1]=function;          //发送MODBUS功能码
			   MODBUSsendbuf[2]=0x02;          //数据字节数
			             
			   MODBUSsendbuf[3]=*(MODBUS_3_4area+regaddr) >> 8 ;        //数据高位
			   MODBUSsendbuf[4]=*(MODBUS_3_4area+regaddr) & 0xff;         //数据低位
			          		      
			   crc_1=CRC16(MODBUSsendbuf,MODBUSsendlen);
               MODBUSsendbuf[MODBUSsendlen]=(UINT8)(crc_1>>8); //+CRC_Hi
               MODBUSsendlen++;
               MODBUSsendbuf[MODBUSsendlen]=(UINT8)crc_1;   //+CRC_Low
	           MODBUSsendlen++;     //计算CAN发送的数据长度
	           modbusDataToCan();
		   }
			      
	     else
		   {
			  MODBUSsendbuf[0]=MODBUSaddr;
			  MODBUSsendbuf[1]=0x80 | function ;
			  MODBUSsendbuf[2]=0x02;	
              MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验              
	           
	          MODBUSsendlen=4;     //计算CAN发送的数据长度
	          modbusDataToCan();	
	            	            		   			   
		   }   			          			       	     
	                
     }



/*-----------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
  函数名称:	  command_05()
  函数功能:	  作为MODBUS从设备 应答05 功能码
  入口参数:	  无
  出口参数:	  无
-------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/    
void command_05(void)
     {  
          UINT16 coiladdr;       
          UINT8  kk,mm,nn;
            
          coiladdr=MODBUSrecvbuf[2];   //线圈地址
          coiladdr=(coiladdr<<8)|((UINT8)(MODBUSrecvbuf[3]));
			                    
		    		                     
		   if( coiladdr<80 )
			{ 
			   mm = coiladdr/8;    
			   nn = coiladdr%8;
			    
			   if(MODBUSrecvbuf[4]==0xFF)
				   MODBUS0area[mm]= MODBUS0area[mm]  |  ONEbit1[nn];        
			   if(MODBUSrecvbuf[4]==0x00)
				   MODBUS0area[mm]= MODBUS0area[mm]  &  ONEbit0[nn];
				      		           
			   for(kk=0;kk<8;kk++)  //原文返回 MODBUSsendbuf[pp]=MODBUSrecvbuf[pp]; 要对自身CAN ID过滤
				  MODBUSsendbuf[kk] = 0xbf;          
	           
	           MODBUSsendlen=8;     
	           modbusDataToCan();   
	                
			 } 
			 
		  else
			 {
			    MODBUSsendbuf[0]=MODBUSaddr;
			    MODBUSsendbuf[1]=0x85;
			    MODBUSsendbuf[2]=0x02;	
                MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验              
	           
	            MODBUSsendlen=4;     //计算CAN发送的数据长度
	            modbusDataToCan();	
	                        		   			   
			  }       
			       	     
	                
     }



/*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
  函数名称:	 command_06()
  函数功能:	 作为MODBUS从设备 应答06 功能码
  入口参数:	 
  出口参数:	 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/    
void command_06(void)       //存在问题
     {  
         UINT16 regaddr;
         UINT8 pp;
                
         regaddr=MODBUSrecvbuf[2];   //寄存器地址
         regaddr=(regaddr<<8)|((UINT8)(MODBUSrecvbuf[3])); 
         
         if(regaddr<40)
         {
         
           MODBUS4area[regaddr]= ((UINT16)MODBUSrecvbuf[4]<<8) |  (UINT16)MODBUSrecvbuf[5] ;    
           for(pp=0;pp<8;pp++)    //原文返回 MODBUSsendbuf[pp]=MODBUSrecvbuf[pp];
             MODBUSsendbuf[pp] = 0xaf;
                    
           MODBUSsendlen = 0x08;
           modbusDataToCan();
                     
         }
         
         else
		 {
			MODBUSsendbuf[0]=MODBUSaddr;
			MODBUSsendbuf[1]=0x86;
			MODBUSsendbuf[2]=0x02;	
            MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验              
	           
	        MODBUSsendlen=4;     //计算CAN发送的数据长度
	        modbusDataToCan();	
	            	            		   			   
		 }  
         
				 	          			       	     	                
     }
     
 
 /*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
  函数名称:	 modbus_master()
  函数功能:	 作为MODBUS主设备 发送 各 功能码
  入口参数:	 
  出口参数:	 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/    
void modbus_master(UINT8 stationaddr,UINT8 function,UINT16 Maddr,UINT16 Mcount)       
     { 
         UINT16 crc_1;
         MODBUSsendbuf[0]=stationaddr;
         MODBUSsendbuf[1]=function;
         MODBUSsendbuf[2]=Maddr>>8;
         MODBUSsendbuf[3]=Maddr&0xff;          
		 MODBUSsendbuf[4]=Mcount>>8;
		 MODBUSsendbuf[5]=Mcount&0xff;
		 
		 crc_1=CRC16(MODBUSsendbuf,6);
         MODBUSsendbuf[6]=(UINT8)(crc_1>>8); //+CRC_Hi
         MODBUSsendbuf[7]=(UINT8)crc_1;   //+CRC_Low
	     MODBUSsendlen=8;     //计算CAN发送的数据长度
	     
	     modbusDataToCan();		 
		             	    
	}
		
				 	          			       	     	                
          
     
/*------------------------------------------------------------------------
--------------------------------------------------------------------------
  函数名称:	 CRC16()
  函数功能:	 
  入口参数:	 要进行CRC校验的数组的头指针 *pushMsg
             要进行CRC校验的数组的字节数
  出口参数:	 校验生成的16位校验码
-------------------------------------------------------------------------
------------------------------------------------------------------------*/
UINT16 CRC16(UINT8 *pushMsg ,UINT8 usDataLen)
   {
    UINT8 uchCRCHi=0xFF;           //高CRC字节初始化
    UINT8 uchCRCLo=0xFF;           //低CRC 字节初始化
    UINT16 uIndex;                   //CRC循环中的索引
   while (usDataLen--)            //传输消息缓冲区
        {
        uIndex   = uchCRCHi ^ *pushMsg++; // 计算CRC 
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; 
		uchCRCLo = auchCRCLo[uIndex] ; 
        }
   return (uchCRCHi<< 8 | uchCRCLo);
   }


 
 
/*------------------------------------------------------------------------
--------------------------------------------------------------------------
  函数名称:	LRC8()
  函数功能:	 
  入口参数:	 要进行LRC校验的数组的头指针 *aushMsg
             要进行CRC校验的数组的字节数  LCRDataLen
  出口参数:	 校验生成的8位校验码
-------------------------------------------------------------------------
------------------------------------------------------------------------*/ 
UINT8 LRC8(UINT8 *auchMsg, UINT8 LCRDataLen) 
{ 
    INT8 uchLRC = 0 ; /*初始化LRC字符 */ 
    while (LCRDataLen--) /*通过数据缓冲器*/ 
    uchLRC  += *auchMsg++;         
    
    return (UINT8)(-((INT8)uchLRC)) ; /*返回二进制补码*/ 
}  




/*------------------------------------------------------------------------
--------------------------------------------------------------------------
  函数名称:	  modbusDataToCan(void)
  函数功能:	  把MODBUS应答报文发送到CAN总线上
  入口参数:	  无
  出口参数:	  status   0:发送成功   1:发送不成功
-------------------------------------------------------------------------
------------------------------------------------------------------------*/

UINT32  modbusDataToCan(void)
{
	UINT32	status=0,i;
	
	
		CTbuf.TxFrameInfo.Bits.PRIO_BIT = 0; 	//CAN通道号
		CTbuf.TxFrameInfo.Bits.FF_BIT	= 1;	//帧格式
		CTbuf.TxFrameInfo.Bits.RTR_BIT	= 0;	//帧类型
		CTbuf.TxFrameInfo.Bits.DLC_BIT	= MODBUSsendlen ;//数据长度
		for(i=0;i<4;i++)
		{
			*((UINT8 *)&CTbuf.TxCANID.Word +i)=MODBUScanID[i];
		}
		memcpy((UINT8 *)&CTbuf.CANTDA,&MODBUSsendbuf[0],4);
		memcpy((UINT8 *)&CTbuf.CANTDB,&MODBUSsendbuf[4],4);
		
		status = CANSendData(00,02,&CTbuf);
	
	return	status;
}




















⌨️ 快捷键说明

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