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] ));
}
说明:
- 参考文件 Modbus Protocol
- 只实作Function 1,2,5,15, 纯粹是确认. 其他 3, 16 等有需要再加.
- Function 1,2,5,15,动作重复性高, 可以再分出 子函数, 降低大小
- 为什么画蛇添足, 不直接把数据建到 TX Buffer 要转一次呢?
主要是考虑之后要加入项目时, 在 USART传送过程中可以先准备数据. - 码只有发送前的一半, 纯粹是怕自己忘记, 方便对照 Modbus 文件.
- 发送后接收, 就跟 Slave 是对照的, 直接看 Slave Code 就好了
非标 Modbus-RTU Master
这千岛湖逛的时候拍的照! 现在就想说”这去她X工作!”

思路:
- 只动 Write 指令
- 似是而非: 故意却似 BUG
- CRC16是基础, 绝对不能动, 一动指定被抓包
- 所以这码绝对不能放上来…
Function List
0x05 Write Single Coil
0x06 Write Single Register
0x0F Write Multiple Coils
0x10 Write Multiple Registers
Related information
<笔记>天才脑袋比不上烂笔头, 写给自己看, 自用资料。
档案取自互联网!如有侵权或不适用情形, 请联系移除!
#Modbus-RTU
非标Modbus-RTU主站开发


2076

被折叠的 条评论
为什么被折叠?



