MODBUS文件包含 callback、modbus、port。
callback文件下有回调函数文件夹 mbcallback.c
#include "mb.h"
#include "includes.h"
/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4
/* ----------------------- Static variables ---------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
/* ----------------------- Defines --自保持寄存器-------------------------------*/
#define REG_HOLDING_START ( 0x3000 ) //起始地址,16位字宽,对应VB区
#define REG_HOLDING_NREGS ( 20 )
/* ----------------------- Static variables ---自保持寄存器---------------------*/
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
//*!
extern HOLD_REG_t Hold_Reg; //保持寄存器
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_INPUT_START )
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegInputStart );
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
/* Number of reception */
u16 MultiWriteNum = usNRegs;
/* 是否更新数据 holdreg 或者 */
USHORT *StartAddr;
// if(eMode == MB_REG_READ)
// {
// UpdataHoldReg();
// StartAddr = (USHORT *)&Hold_Reg;
// }
//
// if(eMode == MB_REG_WRITE)
// {
// StartAddr = (USHORT *)&Hold_Reg;
// }
if( ( usAddress >= REG_HOLDING_START )
&& ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = ( int )( usAddress - REG_HOLDING_START );
while( usNRegs > 0 )
{
if(MB_REG_READ == eMode){
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
// *pucRegBuffer++ = ( unsigned char )( StartAddr[iRegIndex] >> 8 );
// *pucRegBuffer++ = ( unsigned char )( StartAddr[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
else
{
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
// StartAddr[iRegIndex] = *pucRegBuffer++ << 8;
// StartAddr[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
}
/* if(MB_REG_WRITE == eMode)
eStatus = Set_num(usAddress);*/
if(MB_REG_WRITE == eMode)
{
}
// eStatus = Set_num(usAddress - 1,MultiWriteNum);
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
( void )pucRegBuffer;
( void )usAddress;
( void )usNCoils;
( void )eMode;
return MB_ENOREG;
}
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
( void )pucRegBuffer;
( void )usAddress;
( void )usNDiscrete;
return MB_ENOREG;
}
modbus下文件夹有 ascii、functions、include、rtu、tcp文件夹
mbrtu.c代码如下:
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbrtu.h"
#include "mbframe.h"
#include "mbport.h"
#include "mbcrc.h"
#include <includes.h>
/* !!! 满足RTU 多从机 2018/9/20 15:59:14 */
void xMBPortEventInit_new(MB_RTU_DCB *const pMBRTU)
{
pMBRTU->xEventInQueue = FALSE;
}
void xMBPortEventPost_new(MB_RTU_DCB *const pMBRTU,eMBEventType eEvent )
{
pMBRTU->xEventInQueue = TRUE;
pMBRTU->eQueuedEvent = eEvent;
}
BOOL xMBPortEventGet_new(MB_RTU_DCB *const pMBRTU,eMBEventType * eEvent)
{
if(pMBRTU->xEventInQueue){
*eEvent = pMBRTU->eQueuedEvent;
pMBRTU->xEventInQueue = FALSE;
return TRUE;
}
else
return FALSE;
}
void xMBRTUReceiveFSM(MB_RTU_DCB *const pMBRTU)
{
UCHAR ucByte;
/* Always read the character. */
pMBRTU->ucPort->pvMBPortSerialGetByte( ( UCHAR * ) & ucByte );
switch ( pMBRTU->eRcvState )
{
/* If we have received a character in the init state we have to
* wait until the frame is finished.
*/
case STATE_RX_INIT:
pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
break;
/* In the error state we wait until all characters in the
* damaged frame are transmitted.
*/
case STATE_RX_ERROR:
pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
break;
/* In the idle state we wait for a new character. If a character
* is received the t1.5 and t3.5 timers are started and the
* receiver is in the state STATE_RX_RECEIVCE.
*/
case STATE_RX_IDLE:
pMBRTU->ucBufferCount = 0;
pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] = ucByte;
pMBRTU->eRcvState = STATE_RX_RCV;
/* Enable t3.5 timers. */
pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
break;
/* We are currently receiving a frame. Reset the timer after
* every character received. If more than the maximum possible
* number of bytes in a modbus frame is received the frame is
* ignored.
*/
case STATE_RX_RCV:
if( pMBRTU->ucBufferCount < MB_SER_PDU_SIZE_MAX )
{
pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] = ucByte;
}
else
{
pMBRTU->eRcvState = STATE_RX_ERROR;
}
pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
break;
}
}
void xMBRTUTransmitFSM(MB_RTU_DCB *const pMBRTU)
{
switch ( pMBRTU->eSndState )
{
/* We should not get a transmitter event if the transmitter is in
* idle state. */
case STATE_TX_IDLE:
/* enable receiver/disable transmitter. */
pMBRTU->ucPort->pvMBPortSerialEnable( TRUE, FALSE );
break;
case STATE_TX_XMIT:
/* check if we are finished. */
if( pMBRTU->ucBufferCount != 0 )
{
pMBRTU->ucPort->pvMBPortSerialPutByte( ( CHAR )*pMBRTU->pucBuffer );
pMBRTU->pucBuffer++; /* next byte in sendbuffer. */
pMBRTU->ucBufferCount--;
}
else
{
xMBPortEventPost_new(pMBRTU,EV_FRAME_SENT );
/* Disable transmitter. This prevents another transmit buffer
* empty interrupt. */
pMBRTU->ucPort->pvMBPortSerialEnable( TRUE, FALSE );
pMBRTU->eSndState = STATE_TX_IDLE;
}
break;
}
}
eMBErrorCode
eMBRTUReceive(MB_RTU_DCB *const pMBRTU, UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
{
eMBErrorCode eStatus= MB_ENOERR;
pMBRTU->ucPort->pvMBEnterCriticalSection();
/* Length and CRC check */
if( ( pMBRTU->ucBufferCount >= MB_SER_PDU_SIZE_MIN )
&& ( usMBCRC16( ( UCHAR * )pMBRTU->ucBuffer, pMBRTU->ucBufferCount ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = pMBRTU->ucBuffer[MB_SER_PDU_ADDR_OFF];
// /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
// * size of address field and CRC checksum.
// */
// *pusLength = ( USHORT )( pMBRTU->ucBufferCount - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
// /* Return the start of the Modbus PDU to the caller. */
// *pucFrame = ( UCHAR * ) & pMBRTU->ucBuffer[MB_SER_PDU_PDU_OFF];
}
else
{
eStatus = MB_EIO;
}
pMBRTU->ucPort->pvMBExitCriticalSection();
return eStatus;
}
eMBErrorCode
eMBRTUSend(MB_RTU_DCB *const pMBRTU,const UCHAR * pucFrame, USHORT usLength )
{
eMBErrorCode eStatus = MB_ENOERR;
USHORT usCRC16;
pMBRTU->ucPort->pvMBEnterCriticalSection();
/* Check if the receiver is still in idle state. If not we where to
* slow with processing the received frame and the master sent another
* frame on the network. We have to abort sending the frame.
*/
if( pMBRTU->eRcvState == STATE_RX_IDLE )
{
/* First byte before the Modbus-PDU is the slave address. */
pMBRTU->pucBuffer = ( UCHAR * ) pucFrame - 1;
pMBRTU->ucBufferCount = 1;
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
pMBRTU->pucBuffer[MB_SER_PDU_ADDR_OFF] = pMBRTU->ucMBAddress;
pMBRTU->ucBufferCount += usLength;
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
usCRC16 = usMBCRC16( ( UCHAR * ) pMBRTU->pucBuffer, pMBRTU->ucBufferCount );
pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] =