AT32的freertos下modbus TCP移植

1.准备模板

打开雅特力官网,也就是带有LwIP的示例。

下载官方源码:modbus

2.移植

我这里是在这里新建两个文件夹,分别是modbus与port,这个任意,只需要将必要的文件加入项目即可。

将源码中的modbus这些都移植过来,分别是实现,头文件、以及tcp相关的文件。其余的就不需要了

port文件夹里为:源码->demo->MCF5235TCP->port。

接下来将这些文件加入工程。加入头文件

编译后,发现有12个错误

3.依次解决:

1.打开mbconfig.h

确保,我是本来就这样,所以可能就只有12个错误,如果不是这样可能之前编译的错误更多。

2.打开port.h

这里我就关闭tcp_debug了。

3.打开portevent.c

没有定义,自己定义一下,然后这里的sys_mbox_ne()这个函数定义已经发生了改变。按照途中修改,后续报警的xMailBox加上&符号,

4.打开portother.c

删掉多余的这个三个

编译,发现还有五个错误

1.打开porttcp.c

报错说没有memcpy,那么我们加入头文件

还有这个错误,我们ctrl+h寻找,发现定义在portother.c文件里

复制并放在port.h中:

2.突然又发现少个宏定义,很离谱,我之前移植的时候没有少过

是这个宏

拷贝,并放到mbconfig.h文件中:

#ifndef MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS
#define MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS    ( 0 )
#endif

不过我记得我之前没有这个问题。

再次编译:

我出现了以下五个错误

我的main.c为:

/***************************************************************************** @file     main.c* @version  v2.0.6* @date     2022-03-11* @brief    main program***************************************************************************                       Copyright notice & Disclaimer** The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer.** THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.****************************************************************************/#include "at32f435_437_board.h"
#include "at32f435_437_clock.h"
#include "at32_emac.h"
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"#include "lwip/api.h"
#include "lwip/sys.h"
/*FreeModBus*/
#include "mb.h"
#include "mbutils.h"/* ----------------------- Defines ------------------------------------------*/
#define PROG                    "FreeModbus"//输入寄存器起始地址
#define REG_INPUT_START       0x0000
//输入寄存器数量
#define REG_INPUT_NREGS       8
//保持寄存器起始地址
#define REG_HOLDING_START     0x0000
//保持寄存器数量
#define REG_HOLDING_NREGS     8//线圈起始地址
#define REG_COILS_START       0x0000
//线圈数量
#define REG_COILS_SIZE        16//开关寄存器起始地址
#define REG_DISCRETE_START    0x0000
//开关寄存器数量
#define REG_DISCRETE_SIZE     16/* Private variables ---------------------------------------------------------*/
//输入寄存器内容
uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
//输入寄存器起始地址
uint16_t usRegInputStart = REG_INPUT_START;//保持寄存器内容
uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x147b,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
//保持寄存器起始地址
uint16_t usRegHoldingStart = REG_HOLDING_START;//线圈状态
uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x0f,0x02};
//开关输入状态
uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x0f,0x02};
/** @addtogroup UTILITIES_examples* @{*//*开始任务*/
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
/** @addtogroup FreeRTOS_demo* @{*/
extern void tcpip_stack_init(void);
extern void udpecho_init(void);
extern void tcpecho_init(void);TaskHandle_t network_handler;/* led3 task */
void network_task_function(void *pvParameters);/*** @brief  main function.* @param  none* @retval none*/
int main(void)
{nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);system_clock_config();/* init led2*/at32_led_init(LED2);/* init led3*/at32_led_init(LED3);/* init led4*/at32_led_init(LED4);/* init usart1 */uart_print_init(115200);/* enter critical */taskENTER_CRITICAL(); if(xTaskCreate((TaskFunction_t )network_task_function,     (const char*    )"Network_task",   (uint16_t       )512, (void*          )NULL,(UBaseType_t    )2,(TaskHandle_t*  )&network_handler) != pdPASS){printf("Network task could not be created as there was insufficient heap memory remaining.\r\n");}        else{printf("Network task was created successfully.\r\n");}/* exit critical */            taskEXIT_CRITICAL();      /* start scheduler */            vTaskStartScheduler(); }static void modbustcp_thread(void *arg)
{	LWIP_UNUSED_ARG(arg);eMBErrorCode    xStatus;eMBTCPInit( MB_TCP_PORT_USE_DEFAULT );eMBEnable();while(1){eMBPoll();vTaskDelay(5);}/* An error occured. Maybe we can restart. */
//		( void )eMBDisable(  );
//		( void )eMBClose(  );//}
}void modbustcp_init(void)
{sys_thread_new("modbustcp_thread", modbustcp_thread, NULL, 512, 4);
}/* led3 task function */
void network_task_function(void *pvParameters)
{while(emac_system_init() == ERROR);tcpip_stack_init();modbustcp_init();taskENTER_CRITICAL();           //进入临界区vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*** @}*/ /****************************************************************************
* 名	  称: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;/* it already plus one in modbus function method. */usAddress--;if( ( usAddress >= REG_INPUT_START )&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ){iRegIndex = ( int )( usAddress - usRegInputStart );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;/* it already plus one in modbus function method. */usAddress--;if((usAddress >= REG_HOLDING_START)&&\((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS))){iRegIndex = (int)(usAddress - usRegHoldingStart);switch(eMode){                                       case MB_REG_READ://读 MB_REG_READ = 0while(usNRegs > 0){*pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] >> 8);            *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] & 0xFF); iRegIndex++;usNRegs--;					}                            break;case MB_REG_WRITE://写 MB_REG_WRITE = 0while(usNRegs > 0){         usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;iRegIndex++;usNRegs--;}				}}else//错误{eStatus = MB_ENOREG;}	return eStatus;
}extern void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,UCHAR ucValue );
extern UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits );
/****************************************************************************
* 名	  称: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;//寄存器个数int16_t iNCoils = ( int16_t )usNCoils;//寄存器偏移量int16_t usBitOffset;/* it already plus one in modbus function method. */usAddress--;//检查寄存器是否在指定范围内if( ( (int16_t)usAddress >= REG_COILS_START ) &&( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) ){//计算寄存器偏移量usBitOffset = ( int16_t )( usAddress - REG_COILS_START );switch ( eMode ){//读操作case MB_REG_READ:while( iNCoils > 0 ){*pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );iNCoils -= 8;usBitOffset += 8;}break;//写操作case MB_REG_WRITE:while( iNCoils > 0 ){xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,( uint8_t )( iNCoils > 8 ? 8 : iNCoils ),*pucRegBuffer++ );iNCoils -= 8;}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;//操作寄存器个数int16_t iNDiscrete = ( int16_t )usNDiscrete;//偏移量uint16_t usBitOffset;/* it already plus one in modbus function method. */usAddress--; //判断寄存器时候再制定范围内if( ( (int16_t)usAddress >= REG_DISCRETE_START ) &&( usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE ) ){//获得偏移量usBitOffset = ( uint16_t )( usAddress - REG_DISCRETE_START );while( iNDiscrete > 0 ){*pucRegBuffer++ = xMBUtilGetBits( ucRegDiscreteBuf, usBitOffset,( uint8_t)( iNDiscrete > 8 ? 8 : iNDiscrete ) );iNDiscrete -= 8;usBitOffset += 8;}}else{eStatus = MB_ENOREG;}return eStatus;
}
/*** @}*/ 

    usAddress--;每一个都有这个是因为在modbus内部处理的时候,会将地址+1,从1开始。所以读数组的时候,会出现问题。

现在再次编译:

我们按照指示,打开mbutils.c

void __aeabi_assert(const char *expr, const char *file, int line) {// 打印断言失败信息(根据需要修改,如输出到串口、LCD等)// 断言失败后的处理(如停机、复位等)while (1);  // 死循环,防止程序继续运行// 或调用复位函数(根据芯片型号,如 NVIC_SystemReset())
}

加入后,编译通过,下载:

打开tcpip_stack_init();函数,发现绑定ip为172.31.96.101.我的eMBTCPInit( MB_TCP_PORT_USE_DEFAULT );为默认502.

发送数据:读取8个数据:收到回应。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92468.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis面试精讲 Day 16:Redis性能监控与分析工具

【Redis面试精讲 Day 16】Redis性能监控与分析工具 开篇 欢迎来到"Redis面试精讲"系列第16天&#xff0c;今天我们将深入探讨Redis性能监控与分析工具。在大型分布式系统中&#xff0c;Redis作为关键的数据存储和缓存组件&#xff0c;其性能指标直接影响整个系统的…

vue3+vue-flow制作简单可拖拽可增删改流程图

实现效果实现代码 准备工作 安装依赖 npm install vue-flow/core npm install vue-flow/minimap //小地图 npm install vue-flow/controls //自带的缩放、居中、加锁功能我这里只用到上述三个&#xff0c;还有其余的可根据实际情况配合官方文档使用。 npm install vue-flow/bac…

itextPdf获取pdf文件宽高不准确

正常情况下我们通过下面方式获取宽高PdfReader reader new PdfReader(file.getPath()); float width reader.getPageSize(1).getWidth(); float height reader.getPageSize(1).getHeight();但是这样获取的宽高是不准确的&#xff0c;永远都是 宽 > 高&#xff0c;也就是横…

NodeJs学习日志(2):windows安装使用node.js 安装express,suquelize,mysql,nodemon

windows安装使用node.js 安装express&#xff0c;suquelize&#xff0c;mysql&#xff0c;nodemon 系统是win10&#xff0c;默认已经安装好nodejs与npm包名作用expressWeb应用框架suquelize数据库ORMmysql数据库nodemon代码热重载安装express 添加express生成器 npm add expres…

VueCropper 图片裁剪组件在Vue项目中的实践应用

VueCropper 图片裁剪组件在Vue项目中的实践应用 1. 组件介绍 VueCropper 是一个基于 Vue.js 的图片裁剪组件&#xff0c;它提供了丰富的图片裁剪功能&#xff0c;包括&#xff1a; 图片缩放、旋转、移动固定比例裁剪高质量图片输出多种裁剪模式选择 2. 安装与引入 首先需要安装…

给同一个wordpress网站绑定多个域名的实现方法

在WordPress网站上绑定多个域名&#xff0c;可以通过以下几种方法实现&#xff1a; 1. 修改wp-config.php文件 在wp-config.php文件中&#xff0c;找到define(‘WP_DEBUG’, false);&#xff0c;在其下方添加以下代码&#xff1a; define(WP_SITEURL, http:// . $_SERVER[HT…

HarmonyOS分布式开发实战:打造跨设备协同应用

&#x1f4d6; 文章目录 第一章&#xff1a;HarmonyOS分布式架构揭秘第二章&#xff1a;跨设备协同的核心技术第三章&#xff1a;开发环境搭建与配置第四章&#xff1a;实战项目&#xff1a;智能家居控制系统第五章&#xff1a;数据同步与状态管理第六章&#xff1a;性能优化与…

用 Enigma Virtual Box 把 Qt 程序压成单文件 EXE——从编译、收集依赖到一键封包

关键词&#xff1a;Qt、windeployqt、Enigma Virtual Box、单文件、绿色软件 为什么要打成单文件&#xff1f; 传统做法&#xff1a;用 windeployqt 把依赖拷进 release 目录&#xff0c;发给用户一个文件夹&#xff0c;文件又多又乱。理想做法&#xff1a;把整个目录压成一个…

unity中实现选中人物脚下显示圆形标识且完美贴合复杂地形(如弹坑) 的效果

要实现人物脚下圆形 完美贴合复杂地形&#xff08;如弹坑&#xff09; 的效果&#xff0c;核心思路是 「动态生成贴合地面的 Mesh」 —— 即根据地面的高度场实时计算环形顶点的 Y 坐标&#xff0c;让每个顶点都 “贴” 在地面上。核心逻辑&#xff1a;确定环形范围&#xff1a…

引领GameFi 2.0新范式:D.Plan携手顶级财经媒体启动“龙珠创意秀”

在GameFi赛道寻求新突破的今天&#xff0c;一个名为Dragonverse Plan&#xff08;D.Plan&#xff09;的项目正以其独特的经济模型和宏大愿景&#xff0c;吸引着整个Web3社区的目光。据悉&#xff0c;D.Plan即将联合中文区顶级加密媒体金色财经与非小号&#xff08;Feixiaohao&a…

通信算法之307:fpga之时序图绘制

时序图绘制软件 一. 序言 在FPGA设计过程中&#xff0c;经常需要编写设计文档&#xff0c;其中&#xff0c;不可缺少的就是波形图的绘制&#xff0c;可以直接截取Vivado或者Modelsim平台实际仿真波形&#xff0c;但是往往由于信号杂乱无法凸显重点。因此&#xff0c;通过相应软…

计网学习笔记第3章 数据链路层(灰灰题库)

题目 11 单选题 下列说法正确的是______。 A. 路由器具有路由选择功能&#xff0c;交换机没有路由选择功能 B. 三层交换机具有路由选择功能&#xff0c;二层交换机没有路由选择功能 C. 三层交换机适合异构网络&#xff0c;二层交换机不适合异构网络 D. 路由器适合异构网络&…

SQL的LEFT JOIN优化

原sql&#xff0c;一个base表a,LEFT JOIN三个表抽数 SELECT ccu.*, ctr.*, om.*, of.* FROM ods.a ccu LEFT JOIN ods.b ctr ON ccu.coupon_code ctr.coupon_code AND ctr.is_deleted 0 LEFT JOIN ods.c om ON ctr.bill_code om.order_id AND om.deleted 0 LEFT JOIN ods.…

Redis 核心概念、命令详解与应用实践:从基础到分布式集成

目录 1. 认识 Redis 2. Redis 特性 2.1 操作内存 2.2 速度快 2.3 丰富的功能 2.4 简单稳定 2.5 客户端语言多 2.6 持久化 2.7 主从复制 2.8 高可用 和 分布式 2.9 单线程架构 2.9.1 引出单线程模型 2.9.2 单线程快的原因 2.10 Redis 和 MySQL 的特性对比 2.11 R…

【Day 18】Linux-DNS解析

目录 一、DNS概念 1、概念和作用 2、域名解析类型 3、 软件与服务 4、DNS核心概念 区域 记录 5、查询类型 6、分层结构 二、DNS操作 配置本机为DNS内网解析服务器 &#xff08;1&#xff09;修改主配置文件 &#xff08;2&#xff09;添加区域 正向解析区域&#xff1a; …

Python 中 OpenCV (cv2) 安装与使用介绍

Python 中 OpenCV (cv2) 安装与使用详细指南 OpenCV (Open Source Computer Vision Library) 是计算机视觉领域最流行的库之一。Python 通过 cv2 模块提供 OpenCV 的接口。 一、安装 OpenCV 方法 1&#xff1a;基础安装&#xff08;推荐&#xff09; # 安装核心包&#xff0…

微软WSUS替代方案

微软WSUS事件回顾2025年7月10日&#xff0c;微软最新确认Windows Server Update Services&#xff08;WSUS&#xff09;出现了问题&#xff0c;导致IT管理员无法正常同步和部署Windows更新。WSUS是允许管理员根据策略配置&#xff0c;将更新推送到特定计算机&#xff0c;并优化…

Minio 分布式集群安装配置

目录创建 mkdir -p /opt/minio/run && mkdir -p /etc/minio && mkdir -p /indata/disk_0/minio/datarun&#xff1a;启动脚本及二进制文件目录/etc/minio&#xff1a;配置文件目录data&#xff1a;数据存储目录下载 minio wget https://dl.min.io/server/minio…

Spring Boot + ShardingSphere 实现分库分表 + 读写分离实战

&#x1f680; Spring Boot ShardingSphere 实现分库分表 读写分离&#xff08;涵盖99%真实场景&#xff09; &#x1f3f7;️ 标签&#xff1a;ShardingSphere、分库分表、读写分离、MySQL 主从、Spring Boot 实战 分库分表 vs 读写分离 vs 主从配置与数据库高可用架构区别 …

将普通用户添加到 Docker 用户组

这样可以避免每次使用 Docker 命令时都需要 sudo。以下是具体步骤&#xff1a;1. 创建 Docker 用户组&#xff08;如果尚未存在&#xff09; 默认情况下&#xff0c;安装 Docker 时会自动创建 docker 用户组。可以通过以下命令检查&#xff1a; groupadd docker&#xff08;如果…