打印
[应用相关]

STM32驱动w5500移植FreeModbus实现ModbusTCP

[复制链接]
2169|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
首先我们下载FreeModbus源码,然后放到自己的工程中,新建一个MODBUS_TCP和PORT_TCP文件夹,然后将相关文件复制到里面,如下图所示:


然后修改porttcp中的代码:
首先定义一个数组用于接收数据:

static UCHAR    aucTCPBuf[MB_TCP_BUF_SIZE];           //接收缓冲区
1
然后在xMBTCPPortInit中初始化socket连接,然后监听端口。

BOOL
xMBTCPPortInit( USHORT usTCPPort )
{
    BOOL bOkay = FALSE;

    // 侦听端口 Modbus-TCP 端口
        socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);
        listen_tcp_socket(SOCK_TCP_PORT);

    bOkay = TRUE;
    return bOkay;
}


然后在xMBTCPPortSendResponse函数中发送数据

BOOL
xMBTCPPortSendResponse(const UCHAR * pucMBTCPFrame, USHORT usTCPLength )
{
        send_tcp_socket_data(SOCK_TCP_PORT,(UCHAR*)pucMBTCPFrame,usTCPLength);       
    return TRUE;
}


使用特权

评论回复
沙发
keaibukelian|  楼主 | 2021-7-1 17:34 | 只看该作者
然后在xMBPortTCPPool执行接收和其他操作

BOOL
xMBPortTCPPool( void )
{  
        unsigned short int us_rlen;
        unsigned char i;
        i=get_tcp_socket_state(SOCK_TCP_PORT);

        if(i==SOCK_ESTABLISHED_TCP)
        {
                if(get_tcp_socket_irq(SOCK_TCP_PORT) & Sn_IR_CON_TCP)                //查看中断有没有发生
                {
                        clear_tcp_socket_irq(SOCK_TCP_PORT, Sn_IR_CON_TCP);         /*清除接收中断标志位*/                                                        
                }
                us_rlen=get_tcp_rx_buffer_size(SOCK_TCP_PORT);                                 //获取接收到的数据字节                                                   /*定义len为已接收数据的长度*/
                if(us_rlen==0)                                                                                                //没有接收到数据
                        return FALSE;                                                                                        //返回
                else
                {
                        recv_tcp_socket_data(SOCK_TCP_PORT,aucTCPBuf,us_rlen);         //接收数据                                                                            /*接收来自Server的数据*/
                        printf("receive\r\n");
                        usTCPBufLen=us_rlen;
                }
                ( void )xMBPortEventPost( EV_FRAME_RECEIVED );                        //发送已接收到新数据到Modbus-TCP状态机
        }
        else if(i==SOCK_CLOSED_TCP)                                                                        //如果socket关闭
        {
                socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);//重新初始化
        }
        else if(i==SOCK_INIT_TCP)                                                                //如果socket初始化完毕,监听端口
        {
                listen_tcp_socket(SOCK_TCP_PORT);
        }
        else if(i==SOCK_CLOSE_WAIT_TCP)                                                        //如果socket等待关闭,关闭socket连接
        {
                close_tcp_socket(SOCK_TCP_PORT);
        }

        return TRUE;
}


使用特权

评论回复
板凳
keaibukelian|  楼主 | 2021-7-1 17:35 | 只看该作者
其次还要实现读线圈、写线圈、读离散输入、写保持寄存器、读保持寄存器、读输入寄存器等功能,如下:

#define REG_INPUT_START       0x0001        //输入寄存器起始地址
#define REG_INPUT_NREGS       8                        //输入寄存器数量

#define REG_HOLDING_START     0x0001        //保持寄存器起始地址
#define REG_HOLDING_NREGS     8                        //保持寄存器数量

#define REG_COILS_START       0x0001        //线圈起始地址
#define REG_COILS_SIZE        16                        //线圈数量

#define REG_DISCRETE_START    0x0001        //开关寄存器其实地址
#define REG_DISCRETE_SIZE     16                        //开关寄存器数量
//输入寄存器内容
uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
//保持寄存器内容               
uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007};                                       
//线圈状态
uint8_t ucRegCoilsBuf[REG_COILS_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
//离散寄存器内容
uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x01};

/****************************************************************************
* 名          称:eMBRegInputCB
* 功    能:读取输入寄存器,对应功能码是 04 eMBFuncReadInputRegister
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
*                                                usAddress: 寄存器地址
*                                                usNRegs: 要读取的寄存器个数
* 出口参数:
* 注          意:上位机发来的 帧格式是: SlaveAddr(1 Byte)+FuncCode(1 Byte)
*                                                                +StartAddrHiByte(1 Byte)+StartAddrLoByte(1 Byte)
*                                                                +LenAddrHiByte(1 Byte)+LenAddrLoByte(1 Byte)+
*                                                                +CRCAddrHiByte(1 Byte)+CRCAddrLoByte(1 Byte)
*                                                        3 区
****************************************************************************/
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 - REG_INPUT_START );
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}

/****************************************************************************
* 名          称:eMBRegHoldingCB
* 功    能:对应功能码有:06 写保持寄存器 eMBFuncWriteHoldingRegister
*                                                                                                        16 写多个保持寄存器 eMBFuncWriteMultipleHoldingRegister
*                                                                                                        03 读保持寄存器 eMBFuncReadHoldingRegister
*                                                                                                        23 读写多个保持寄存器 eMBFuncReadWriteMultipleHoldingRegister
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
*                                                usAddress: 寄存器地址
*                                                usNRegs: 要读写的寄存器个数
*                                                eMode: 功能码
* 出口参数:
* 注          意:4 区
****************************************************************************/
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
        eMBErrorCode    eStatus = MB_ENOERR;
        int             iRegIndex;


        if((usAddress >= REG_HOLDING_START)&&\
                ((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS)))
        {
                iRegIndex = (int)(usAddress - REG_HOLDING_START);
                switch(eMode)
                {                                       
                        case MB_REG_READ://读 MB_REG_READ = 0
                                while(usNRegs > 0)
                                {
                                        *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] >> 8);            
                                        *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] & 0xFF);
                                        iRegIndex++;
                                        usNRegs--;                                       
                                }                           
                        break;
                        case MB_REG_WRITE://写 MB_REG_WRITE = 0
                                while(usNRegs > 0)
                                {         
                                        usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                                        usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                                        iRegIndex++;
                                        usNRegs--;
                                }
                        break;                               
                }
        }
        else//错误
        {
                eStatus = MB_ENOREG;
        }       
       
        return eStatus;
}

/****************************************************************************
* 名          称:eMBRegCoilsCB
* 功    能:对应功能码有:01 读线圈 eMBFuncReadCoils
*                                                  05 写线圈 eMBFuncWriteCoil
*                                                  15 写多个线圈 eMBFuncWriteMultipleCoils
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
*                                                usAddress: 线圈地址
*                                                usNCoils: 要读写的线圈个数
*                                                eMode: 功能码
* 出口参数:
* 注          意:如继电器
*                                                0 区
****************************************************************************/
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
        eMBErrorCode    eStatus = MB_ENOERR;
        int             iRegIndex;
        u8 i;
        USHORT readNumber=usNCoils;
        USHORT coilValue=0x0000;
        if((usAddress >= REG_COILS_START)&&\
        ((usAddress+usNCoils) <= (REG_COILS_START + REG_COILS_SIZE)))
        {
                iRegIndex = (int)(usAddress + usNCoils-REG_COILS_START);
                switch(eMode)
                {                                       
                        case MB_REG_READ://读 MB_REG_READ = 0
                                for(i=0;i<usNCoils;i++)
                                {
                                        readNumber--;
                                        iRegIndex--;
                                        coilValue|=ucRegCoilsBuf[iRegIndex]<<readNumber;
                                }
                                if(usNCoils<=8)
                                {
                                        * pucRegBuffer=coilValue;
                                }
                                else
                                {
                                        * pucRegBuffer++ = (coilValue)&0x00ff;
                                        * pucRegBuffer++ = (coilValue>>8)&0x00ff;
                                }
                        break;                           
                        case MB_REG_WRITE://写 MB_REG_WRITE = 1
                                while(usNCoils > 0)
                                {         
                                        //                         usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                                        //           usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                                                iRegIndex++;
                                                usNCoils--;
                                }
                        break;
                }
        }
        else//错误
        {
                eStatus = MB_ENOREG;
        }       

        return eStatus;
}
/****************************************************************************
* 名          称:eMBRegDiscreteCB
* 功    能:读取离散寄存器,对应功能码有:02 读离散寄存器 eMBFuncReadDiscreteInputs
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
*                                                usAddress: 寄存器地址
*                                                usNDiscrete: 要读取的寄存器个数
* 出口参数:
* 注          意:1 区
****************************************************************************/
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
        eMBErrorCode    eStatus = MB_ENOERR;
        int             iRegIndex;
        u8 i;
        USHORT readNumber=usNDiscrete;
        USHORT coilValue=0x0000;
        iRegIndex = (int)(usAddress + usNDiscrete-REG_DISCRETE_START);
        if((usAddress >= REG_DISCRETE_START)&&\
        ((usAddress+usNDiscrete) <= (REG_DISCRETE_START + REG_DISCRETE_SIZE)))
        {
                for(i=0;i<usNDiscrete;i++)
                {
                        readNumber--;
                        iRegIndex--;
                        coilValue|=ucRegDiscreteBuf[iRegIndex]<<readNumber;
                }
                if(usNDiscrete<=8)
                {
                        * pucRegBuffer=coilValue;
                }
                else
                {
                        * pucRegBuffer++ = (coilValue)&0x00ff;
                        * pucRegBuffer++ = (coilValue>>8)&0x00ff;
                }
        }
        else
        {
                eStatus = MB_ENOREG;
        }
    return eStatus;
}



使用特权

评论回复
地板
胖胖考拉| | 2022-2-24 15:34 | 只看该作者
说实在的,理论讲得再好,都不如自己用这套理论做个实际可以通讯的工程分享给大家有说服力!
毕竟大家都在用行动默默的说着:重在看效果,而不是浮华的文字!!

使用特权

评论回复
5
帛灿灿| | 2023-9-29 08:03 | 只看该作者

共模电感一个以铁氧体为磁芯的共模干扰抑制器件

使用特权

评论回复
6
童雨竹| | 2023-9-29 11:02 | 只看该作者

测试方法包括负载测试、静态测试和动态测试等

使用特权

评论回复
7
Pulitzer| | 2023-9-29 12:05 | 只看该作者

还有另一种技术正在变得普遍

使用特权

评论回复
8
公羊子丹| | 2023-9-29 13:08 | 只看该作者

测试结果可能包括输出电压和电流、电压波浪、效率、负载能力等指标

使用特权

评论回复
9
公羊子丹| | 2023-9-29 14:01 | 只看该作者

器件整合的再紧凑都无法发挥最大的效率

使用特权

评论回复
10
Wordsworth| | 2023-9-29 15:04 | 只看该作者

达到抑制干扰的目的

使用特权

评论回复
11
Clyde011| | 2023-9-29 16:07 | 只看该作者

在动态测试过程中,测试员需要改变测试负载的值和频率,

使用特权

评论回复
12
万图| | 2023-9-29 18:03 | 只看该作者

共模电感的电感值可以用电桥来测量

使用特权

评论回复
13
Uriah| | 2023-9-29 19:06 | 只看该作者

单层板不具有固定孔

使用特权

评论回复
14
MessageRing| | 2023-9-30 18:44 | 只看该作者
这个可不可以用cubeMX生成啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

4166

帖子

5

粉丝