当前位置: 首页 > news >正文

公司网站开发费摊销大连建设安全网站

公司网站开发费摊销,大连建设安全网站,通辽网站建设培训,楼盘 东莞网站建设代码地址 STM32MODBUSRTU: stm32上的modbus工程 从站 FreeModbus是一个开源的Modbus通信协议栈实现。它允许开发者在各种平台上轻松地实现Modbus通信功能,包括串口和以太网。FreeMODBUS提供了用于从设备和主站通信的功能,支持Modbus RTU和Modbus TCP协…

代码地址

STM32MODBUSRTU: stm32上的modbus工程

从站

FreeModbus是一个开源的Modbus通信协议栈实现。它允许开发者在各种平台上轻松地实现Modbus通信功能,包括串口和以太网。FreeMODBUS提供了用于从设备和主站通信的功能,支持Modbus RTU和Modbus TCP协议。在工业控制和自动化领域广泛应用。

  FreeModBus可通过官方网站下载:FreeMODBUS

参考文章:FreeModbus RTU 从机Hal库裸机移植避坑指南 - Atul-8 - 博客园

1. STM32CubeMX 配置流程

我假设你已经学会使用stm32cubeMX点灯了;

1.1下载模式配置

1.2 定时器配置

为了实现一个1750us的超时计时定时器,其中计算过程如下,使用内部时钟8M,预分配399+1,及400/8m=50us,计数周期为34+1,也就是35*50us=1750us

1.3 串口配置

1.4 中断配置

关闭自动生成中断函数,因为需要在freemodbus源码里添加这两个函数。

2.库文件导入

2.1 .c文件汇总

2.2 .h文件汇总

2.3 demo文件选择

3. 移植流程

ok 完成上述步骤后, 你就可以开始正式的移植工作了:

主要需要移植的地方为: portserial.c && porttimer.c && demo.c

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\modbus\include\mbconfig.h

文件中将ASCII关闭

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\modbus\rtu\mbrtu.c

文件中有两处断言需要调整,我不清楚为什么,但是我的不修改会进入断言

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\modbus\port\portserial.c

代码如下:

/** FreeModbus Libary: BARE Port* Copyright (C) 2006 Christian Walter <wolti@sil.at>** 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$*/#include "port.h"/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "main.h"
#include "usart.h"
/* ----------------------- static functions ---------------------------------*/
static void prvvUARTTxReadyISR( void );
static void prvvUARTRxISR( void );extern UART_HandleTypeDef huart1;/* ----------------------- Start implementation -----------------------------*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/if (xRxEnable) {__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);} else {__HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE);}if (xTxEnable) {__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);} else {__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);}
}BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{MX_USART1_UART_Init();return TRUE;
}BOOL
xMBPortSerialPutByte( CHAR ucByte )
{/* Put a byte in the UARTs transmit buffer. This function is called* by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been* called. */USART1->DR = ucByte;return TRUE;
}BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{/* Return the byte in the UARTs receive buffer. This function is called* by the protocol stack after pxMBFrameCBByteReceived( ) has been called.*/*pucByte = (USART1->DR & (uint16_t)0x00FF);return TRUE;
}/* Create an interrupt handler for the transmit buffer empty interrupt* (or an equivalent) for your target processor. This function should then* call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that* a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character.*/
static void prvvUARTTxReadyISR( void )
{pxMBFrameCBTransmitterEmpty(  );
}/* Create an interrupt handler for the receive interrupt for your target* processor. This function should then call pxMBFrameCBByteReceived( ). The* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the* character.*/
static void prvvUARTRxISR( void )
{pxMBFrameCBByteReceived(  );
}void USART1_IRQHandler(void)
{if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)){__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);	prvvUARTRxISR();// __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);}if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE)){__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_TXE);			prvvUARTTxReadyISR();}
//    HAL_UART_IRQHandler(&huart1);
}

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\modbus\port\porttimer.c

代码如下:

/** FreeModbus Libary: BARE Port* Copyright (C) 2006 Christian Walter <wolti@sil.at>** 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$*//* ----------------------- Platform includes --------------------------------*/
#include "port.h"/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "main.h"
/* ----------------------- static functions ---------------------------------*/
static void prvvTIMERExpiredISR( void );extern TIM_HandleTypeDef htim4;
/* ----------------------- Start implementation -----------------------------*/static void MX_TIM4_Init(void)
{TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim4.Instance = TIM4;htim4.Init.Prescaler = 399;htim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.Period = 34;htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim4) != HAL_OK) {Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) {Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK) {Error_Handler();}
}BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{MX_TIM4_Init();__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_UPDATE);      __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE);					return TRUE;
}inline void
vMBPortTimersEnable(  )
{/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */__HAL_TIM_SET_COUNTER(&htim4, 0);__HAL_TIM_ENABLE(&htim4);
}inline void
vMBPortTimersDisable(  )
{/* Disable any pending timers. */__HAL_TIM_DISABLE(&htim4);
}/* Create an ISR which is called whenever the timer has expired. This function* must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that* the timer has expired.*/
static void prvvTIMERExpiredISR( void )
{( void )pxMBPortCBTimerExpired(  );
}void TIM4_IRQHandler(void)
{if(__HAL_TIM_GET_FLAG(&htim4, TIM_FLAG_UPDATE)){__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_UPDATE);prvvTIMERExpiredISR();}
}

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\modbus\demo.c

代码如下:这里是主要modbus栈需要维护的数据

/** FreeModbus Libary: BARE Demo Application* Copyright (C) 2006 Christian Walter <wolti@sil.at>** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program 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 General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA** File: $Id$*//* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4/* ----------------------- Static variables ---------------------------------*/
static USHORT   usRegInputStart = REG_INPUT_START;
static USHORT   usRegInputBuf[REG_INPUT_NREGS];// 十路输入寄存器
#define REG_INPUT_SIZE  10
uint16_t REG_INPUT_BUF[REG_INPUT_SIZE];// 十路保持寄存器
#define REG_HOLD_SIZE   10
uint16_t REG_HOLD_BUF[REG_HOLD_SIZE];// 十路线圈
#define REG_COILS_SIZE 10
uint8_t REG_COILS_BUF[REG_COILS_SIZE] = {1, 1, 1, 1, 0, 0, 0, 0, 1, 1};// 十路离散量
#define REG_DISC_SIZE  10
uint8_t REG_DISC_BUF[REG_DISC_SIZE] = {1,1,1,1,0,0,0,0,1,1};/* ----------------------- Start implementation -----------------------------*//// CMD4命令处理回调函数
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{USHORT usRegIndex = usAddress - 1;// 非法检测if ((usRegIndex + usNRegs) > REG_INPUT_SIZE) {return MB_ENOREG;}// 循环读取while (usNRegs > 0) {*pucRegBuffer++ = (unsigned char)(REG_INPUT_BUF[usRegIndex] >> 8);*pucRegBuffer++ = (unsigned char)(REG_INPUT_BUF[usRegIndex] & 0xFF);usRegIndex++;usNRegs--;}// 模拟输入寄存器被改变for (usRegIndex = 0; usRegIndex < REG_INPUT_SIZE; usRegIndex++) {REG_INPUT_BUF[usRegIndex]++;}return MB_ENOERR;
}/// CMD6、3、16命令处理回调函数
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,eMBRegisterMode eMode )
{USHORT usRegIndex = usAddress - 1;// 非法检测if ((usRegIndex + usNRegs) > REG_HOLD_SIZE) {return MB_ENOREG;}// 写寄存器if (eMode == MB_REG_WRITE) {while (usNRegs > 0) {REG_HOLD_BUF[usRegIndex] = (pucRegBuffer[0] << 8) | pucRegBuffer[1];pucRegBuffer += 2;usRegIndex++;usNRegs--;}}// 读寄存器else {while (usNRegs > 0) {*pucRegBuffer++ = (unsigned char)(REG_HOLD_BUF[usRegIndex] >> 8);*pucRegBuffer++ = (unsigned char)(REG_HOLD_BUF[usRegIndex] & 0xFF);usRegIndex++;usNRegs--;}}return MB_ENOERR;
}/// CMD1、5、15命令处理回调函数
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,eMBRegisterMode eMode )
{USHORT usRegIndex = usAddress - 1;UCHAR ucBits = 0;UCHAR ucState = 0;UCHAR ucLoops = 0;// 非法检测if ((usRegIndex + usNCoils) > REG_COILS_SIZE) {return MB_ENOREG;}if (eMode == MB_REG_WRITE) {ucLoops = (usNCoils - 1) / 8 + 1;while (ucLoops != 0) {ucState = *pucRegBuffer++;ucBits = 0;while (usNCoils != 0 && ucBits < 8) {REG_COILS_BUF[usRegIndex++] = (ucState >> ucBits) & 0X01;usNCoils--;ucBits++;}ucLoops--;}} else {ucLoops = (usNCoils - 1) / 8 + 1;while (ucLoops != 0) {ucState = 0;ucBits = 0;while (usNCoils != 0 && ucBits < 8) {if (REG_COILS_BUF[usRegIndex]) {ucState |= (1 << ucBits);}usNCoils--;usRegIndex++;ucBits++;}*pucRegBuffer++ = ucState;ucLoops--;}}return MB_ENOERR;
}/// CMD2命令处理回调函数
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{USHORT usRegIndex = usAddress - 1;UCHAR ucBits = 0;UCHAR ucState = 0;UCHAR ucLoops = 0;// 非法检测if ((usRegIndex + usNDiscrete) > REG_DISC_SIZE) {return MB_ENOREG;}ucLoops = (usNDiscrete - 1) / 8 + 1;while (ucLoops != 0) {ucState = 0;ucBits = 0;while (usNDiscrete != 0 && ucBits < 8) {if (REG_DISC_BUF[usRegIndex]) {ucState |= (1 << ucBits);}usNDiscrete--;usRegIndex++;ucBits++;}*pucRegBuffer++ = ucState;ucLoops--;}// 模拟离散量输入被改变for (usRegIndex = 0; usRegIndex < REG_DISC_SIZE; usRegIndex++) {REG_DISC_BUF[usRegIndex] = !REG_DISC_BUF[usRegIndex];}return MB_ENOERR;
}

E:\STM32CubeIDE\Workspace\FreeMODBUSRTUSlave\Core\Src\freertos.c

如下修改:

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "mb.h"
#include "mbport.h"
/* USER CODE END Includes */
/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the defaultTask thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */eMBInit(MB_RTU, 0x01, 0, 115200, MB_PAR_NONE); eMBEnable();for(;;){osDelay(1);eMBPoll();}/* USER CODE END StartDefaultTask */
}

4. 运行

好像带连续读取保护,这个我还没看,连续读取会失败

答:由于主频过低,导致使用中断的方式接收数据时,让处理时间稍微耗时,导致下一次数据露采,所以会有通讯失败的情况。

解决办法是提高主频,或者降低波特率。

主站

开源一套MODBUS主机代码(带讲解分析) – 电子创客营

源码地址:https://github.com/Derrick45/modbus-host

1. STM32CubeMX 配置流程

1.1配置系统模式

1.2配置定时器3

这个需要和port中代码保持一致

因为系统主频配置为64MHz

1.3配置串口1

1.4打开串口1和tim3中断

1.5 取消默认生成中断函数

因为后面代码需要自己实现

1.6 freeRTOS创建两个任务

一个默认任务,处理poll函数,一个任务做发送

1.7 配置系统时钟为64M

1.8 生成独立文件

2. 库文件导入

把源码文件放到modbus文件夹中

环境配置

3.移植流程

MODBUSRTUMaster\Core\Src\freertos.c

添加头文件

任务逻辑实现,默认任务处理poll

发送任务每一秒钟发送一次测试数据

4. 运行

http://www.dtcms.com/a/520548.html

相关文章:

  • 东莞教育网站建设浙江建设厅网站查询
  • 深圳公司网站设计企业虹口建设机械网站
  • Rust 所有权与借用机制深度剖析:原理、常见陷阱与实战优化
  • golang学习笔记:标准库encoding
  • Go语言实战教学:从一个混合定时任务调度器(Crontab)深入理解Go的并发、接口与工程哲学
  • 如何做原创小说网站广州商城网站制作网站
  • 让线程按指定顺序运行
  • 定制手机网站开发显示网站翻页代码
  • CoAlbum:多级缓存与性能对比
  • 【算法专题训练】27、树的层序遍历
  • 网站导入wordpress基层建设是哪个网站的
  • 第6章—手动移植创建STM32工程
  • Android Bluetooth 蓝牙通信
  • 简述一般网站开发方式广州三合一企业网站哪家好
  • 网站建设邀标函专业的外贸建站公司
  • C++ STL(标准模板库)深度解析:从基础到实践
  • 压缩与缓存调优实战指南:从0到1根治性能瓶颈(二)
  • Linux小课堂: SSH 配置文件详解之全局与局部 Config 文件的语义梳理与技术深化
  • 6-2〔O҉S҉C҉P҉ ◈ 研记〕❘ 客户端攻击▸利用WORD宏让客户端执行命令
  • 网站页面设计报价xampp做网站设置
  • 制作 网站 盈利怎么看网站到期时间
  • Qt6.10 | Qt Bluetooth 蓝牙
  • 网站自动化开发无极官方网站下载
  • 基于 docker compose 进行部署PandaWiki
  • 哪里建设网站设计服务
  • Python - 100天从新手到大师:第五十八天 Python中的并发编程(1-3)
  • C语言-动态内存分配
  • 多个PDF文档如何批量删除页眉处的多余信息
  • 网站服务器空间大小网站自适应宽度
  • 静态网站什么样做个简单的网站