基于Freertos与lwip移植FreeModbusTcp协议_freertos+modbustcp-程序员宅基地

技术标签: LWIP  Freertos  arm开发  Freemodbus  

前言:

        本文是在已移植Freertos与lwip的基础项目上对FreeModbusTcp协议的移植步骤讲解,本文不涉及Modbus Tcp相关协议讲解,软硬件开发环境与lwip的移植步骤可参考我之前的一篇文章:基于FreeRTOS的N32G457VEL7之LWIP网络协议栈移植-程序员宅基地


1、获取FreeModbus源码包

下载路径:【免费】freemodbusV1.5&V1.6资源-CSDN文库

本例程是使用了freemodbusV1.6版本

2、将源码拷贝至项目文件夹目录下

①在项目文件夹下新建 freemodbus 文件夹,并在freemodbus 文件夹下新建 port文件夹;

②并将freemodbus源码目录下的modbus文件夹拷贝到freemodbus文件夹下。

3、将freemodbus-v1.6\demo\MCF5235TCP\port下的相关文件拷贝至port文件夹下。由于在上一步中移植的freemodbus\modbus\include文件夹下已存在mbconfig.h文件,所以此处的mbconfig.h文件可以不移植到项目中。

4、将freemodbus-v1.6\demo\MCF5235TCP下的demo.c文件拷贝至freemodbus\modbus下,并修改为mb_callback_tcp.c,同时新建mb_callback_tcp.h文件。

5、在工程中新建FREEMODBUS_TCP分组,并将相关文件添加到工程中。

6、添加freeModbus Tcp头文件到工程中

7、相应修改源代码
①在mbconfig.h中,使能Modbus Tcp,失能ASCII与RTU,同时失能线圈寄存器函数与分离寄存器函数(本例中只实现了输入寄存器函数与保持寄存器函数,所以将未实现的线圈寄存器函数与分离寄存器函数失能)。
/*! \brief If Modbus ASCII support is enabled. */
#define MB_ASCII_ENABLED                        (  0 )

/*! \brief If Modbus RTU support is enabled. */
#define MB_RTU_ENABLED                          (  0 )

/*! \brief If Modbus TCP support is enabled. */
#define MB_TCP_ENABLED                          (  1 )
/*! \brief If the <em>Read Coils</em> function should be enabled. */
#define MB_FUNC_READ_COILS_ENABLED              (  0 )

/*! \brief If the <em>Write Coils</em> function should be enabled. */
#define MB_FUNC_WRITE_COIL_ENABLED              (  0 )

/*! \brief If the <em>Write Multiple Coils</em> function should be enabled. */
#define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED    (  0 )

/*! \brief If the <em>Read Discrete Inputs</em> function should be enabled. */
#define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED    (  0 )
②在mbport.h中,添加port.h头文件,并声明xMBTCPPortEventInit,vMBTCPPortEventClose,xMBTCPPortEventPost,xMBTCPPortEventGet这些函数。
#include "port.h"

#ifndef _MB_PORT_H
#define _MB_PORT_H

#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif
/* ----------------------- Supporting functions -----------------------------*/
BOOL            xMBPortEventInit( void );

BOOL            xMBPortEventPost( eMBEventType eEvent );

BOOL            xMBPortEventGet(  /*@out@ */ eMBEventType * eEvent );

BOOL 			xMBTCPPortEventInit( void );

void 			vMBTCPPortEventClose( void );

BOOL 			xMBTCPPortEventPost( eMBEventType eEvent );

BOOL 			xMBTCPPortEventGet( eMBEventType *eEvent );
③、在port.h中声明接收发送ETH帧时的打印函数prvvMBTCPLogFrame,与临界区函数vMBPortEnterCritical,vMBPortExitCritical。
#define MB_TCP_DEBUG            1       /* Debug output in TCP module. */

#define ENTER_CRITICAL_SECTION( )   vMBPortEnterCritical()
#define EXIT_CRITICAL_SECTION( )    vMBPortExitCritical()
/* ----------------------- Type definitions ---------------------------------*/
/* ----------------------- Function prototypes ------------------------------*/
#ifdef MB_TCP_DEBUG
void            vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule,
                            const CHAR * szFmt, ... );
void            prvvMBTCPLogFrame( UCHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen );
#endif

void            vMBPortEnterCritical( void );
void            vMBPortExitCritical( void );
④、修改portevent.c文件如下,主要是实现了第②步中那些函数,同时删除了一些用不到的头文件。
/*
 * FreeModbus Libary: BARE Port
 * Copyright (C) 2006 Christian Walter <[email protected]>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File: $Id: portevent.c,v 1.1 2006/08/22 21:35:13 wolti Exp $
 */

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"

/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL     xEventInQueue;

static eMBEventType eTCPQueuedEvent ;
static BOOL         xTCPEventInQueue= FALSE ;

/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{
    xEventInQueue = FALSE;
    return TRUE;
}

BOOL
xMBPortEventPost( eMBEventType eEvent )
{
    xEventInQueue = TRUE;
    eQueuedEvent = eEvent;
    return TRUE;
}

BOOL
xMBPortEventGet( eMBEventType * eEvent )
{
    BOOL            xEventHappened = FALSE;

    if( xEventInQueue )
    {
        *eEvent = eQueuedEvent;
        xEventInQueue = FALSE;
        xEventHappened = TRUE;
    }
    return xEventHappened;
}



BOOL
xMBTCPPortEventInit( void )
{
    xTCPEventInQueue = FALSE;
    return TRUE ;
}

void
vMBTCPPortEventClose( void )
{
    xTCPEventInQueue = FALSE;
}

BOOL
xMBTCPPortEventPost( eMBEventType eEvent )
{
    xTCPEventInQueue = TRUE;
    eTCPQueuedEvent = eEvent;
    return TRUE;
}

BOOL
xMBTCPPortEventGet( eMBEventType *eEvent )
{
     if( xTCPEventInQueue )
        {
          *eEvent = eTCPQueuedEvent;
          xTCPEventInQueue = FALSE;
          return TRUE;
        }
    else
        {
           return FALSE  ;
        }
}
⑤、修改portother.c文件如下,主要是实现了第③步中的帧打印函数与临界区函数。
/*
 * FreeModbus Libary: lwIP Port
 * Copyright (C) 2006 Christian Walter <[email protected]>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File: $Id$
 */

/* ----------------------- System includes ----------------------------------*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include "port.h"
#include <FreeRTOS.h>
#include <task.h>
/* ----------------------- Defines ------------------------------------------*/
#define MB_FRAME_LOG_BUFSIZE    512

/* ----------------------- Start implementation -----------------------------*/

#ifdef MB_TCP_DEBUG
void
prvvMBTCPLogFrame( UCHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen )
{
    int             i;
    int             res = 0;
    int             iBufPos = 0;
    size_t          iBufLeft = MB_FRAME_LOG_BUFSIZE;
    static CHAR     arcBuffer[MB_FRAME_LOG_BUFSIZE];

    assert( pucFrame != NULL );

    for( i = 0; i < usFrameLen; i++ )
    {
        /* Print some additional frame information. */
        switch ( i )
        {
        case 0:
            /* TID = Transaction Identifier. */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, "| TID = " );
            break;
        case 2:
            /* PID = Protocol Identifier. */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | PID = " );
            break;
        case 4:
            /* Length */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | LEN = " );
            break;
        case 6:
            /* UID = Unit Identifier. */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | UID = " );
            break;
        case 7:
            /* MB Function Code. */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, "|| FUNC = " );
            break;
        case 8:
            /* MB PDU rest. */
            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | DATA = " );
            break;
        default:
            res = 0;
            break;
        }
        if( res == -1 )
        {
            break;
        }
        else
        {
            iBufPos += res;
            iBufLeft -= res;
        }

        /* Print the data. */
        res = snprintf( &arcBuffer[iBufPos], iBufLeft, "%02X", pucFrame[i] );
        if( res == -1 )
        {
            break;
        }
        else
        {
            iBufPos += res;
            iBufLeft -= res;
        }
    }

    if( res != -1 )
    {
        /* Append an end of frame string. */
        res = snprintf( &arcBuffer[iBufPos], iBufLeft, " |\r\n" );
        if( res != -1 )
        {
            vMBPortLog( MB_LOG_DEBUG, (CHAR *)pucMsg, "%s", arcBuffer );
        }
    }
}
#endif

void
vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule, const CHAR * szFmt, ... )
{
    va_list         args;
    static const char *arszLevel2Str[] = { "DEBUG", "INFO", "WARN", "ERROR" };

    ( void )printf( "%s: %s: ", arszLevel2Str[eLevel], szModule );
    va_start( args, szFmt );
    vprintf( szFmt, args );
    va_end( args );
}

void
vMBPortEnterCritical( void )
{
    taskENTER_CRITICAL(  );
}

void
vMBPortExitCritical( void )
{
    taskEXIT_CRITICAL(  );
}
⑥在porttcp.c中添加string.h头文件,修改vMBPortEventClose为vMBTCPPortEventClose。
/* ----------------------- System includes ----------------------------------*/
#include <stdio.h>
#include "string.h"
#include "port.h"
/* ----------------------- Prototypes ---------------------------------------*/
void            vMBTCPPortEventClose( void );
void            vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule,
                            const CHAR * szFmt, ... );
void
vMBTCPPortClose(  )
{
    /* Shutdown any open client sockets. */
    prvvMBPortReleaseClient( pxPCBClient );

    /* Shutdown or listening socket. */
    prvvMBPortReleaseClient( pxPCBListen );

    /* Release resources for the event queue. */
    vMBTCPPortEventClose( );
}
⑦、修改mb_callback_tcp.c文件如下,该文件主要是实现了输入寄存器与保持寄存器的具体实现。
/* ------------------------ System includes ------------------------------- */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

/* ------------------------ FreeModbus includes --------------------------- */
#include "mb.h"

/* ------------------------ Project includes ------------------------------ */
#include "mb_callback_tcp.h"


/* ----------------------- Static variables ------------------------------- */
static USHORT   usRegInputStart = S_REG_INPUT_START;
static USHORT   usRegInputBuf[S_REG_INPUT_NREGS];
static USHORT   usRegHoldingStart = S_REG_HOLDING_START;
static USHORT   usRegHoldingBuf[S_REG_HOLDING_NREGS];

static USHORT TempPara[10];
/* ------------------------ Static functions ------------------------------ */
/**
 * The callback method of the input function.
 * @param reg_addr Offset of the register address relative to the start address		
 * @return none
 */
static void  RegInputReadCallBack(uint16_t reg_addr)
{
	switch(reg_addr)
	{
        case 0:usRegInputBuf[reg_addr] = 0		;break;		
		case 1:usRegInputBuf[reg_addr] = 1		;break;		
        case 2:usRegInputBuf[reg_addr] = 2		;break;		
        case 3:usRegInputBuf[reg_addr] = 3		;break;		
        case 4:usRegInputBuf[reg_addr] = 4		;break;		
		case 5:usRegInputBuf[reg_addr] = 5		;break;		
		case 6:usRegInputBuf[reg_addr] = 6		;break;
        case 7:usRegInputBuf[reg_addr] = 7		;break;
        case 8:usRegInputBuf[reg_addr] = 8		;break;		
		case 9:usRegInputBuf[reg_addr] = 9		;break;		     	
        default:break;
	}
}

/**
 * The callback method of the read hold function.
 * @param reg_addr Offset of the register address relative to the start address		
 * @return none
 */
static void  RegHoldReadCallBack(uint16_t reg_addr)
{
	switch(reg_addr)
	{
        case 0:usRegHoldingBuf[reg_addr] = TempPara[0]		;break;		
		case 1:usRegHoldingBuf[reg_addr] = TempPara[1]		;break;		
        case 2:usRegHoldingBuf[reg_addr] = TempPara[2]		;break;		
        case 3:usRegHoldingBuf[reg_addr] = TempPara[3]	    ;break;		
        case 4:usRegHoldingBuf[reg_addr] = TempPara[4]		;break;		
		case 5:usRegHoldingBuf[reg_addr] = TempPara[5]		;break;		
		case 6:usRegHoldingBuf[reg_addr] = TempPara[6]		;break;
        case 7:usRegHoldingBuf[reg_addr] = TempPara[7]		;break;		
		case 8:usRegHoldingBuf[reg_addr] = TempPara[8]		;break;		
        case 9:usRegHoldingBuf[reg_addr] = TempPara[9]		;break;	     	
        default:break;
	}
}

/**
 * The callback method of the write hold function.
 * @param reg_addr Offset of the register address relative to the start address		
 * @return none
 */
static void  RegHoldWriteCallBack(uint16_t reg_addr)
{
	switch(reg_addr)
	{
        case 0:TempPara[0] = usRegHoldingBuf[reg_addr]      ;printf("TempPara[0] = %d\r\n",TempPara[0]);break;		
		case 1:TempPara[1] = usRegHoldingBuf[reg_addr]		;printf("TempPara[1] = %d\r\n",TempPara[1]);break;	
        case 2:TempPara[2] = usRegHoldingBuf[reg_addr]		;printf("TempPara[2] = %d\r\n",TempPara[2]);break;	
        case 3:TempPara[3] = usRegHoldingBuf[reg_addr]	    ;printf("TempPara[3] = %d\r\n",TempPara[3]);break;	
        case 4:TempPara[4] = usRegHoldingBuf[reg_addr]		;printf("TempPara[4] = %d\r\n",TempPara[4]);break;	
		case 5:TempPara[5] = usRegHoldingBuf[reg_addr]		;printf("TempPara[5] = %d\r\n",TempPara[5]);break;	
		case 6:TempPara[6] = usRegHoldingBuf[reg_addr]		;printf("TempPara[6] = %d\r\n",TempPara[6]);break;
        case 7:TempPara[7] = usRegHoldingBuf[reg_addr]		;printf("TempPara[7] = %d\r\n",TempPara[7]);break;	
		case 8:TempPara[8] = usRegHoldingBuf[reg_addr]		;printf("TempPara[8] = %d\r\n",TempPara[8]);break;	
        case 9:TempPara[9] = usRegHoldingBuf[reg_addr]		;printf("TempPara[9] = %d\r\n",TempPara[9]);break;    	
        default:break;
	}
}


/* ------------------------ Implementation -------------------------------- */
/**
 * Modbus slave input register callback function.
 * @param pucRegBuffer input register buffer	
 * @param usAddress input register address		
 * @param usNRegs input register number			
 * @return result
 */
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    /* it already plus one in modbus function method. */
    usAddress--;

    if( ( usAddress >= S_REG_INPUT_START )
        && ( usAddress + usNRegs <= S_REG_INPUT_START + S_REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        while( usNRegs > 0 )
        {
            RegInputReadCallBack(iRegIndex);
            *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}

/**
 * Modbus slave holding register callback function.	
 * @param pucRegBuffer holding register buffer	
 * @param usAddress holding register address	
 * @param usNRegs holding register number		
 * @param eMode read or write					
 * @return result
 */
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    /* it already plus one in modbus function method. */
    usAddress--;
    if( ( usAddress >= S_REG_HOLDING_START ) &&
        ( usAddress + usNRegs <= S_REG_HOLDING_START + S_REG_HOLDING_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegHoldingStart );
        switch ( eMode )
        {
            /* Pass current register values to the protocol stack. */
        case MB_REG_READ:
            while( usNRegs > 0 )
            {
                RegHoldReadCallBack(iRegIndex);
                *pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 );
                *pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF );
                iRegIndex++;
                usNRegs--;
            }
            break;

            /* Update current register values with new values from the
             * protocol stack. */
        case MB_REG_WRITE:
            while( usNRegs > 0 )
            {
                usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                RegHoldWriteCallBack(iRegIndex);
                iRegIndex++;
                usNRegs--;
            }
            break;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}

eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
    return MB_ENOREG;
}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    return MB_ENOREG;
}




⑧、修改mb_callback_tcp.h文件如下。
#ifndef    	USER_APP
#define 	USER_APP
/* ------------------------ FreeModbus includes --------------------------- */
#include "mb.h"


/* ------------------------ Defines --------------------------------------- */
#define S_COIL_START                  0         /*线圈寄存器起始地址*/
#define S_COIL_NCOILS                 10        /*线圈寄存器数量*/

#define S_DISCRETE_INPUT_START        10000		/*离散寄存器起始地址*/
#define S_DISCRETE_INPUT_NDISCRETES   10        /*离散寄存器数量*/

#define S_REG_INPUT_START             30000		/*输入寄存器起始地址*/
#define S_REG_INPUT_NREGS             10		/*输入寄存器数量*/

#define S_REG_HOLDING_START           40000		/*保持寄存器起始地址*/
#define S_REG_HOLDING_NREGS           10		/*保持寄存器数量*/


 eMBErrorCode    eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNRegs );
 eMBErrorCode    eMBRegHoldingCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs,eMBRegisterMode eMode);
 eMBErrorCode    eMBRegCoilsCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNCoils,eMBRegisterMode eMode);
 eMBErrorCode    eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNDiscrete );

#endif

⑨、修改main.c如下,板子IP为192.168.12.247,端口为502,电脑IP为192.168.12.245。

/*****************************************************************************
 * Copyright (c) 2019, Nations Technologies Inc.
 *
 * All rights reserved.
 * ****************************************************************************
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Nations' name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************/

/**
 * @file main.c
 * @author Nations
 * @version v1.0.0
 *
 * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
 */
#include <stdio.h>
#include "drv_log.h"
#include "drv_rcc.h"
#include "drv_log_segger.h"

#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "task.h"
#include "misc.h"

#include "lwip/netif.h"
#include "lwip/api.h"
#include "lwip/sockets.h"
#include "lwipopts.h"
#include "lwip_port.h"
#include "mb.h"

/** @addtogroup N32G45X_StdPeriph_Examples
 * @{
 */
int errno ;
void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName)
{
    printf("stack overflow\n");
}

void vApplicationMallocFailedHook(void)
{
    printf("malloc failed\n");
}
/** @addtogroup USART_Printf
 * @{
 */

/***********************************task init**********************************/
#define START_TASK_PRIO         osPriority_5      
#define START_STK_SIZE          ((unsigned short)128)      
TaskHandle_t StartThread_Handler;           
static void StartThread(void const * argument);     

#define LED_TASK_PRIO           osPriority_10         
#define LED_STK_SIZE            ((unsigned short)128)     
TaskHandle_t LedThread_Handler; 
static void LedThread(void const * argument);  

#define LWIP_DMEO_TASK_PRIO     osPriority_10         
#define LWIP_DMEO_STK_SIZE      ((unsigned short)2*128)     
TaskHandle_t LwipThread_Handler;
static void LwipThread(void const * argument);   
/***********************************task end***********************************/
//uint32_t PreviousWakeTime;

/**
 * @brief  Main program
 */
extern void test_tcp_server_init(void);
extern void test_tcp_client_init(void);
int main(void)
{
	//drv_SysClockInit_144MHZ();
    RCC_ClocksType clks;
	
	drv_log_init();
	drv_log_segger_Init();

    /* Output a message on Hyperterminal using printf function */
    RCC_GetClocksFreqValue(&clks);
    log_info("SYSCLK: %d\r\n", clks.SysclkFreq);
    log_info("HCLK: %d\r\n", clks.HclkFreq); 
    log_info("PCLK1: %d\r\n", clks.Pclk1Freq);
    log_info("PCLK2: %d\r\n", clks.Pclk2Freq);
    log_info("AdcPllClkFreq: %d\r\n", clks.AdcPllClkFreq);	
    log_info("AdcHclkFreq: %d\r\n", clks.AdcHclkFreq);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	/* Initialize all configured peripherals */
    osThreadDef(Start_Thread, StartThread, START_TASK_PRIO, 0, START_STK_SIZE);
    StartThread_Handler  = osThreadCreate(osThread(Start_Thread), NULL);

    /* Start scheduler */
	osKernelStart();	
		
    while (1){}
}

static void StartThread(void const * argument)
{	
	uint16_t u16Val = 0;
	UBaseType_t uxHighWaterMark;
	uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );  
	log_info("1---StartThread: uxHighWaterMark:%ld\r\n",uxHighWaterMark);	
		
	
	for(int i=0;i<5;i++)
	{
		osDelay(500);
		log_info("StartThread\r\n");
	}
	
	/* Initialize all configured peripherals */
	osThreadDef(Led_Thread, LedThread, LED_TASK_PRIO, 0, LED_STK_SIZE);
    LedThread_Handler  = osThreadCreate(osThread(Led_Thread), NULL);
	
    osThreadDef(Lwip_Thread, LwipThread, LWIP_DMEO_TASK_PRIO, 0, LWIP_DMEO_STK_SIZE);
    LwipThread_Handler  = osThreadCreate(osThread(Lwip_Thread), NULL);	
		
	u16Val = uxTaskGetNumberOfTasks();
	log_info("In all tasks:%d\r\n",u16Val);

	uxHighWaterMark = uxTaskGetStackHighWaterMark( LedThread_Handler );  
	log_info("1---LwipThread: uxHighWaterMark:%ld\r\n",uxHighWaterMark);
	
	uxHighWaterMark = uxTaskGetStackHighWaterMark( LwipThread_Handler );  
	log_info("2---LwipThread: uxHighWaterMark:%ld\r\n",uxHighWaterMark);

	uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );  
	log_info("0---StartThread: uxHighWaterMark:%ld\r\n",uxHighWaterMark);		
	
	vTaskDelete(xTaskGetCurrentTaskHandle());
}	

static void LedThread(void const * argument)
{
	for(int i=0;i<10;i++)
	{
		osDelay(1100);
		printf("LedThread is running\r\n");
		print_log("LedThread is running\r\n");
	}
	while(1){osDelay(1000);}	
}

static void LwipThread(void const * argument)
{	
    RCC_EnableAPB2PeriphClk(  RCC_APB2_PERIPH_AFIO  | RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_GPIOC
                            | RCC_APB2_PERIPH_GPIOD | RCC_APB2_PERIPH_GPIOE | RCC_APB2_PERIPH_GPIOF
                            | RCC_APB2_PERIPH_GPIOG ,
                            ENABLE);
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ETHMAC, ENABLE);
    if (lwip_port_init())
    {
        printf("LWIP Init Falied!\n");
        while (1)
            ;
    }
	
    log_info("LWIP Init Success!\n");
    //test_tcp_server_init();    
    //test_tcp_client_init();
	eMBTCPInit(0);
	eMBEnable();
    log_info("TCP Task Success!\n");	
	while(1)
	{
		eMBPoll();
		osDelay(50);
	}
}


8、编译下载测试:

在40005保持寄存器写入15

在40003保持寄存器写入13

读保持寄存器

读输入寄存器


至此移植测试完毕,通讯成功。后续我整理出该工程后,分享给大家。

本例程移植参考链接:

freemodbus modbus TCP 学习笔记_freemodbustcp-程序员宅基地

STM32F407ZET7+ETH+LWIP移植modbusTCP测试通过(带软件和freemodbusv1.6包)_stm32f407ETH资源-CSDN文库

STM32F407+LAN8720+LWIP移植freemodbusTCP.zip_freemodbustcp移植资源-CSDN文库

STM32F103移植FreeModbus同时实现ModbusRTU和ModbusTCP.zip_freemodbustcp移植资源-CSDN文库

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Dd_456456/article/details/136447080

智能推荐

基于Java学生成绩管理系统设计与实现(源码+部署文档+报告)_基于java的学生成绩管理系统的设计与实现-程序员宅基地

文章浏览阅读1k次,点赞20次,收藏22次。采用servlet+jsp+jdbc+mysql的技术以及mvc模式进行项目开发,本次开发的内容主要以实现CRUD核心功能为主的学生成绩管理系统,前端采用jquery+javascript+jstl进行数据传输以及处理,bootstrap写界面。_基于java的学生成绩管理系统的设计与实现

linux加载虚拟sriov网卡,网卡直通SR-IOV技术-程序员宅基地

文章浏览阅读1.5k次。相关技术IO虚拟化简介全虚拟化通过VMM来模拟IO设备实现,VMM截获GuestOS的IO请求,通过软件模拟真实的硬件。VMM必须处理所有虚机的IO请求,然后将所有的IO情况序列化为可以被底层硬件处理的单一IO流。好处是GuestOS不需要考虑硬件设备的情况。问题是效率相对较低。例如 qemu。一个完整的数据包从虚拟机到物理机的路径是:虚拟机--QEMU虚拟网卡--虚拟化层--内核网桥--物理网卡..._qemu sr-iov

查找算法练习题_关于顺序查找算法 在下面的线性表中 ( 15, 24, 32, 47, 50, 58, 62, 79-程序员宅基地

文章浏览阅读1.4w次,点赞2次,收藏10次。1、在对有二十个数据有序表作二分查找时有___________个结点的查找长度是4.2、用折半查找法的查找速度比用顺序查找法的查找速度_________. A 必然慢 B必然快 C速度相等 D 快慢不定3、写出从循环单链表中查找出最大值的算法.4、写出从循环单链表中查找出最小值的算法 .5、适合折半查找的表的存贮方式及元素排列要求为( ) A、 链..._关于顺序查找算法 在下面的线性表中 ( 15, 24, 32, 47, 50, 58, 62, 79, 83, 96 )

DAPP开发中Web3唤醒MetaMask签名数据+Java校验签名实现去中心化和中心化用户数据的鉴权_web3.eth.personal.sign-程序员宅基地

文章浏览阅读2.5w次,点赞6次,收藏17次。使用场景大多数用在DAPP中调用中心化数据或者操作某些中心化功能的时候通过DAPP调用MetaMask钱包对数据进行签名传递给后台,后台验证签名数据是否是否当前用户钱包地址签名的数据实现鉴权。一、DAPP端用Web3签名数据注:不同的web3版本签名代码有点差异1、0.26版本签名web3.personal.sign//参数1:要签名的数据//参数2:签名的钱包地址web3.personal.sign(web3.fromUtf8("Hello Dapp"), "0x4..._web3.eth.personal.sign

Unsupported JPEG process: SOF type 0xc3之jai_imageio-1_0_01-lib-windows-i586-jre.exe安装踩过的坑_java unsupported jpeg process:-程序员宅基地

文章浏览阅读852次。开门见山。本人这里用的是jai_imageio-1_0_01-lib-windows-i586-jre.exe。(他还有另外的一个版本jai_imageio-1_0_01-lib-windows-i586-jdk.exe)。这里正式开始,本人测试环境:Win10 64位JDK是用jdk1.8.0_191 32位。直接双击jai_imageio-1_0_01-lib-windows-i586-jre.exe进行安装,如果之前已经装个一次,则第二次就会是卸载过程,如果没有装过,则是安装过程。以下过程_java unsupported jpeg process:

EMC原理-传导(共模、差模)与辐射(近场、远场)详解_电路直角emc-程序员宅基地

文章浏览阅读1.8k次,点赞3次,收藏26次。EMC原理-传导(共模、差模)与辐射(近场、远场)详解_电路直角emc

随便推点

原 自学JVAVA---(71)--(内功心法【70】)DCL单例模式-程序员宅基地

文章浏览阅读106次。DCL单例模式【小城贝尔】私有默认构造器,静态方法调实例。加入线程同步锁,双重检查上边过。指令重排风险在,懒汉前边vola在。package concurrently.HappenBefore;public class DoubleCheakingLocking { //静态属性 private volatile static DoubleCheakingLocki...

linux 版本中 i386/i686/x86-64/pcc 等... 的区别_linux/386 x86_64-程序员宅基地

文章浏览阅读1.6k次。参考1:一.I386 为32位 x86 64位二.安装介质1. i386 适用于intel和AMD所有32位的cpu.以及via采用X86架构的32的cpu.intel平台包括8086,80286,80386,80486,奔腾系列(1.2.3.4)、赛扬系列,Pentium D系列 以及centrino P-M,core duo 等.2_linux/386 x86_64

Python面试中,羞于谈钱的你:17k就17k吧,事后你又后悔了_hr报的薪资是17k太低了-程序员宅基地

文章浏览阅读389次。毕业3年,能力相仿、技术领域一样的2个程序员,准备跳槽到同一家公司,最后,一个谈下了20k,一个拿着17k。为什么薪资相差3k?因为:“谈判”。有程序员会来问:Python面试时,明明给不到,还一直问我的期望薪资,有什么用???接了offer以后,对薪资还是有些不满意,该怎么和hr说啊?挂出的岗位薪资是15-20k,提17k有问题吗???期望薪资 vs 岗位成本怎么理解15K~20..._hr报的薪资是17k太低了

LCTF-2016-PWN100-程序员宅基地

文章浏览阅读215次。栈溢出。可以通过libcdb.com获取libc.so.6和对应的libc关键函数偏移。或者使用libc-database。#!/usr/bin/env pythonfrom pwn import *DEBUG = 1if DEBUG: context.log_level = 'debug' p = process('./pwn1003s4d...

【老生谈算法】matlab实现瑞利衰落信道仿真-程序员宅基地

文章浏览阅读452次。由于多径和移动台运动等影响因素,使得移动信道对传输信号在时间、频率和角度上造成了色散,如时间色散、频率色散、角度色散等等,因此多径信道的特性对通信质量有着至关重要的影响,而多径信道的包络统计特性成为我们研究的焦点。根据不同无线环境,接收信号包络一般服从几种典型分布,如瑞利分布、莱斯分布和Nakagami-m分布.在本文中,专门针对服从瑞利分布的多径信道进行模拟仿真,进一步加深对多径信道特性的了解.通常在离基站较远、反射物较多的地区,发射机和接收机之间没有直射波路径,存在大量反射波;表1 多径延时参数。

前端高频面试题及答案整理(二)_监测数组的时候可能触发多次 get/set,那么如何防止触发多次呢?-程序员宅基地

文章浏览阅读2.1k次,点赞3次,收藏5次。防抖():触发高频事件 N 秒后只会执行一次,如果 N 秒内事件再次触发,则会重新计时。类似王者荣耀的回城功能,你反复触发回城功能,那么只认最后一次,从最后一次触发开始计时。核心思想:每次事件触发就清除原来的定时器,建立新的定时器。使用apply或call调用传入的函数。函数内部支持使用 this 和 event 对象;应用:防抖常应用于用户进行搜索输入节约请求资源,触发事件时进行防抖只触发一次。实现:并发与并行的区别?并发是宏观概念,我分别有任务 A 和任务 B,在一段时间内通过任务间的切换完成了这_监测数组的时候可能触发多次 get/set,那么如何防止触发多次呢?

推荐文章

热门文章

相关标签