非标 Modbus-RTU Master 开发纪录

非标Modbus-RTU主站开发

Modbus-RTU Master

为啥不直接移植Free Modbus? 因为PM需要非标的, 这理由真是无懈可击.
且要改非标前要先按标准做出来验证, 有点套是吧!

Modbus General Function List

0x01 Read Coils
0x02 Read Discrete Inputs
0x03 Read Holding Registers
0x05 Write Single Coil
0x06 Write Single Register
0x0F Write Multiple Coils
0x10 Write Multiple Registers

Function Code

Function 01 Read Colis

/*******************************************************************************
* Function Name  : xRtuCmd01(uint8_t ID, uint16_t address, uint16_t length)
* Description    : Read Coils
* Input          : ID, Address, Qty
* Output         : None
* Return         : Result 
*/   
RTUCmdError_t  xRtuCmd01(uint8_t ID, uint16_t address, uint16_t length)
{
	uint16_t i; 
    uint16_t uiCrcValue; 
	uint8_t  ucBuf[10];
	
	ucBuf[0]=ID;
	ucBuf[1]=0x01;	
	ucBuf[2]=(uint8_t)(address>>8);		
	ucBuf[3]=(uint8_t)(address & 0x00FF);	
	ucBuf[4]=(uint8_t)(length>>8);		
	ucBuf[5]=(uint8_t)(length & 0x00FF);		
    /* Append CRC16 to output buffer */
    uiCrcValue  = uiRtuCRC16( ucBuf, 6 );  
    ucBuf[6]= (uint8_t)(uiCrcValue & 0x00FF); 
    ucBuf[7]= (uint8_t)(uiCrcValue >>8);  

	while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );	
	ucUARTByteRecevied = FALSE;
	RX1_BufferIndex = 0; 

	USART1_TX_Length = 8;	
	for( i=0; i<USART1_TX_Length; i++) { USART1_TX_Buffer[i] = ucBuf[i]; }

	USART1_TX_Busy = BUSY;
	USART1->CR1 |=  USART_CR1_TXEIE; 

    return( xRtuReplyCheck( ucBuf[0], ucBuf[1] ));
}

Function 02 Read Descrite Inputs

/*******************************************************************************
* Function Name  : xRtuCmd02(uint8_t ID, uint16_t address, uint16_t length)
* Description    : Read Discrete Inputs
* Input          : ID, Address, Qty
* Output         : None
* Return         : Result 
*/  
RTUCmdError_t  xRtuCmd02(uint8_t ID, uint16_t address, uint16_t length)
{
	uint16_t i; 
    uint16_t uiCrcValue; 
	uint8_t  ucBuf[10];
	
	ucBuf[0]= ID;
	ucBuf[1]= 2;	
	ucBuf[2]= (uint8_t)(address>>8);		
	ucBuf[3]= (uint8_t)(address & 0x00FF);	
	ucBuf[4]= (uint8_t)(length>>8);		
	ucBuf[5]= (uint8_t)(length & 0x00FF);		
    /* Append CRC16 to output buffer */
    uiCrcValue  = uiRtuCRC16( ucBuf, 6 );  
    ucBuf[6]= (uint8_t)(uiCrcValue & 0x00FF); 
    ucBuf[7]= (uint8_t)(uiCrcValue >>8);  

	while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );	
	ucUARTByteRecevied = FALSE;
	RX1_BufferIndex = 0; 

	USART1_TX_Length = 8;	
	for( i=0; i<USART1_TX_Length; i++) { USART1_TX_Buffer[i] = ucBuf[i]; }

	USART1_TX_Busy = BUSY;
	USART1->CR1 |=  USART_CR1_TXEIE; 

    return( xRtuReplyCheck( ucBuf[0], ucBuf[1] ));
}

Function 05 Write Single Coil

/*******************************************************************************
* Function Name  : xRtuCmd05(uint8_t ID, uint16_t address, CtrlType_t Cmd)
* Description    : Write Single Coil
* Input          : ID, Address, Cmd ON/OFF
* Output         : None
* Return         : Result 
*/  
RTUCmdError_t xRtuCmd05(uint8_t ID, uint16_t address, CtrlType_t Cmd)
{
	uint16_t 		i = 0; 
    uint16_t 		uiCrcValue = 0; 
	uint8_t  		ucBuf[10];

	ucBuf[0]= ID;                               // Slave ID
	ucBuf[1]=  5;	                            // Func
	ucBuf[2]= (uint8_t)(address>>8);	        // Address Hi	
	ucBuf[3]= (uint8_t)(address & 0x00FF);	    // address Lo
	ucBuf[4]= 0x00;		                        // Cmd Hi
	ucBuf[5]= 0x00;	                            // Cmd Lo
    if( ON == Cmd ) { ucBuf[4]=0xFF;  }
    /* Append CRC16 to output buffer */
    uiCrcValue  = uiRtuCRC16( ucBuf, 6 );  		
    ucBuf[6]= (uint8_t)(uiCrcValue & 0x00FF);   // CRC Lo
    ucBuf[7]= (uint8_t)(uiCrcValue >>8);        // CRC Hi

	// Make sure TX Completed before new command 
	while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );	
	ucUARTByteRecevied = FALSE;
	RX1_BufferIndex = 0; 
	// Copy Data to TX Buffer 
	USART1_TX_Length = 8;	
	for( i=0; i < USART1_TX_Length; i++ ) { USART1_TX_Buffer[i] = ucBuf[i]; }
    // Active TX Transfer by Enable TXE 
	USART1_TX_Busy = BUSY;
	USART1->CR1 |=  USART_CR1_TXEIE; 	
	
    return( xRtuReplyCheck( ucBuf[0], ucBuf[1] ));
}

Function 15 Write Multiple Coils

/*******************************************************************************
* Function Name  : xRtuCmd05(uint8_t ID, uint16_t address, CtrlType_t Cmd)
* Description    : Write Single Coil
* Input          : ID, Address, Cmd ON/OFF
* Output         : None
* Return         : Result 
*/  
RTUCmdError_t xRtuCmd15(uint8_t ID,uint16_t address, uint16_t uiQty,uint16_t uiCmd)
{
	uint16_t 		i = 0; 
    uint16_t 		uiCrcValue = 0; 
	uint8_t  		ucBuf[12];

	ucBuf[0]= ID;                              // Slave ID
	ucBuf[1]= 15;	                           // Func 
	ucBuf[2]=(uint8_t)(address>>8);		       // Address Hi	
	ucBuf[3]=(uint8_t)(address & 0x00FF);	   // address Lo
	ucBuf[4]=(uint8_t)(uiQty>>8);		       // Qty Hi
	ucBuf[5]=(uint8_t)(uiQty & 0x00FF);		   // Qty Lo
    ucBuf[6]= 2; 	                           // Cmd Byte Count
    ucBuf[7]= (uint8_t)(uiCmd & 0x00FF);       // Cmd Hi
    ucBuf[8]= (uint8_t)(uiCmd >>8);  	       // Cmd Lo
    /* Append CRC16 to output buffer */
    uiCrcValue  = uiRtuCRC16( ucBuf, 9 );  
    ucBuf[9] = (uint8_t)(uiCrcValue & 0x00FF); // CRC Lo 
    ucBuf[10]= (uint8_t)(uiCrcValue >>8);      // CRC Hi

	// Make sure TX Completed before new command 
	while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );	
	ucUARTByteRecevied = FALSE;
	RX1_BufferIndex = 0; 
	// Copy Data to TX Buffer 
	USART1_TX_Length = 11;	
	for( i=0; i < USART1_TX_Length; i++ ) { USART1_TX_Buffer[i] = ucBuf[i]; }
    // Active TX Transfer by Enable TXE & SoftwareFlag=BUSY
	USART1_TX_Busy = BUSY;
	USART1->CR1 |=  USART_CR1_TXEIE; 	
	
    return( xRtuReplyCheck( ucBuf[0], ucBuf[1] ));
}

说明:

  1. 参考文件 Modbus Protocol
  2. 只实作Function 1,2,5,15, 纯粹是确认. 其他 3, 16 等有需要再加.
  3. Function 1,2,5,15,动作重复性高, 可以再分出 子函数, 降低大小
  4. 为什么画蛇添足, 不直接把数据建到 TX Buffer 要转一次呢?
    主要是考虑之后要加入项目时, 在 USART传送过程中可以先准备数据.
  5. 码只有发送前的一半, 纯粹是怕自己忘记, 方便对照 Modbus 文件.
  6. 发送后接收, 就跟 Slave 是对照的, 直接看 Slave Code 就好了

非标 Modbus-RTU Master

这千岛湖逛的时候拍的照! 现在就想说”这去她X工作!”
在这里插入图片描述

思路:

  1. 只动 Write 指令
  2. 似是而非: 故意却似 BUG
  3. CRC16是基础, 绝对不能动, 一动指定被抓包
  4. 所以这码绝对不能放上来…

Function List

0x05 Write Single Coil

0x06 Write Single Register

0x0F Write Multiple Coils

0x10 Write Multiple Registers

Related information

<笔记>天才脑袋比不上烂笔头, 写给自己看, 自用资料。
档案取自互联网!如有侵权或不适用情形, 请联系移除!
#Modbus-RTU

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值