技术标签: 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文库
文章浏览阅读1k次,点赞20次,收藏22次。采用servlet+jsp+jdbc+mysql的技术以及mvc模式进行项目开发,本次开发的内容主要以实现CRUD核心功能为主的学生成绩管理系统,前端采用jquery+javascript+jstl进行数据传输以及处理,bootstrap写界面。_基于java的学生成绩管理系统的设计与实现
文章浏览阅读1.5k次。相关技术IO虚拟化简介全虚拟化通过VMM来模拟IO设备实现,VMM截获GuestOS的IO请求,通过软件模拟真实的硬件。VMM必须处理所有虚机的IO请求,然后将所有的IO情况序列化为可以被底层硬件处理的单一IO流。好处是GuestOS不需要考虑硬件设备的情况。问题是效率相对较低。例如 qemu。一个完整的数据包从虚拟机到物理机的路径是:虚拟机--QEMU虚拟网卡--虚拟化层--内核网桥--物理网卡..._qemu sr-iov
文章浏览阅读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 )
文章浏览阅读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
文章浏览阅读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:
文章浏览阅读1.8k次,点赞3次,收藏26次。EMC原理-传导(共模、差模)与辐射(近场、远场)详解_电路直角emc
文章浏览阅读106次。DCL单例模式【小城贝尔】私有默认构造器,静态方法调实例。加入线程同步锁,双重检查上边过。指令重排风险在,懒汉前边vola在。package concurrently.HappenBefore;public class DoubleCheakingLocking { //静态属性 private volatile static DoubleCheakingLocki...
文章浏览阅读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
文章浏览阅读389次。毕业3年,能力相仿、技术领域一样的2个程序员,准备跳槽到同一家公司,最后,一个谈下了20k,一个拿着17k。为什么薪资相差3k?因为:“谈判”。有程序员会来问:Python面试时,明明给不到,还一直问我的期望薪资,有什么用???接了offer以后,对薪资还是有些不满意,该怎么和hr说啊?挂出的岗位薪资是15-20k,提17k有问题吗???期望薪资 vs 岗位成本怎么理解15K~20..._hr报的薪资是17k太低了
文章浏览阅读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...
文章浏览阅读452次。由于多径和移动台运动等影响因素,使得移动信道对传输信号在时间、频率和角度上造成了色散,如时间色散、频率色散、角度色散等等,因此多径信道的特性对通信质量有着至关重要的影响,而多径信道的包络统计特性成为我们研究的焦点。根据不同无线环境,接收信号包络一般服从几种典型分布,如瑞利分布、莱斯分布和Nakagami-m分布.在本文中,专门针对服从瑞利分布的多径信道进行模拟仿真,进一步加深对多径信道特性的了解.通常在离基站较远、反射物较多的地区,发射机和接收机之间没有直射波路径,存在大量反射波;表1 多径延时参数。
文章浏览阅读2.1k次,点赞3次,收藏5次。防抖():触发高频事件 N 秒后只会执行一次,如果 N 秒内事件再次触发,则会重新计时。类似王者荣耀的回城功能,你反复触发回城功能,那么只认最后一次,从最后一次触发开始计时。核心思想:每次事件触发就清除原来的定时器,建立新的定时器。使用apply或call调用传入的函数。函数内部支持使用 this 和 event 对象;应用:防抖常应用于用户进行搜索输入节约请求资源,触发事件时进行防抖只触发一次。实现:并发与并行的区别?并发是宏观概念,我分别有任务 A 和任务 B,在一段时间内通过任务间的切换完成了这_监测数组的时候可能触发多次 get/set,那么如何防止触发多次呢?