技术标签: LWIP Freertos arm开发 Freemodbus
本文是在已移植Freertos与lwip的基础项目上对FreeModbusTcp协议的移植步骤讲解,本文不涉及Modbus Tcp相关协议讲解,软硬件开发环境与lwip的移植步骤可参考我之前的一篇文章:基于FreeRTOS的N32G457VEL7之LWIP网络协议栈移植-程序员宅基地
下载路径:【免费】freemodbusV1.5&V1.6资源-CSDN文库
本例程是使用了freemodbusV1.6版本
①在项目文件夹下新建 freemodbus 文件夹,并在freemodbus 文件夹下新建 port文件夹;
②并将freemodbus源码目录下的modbus文件夹拷贝到freemodbus文件夹下。
/*! \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 )
#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 );
#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 );
/*
* 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 ;
}
}
/*
* 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( );
}
/* ----------------------- 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( );
}
/* ------------------------ 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;
}
#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);
}
}
在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文库
文章浏览阅读451次。dev/mem: 物理内存的全镜像。可以用来访问物理内存。/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。调试嵌入式Linux内核时,可能需要查看某个内核变量的值。/dev/kmem正好提供了访问内核虚拟内存的途径。现在的内核大都默认禁用了/dev/kmem,打开的方法是在 make menuconfig中选中 device drivers --> ..._dev/mem 源码实现
文章浏览阅读7.1k次,点赞2次,收藏19次。vxe-table,一个小众但功能齐全并支持excel操作的vue表格组件_vxe-table
文章浏览阅读62次。参考:http://www.ruanyifeng.com/blog/2016/01/babel.htmlBabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item..._让开发环境支持bable
文章浏览阅读2.8k次,点赞6次,收藏29次。摘要:FPGA视频处理FIFO的典型应用,视频输入FIFO的作用,视频输出FIFO的作用,视频数据跨时钟域FIFO,视频缩放FIFO的作用_fpga 频分复用 视频
文章浏览阅读575次。【代码】R语言:设置工作路径为当前文件存储路径。_r语言设置工作目录到目标文件夹
文章浏览阅读452次。格式:background: linear-gradient(direction, color-stop1, color-stop2, ...);<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner>] ,]? &l..._background线性渐变
文章浏览阅读1k次,点赞26次,收藏8次。第十三届蓝桥杯青少年组python编程省赛真题一、题目要求(注:input()输入函数的括号中不允许添加任何信息)1、编程实现给定一个正整数N,输出正整数N中各数位最大的那个数字。例如:N=132,则输出3。2、输入输出输入描述:只有一行,输入一个正整数N输出描述:只有一行,输出正整数N中各数位最大的那个数字输入样例:
文章浏览阅读2.2k次。一个网络协议主要由以下三个要素组成:1.语法数据与控制信息的结构或格式,包括数据的组织方式、编码方式、信号电平的表示方式等。2.语义即需要发出何种控制信息,完成何种动作,以及做出何种应答,以实现数据交换的协调和差错处理。3.时序即事件实现顺序的详细说明,以实现速率匹配和排序。不完整理解:语法表示长什么样,语义表示能干什么,时序表示排序。转载于:https://blog.51cto.com/98..._网络协议三要素csdn
文章浏览阅读153次。主要的思想,将所有的系统都可以看作两部分,真正的数据log系统和各种各样的query engine所有的一致性由log系统来保证,其他各种query engine不需要考虑一致性,安全性,只需要不停的从log系统来同步数据,如果数据丢失或crash可以从log系统replay来恢复可以看出kafka系统在linkedin中的重要地位,不光是d..._the log: what every software engineer should know about real-time data's uni
文章浏览阅读746次。伟大是熬出来的 目录 前言 引言 时间熬成伟大:领导者要像狼一样坚忍 第一章 内圣外王——领导者的心态修炼 1. 天纵英才的自信心 2. 上天揽月的企图心 3. 誓不回头的决心 4. 宠辱不惊的平常心 5. 换位思考的同理心 6. 激情四射的热心 第二章 日清日高——领导者的高效能修炼 7. 积极主动,想到做到 8. 合理掌控自己的时间和生命 9. 制定目标,马..._当狼拖着受伤的右腿逃生时,右腿会成为前进的阻碍,它会毫不犹豫撕咬断自己的腿, 以
文章浏览阅读285次。在当今的大数据时代,人们对高速度和高带宽的需求越来越大,迫切希望有一种新型产品来作为高性能计算和数据中心的主要传输媒质,所以有源光缆(AOC)在这种环境下诞生了。有源光缆究竟是什么呢?应用在哪些领域,有什么优势呢?易天将为您解答!有源光缆(Active Optical Cables,简称AOC)是两端装有光收发器件的光纤线缆,主要构成部件分为光路和电路两部分。作为一种高性能计..._aoc 光缆
文章浏览阅读2.2k次。在“桌面”上按快捷键“Ctrl+R”,调出“运行”窗口。接着,在“打开”后的输入框中输入“Gpedit.msc”。并按“确定”按钮。如下图 找到“用户配置”下的“Windows设置”下的“Internet Explorer 维护”的“连接”,双击选择“自动浏览器配置”。如下图 选择“自动启动配置”,并在下面的“自动代理URL”中填写相应的PAC文件地址。如下..._設置proxy腳本