news 2026/4/18 10:20:03

FreeModbus+STM32F407IGT6标准库项目代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreeModbus+STM32F407IGT6标准库项目代码

FreeModbus移植的文章比较多了,分享一个移植好可用的代码。

代码连接:STM32F407IGT6移植FreeModbushttps://gitee.com/zhuzheshuai/STM32F407IGT6_FreeModbus

通信使用串口和RS485两种方式,RS485发送/接收使能引脚用的PH9,可以根据实际电路进行修改。原理图和代码。

#include "bsp_usart.h" void USART3_Init(uint32_t baud) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_StructInit(&GPIO_InitStructure); USART_StructInit(&USART_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART3, &USART_InitStructure); USART_Cmd(USART3, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART1_Init(uint32_t baud) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_StructInit(&GPIO_InitStructure); USART_StructInit(&USART_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void RS485_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOH, &GPIO_InitStructure); GPIO_WriteBit(GPIOH, GPIO_Pin_9, Bit_RESET); } int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); return ch; } int fgetc(FILE *f) { /* 等待串口1输入数据 */ while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(USART1); }

用了条件编译,如果Modbus通讯用的串口,注释 #define EN_RS485;如果用RS485需要修改对应串口引脚号和RS485的使能引脚。

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" /* ----------------------- User includes ----------------------------------*/ #include "bsp_usart.h" #define SLAVE_RS485_RECEIVE_MODE GPIO_WriteBit(GPIOH, GPIO_Pin_9, Bit_SET) #define SLAVE_RS485_SEND_MODE GPIO_WriteBit(GPIOH, GPIO_Pin_9, Bit_RESET) #define EN_RS485 /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR( void ); static void prvvUARTRxISR( void ); /* ----------------------- Start implementation -----------------------------*/ void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) { /* If xRXEnable enable serial receive interrupts. If xTxENable enable * transmitter empty interrupts. */ #ifdef EN_RS485 if(xRxEnable == TRUE) { SLAVE_RS485_RECEIVE_MODE; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); } else { SLAVE_RS485_SEND_MODE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); } if(xTxEnable == TRUE) { USART_ITConfig(USART3, USART_IT_TXE, ENABLE); } else { USART_ITConfig(USART3, USART_IT_TXE, DISABLE); } #else if(xRxEnable == TRUE) { USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } else { USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); } if(xTxEnable == TRUE) { USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } else { USART_ITConfig(USART1, USART_IT_TXE, DISABLE); } #endif } BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { #ifdef EN_RS485 USART3_Init((uint32_t)ulBaudRate); #else USART1_Init((uint32_t)ulBaudRate); #endif 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. */ #ifdef EN_RS485 SLAVE_RS485_SEND_MODE; USART_SendData(USART3, (uint16_t)ucByte); while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); SLAVE_RS485_RECEIVE_MODE; #else USART_SendData(USART1, (uint16_t)ucByte); #endif 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. */ #ifdef EN_RS485 *pucByte = (CHAR)USART_ReceiveData(USART3); #else *pucByte = (CHAR)USART_ReceiveData(USART1); #endif 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( ); } #ifdef EN_RS485 void USART3_IRQHandler(void) { if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { prvvUARTRxISR(); USART_ClearITPendingBit(USART3, USART_IT_RXNE); } if(USART_GetITStatus(USART3, USART_IT_ORE) != RESET) { USART_ClearITPendingBit(USART3, USART_IT_ORE); prvvUARTRxISR(); } if(USART_GetITStatus(USART3, USART_IT_TXE) != RESET) { prvvUARTTxReadyISR(); USART_ClearITPendingBit(USART3, USART_IT_TXE); } } #else void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { prvvUARTRxISR(); USART_ClearITPendingBit(USART1, USART_IT_RXNE); } if(USART_GetITStatus(USART1, USART_IT_ORE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_ORE); prvvUARTRxISR(); } if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { prvvUARTTxReadyISR(); USART_ClearITPendingBit(USART1, USART_IT_TXE); } } #endif

后续增加了FreeRTOS

测试的效果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 0:21:22

直线导轨限速受哪些因素影响?负载预压环境关联分析

“直线导轨的限速不是一个固定值&#xff0c;它受多种因素影响——这是很多客户容易忽略的点。作为台湾HIWIN集团正式授权专属经销商&#xff0c;深圳市海威机电有限公司今天就来分析影响直线导轨限速的三个核心因素&#xff1a;负载、预压、环境&#xff0c;帮你找到最适合的限…

作者头像 李华
网站建设 2026/4/18 6:30:37

Javaweb房产销售管理系统

可s我领取源码!JavaWeb 房产销售管理系统是一款专门为房地产销售企业设计的综合性管理平台&#xff0c;旨在提升房产销售流程的效率与透明度&#xff0c;实现房源、客户、销售团队等多方面的高效管理。借助 Java Web 技术&#xff0c;该系统能够为企业提供稳定、可靠且功能丰富…

作者头像 李华
网站建设 2026/4/18 6:31:07

8个AI论文工具,专科生轻松搞定毕业写作!

8个AI论文工具&#xff0c;专科生轻松搞定毕业写作&#xff01; AI 工具让论文写作不再难 对于专科生来说&#xff0c;毕业论文可能是大学生活中最令人头疼的任务之一。从选题到开题&#xff0c;再到撰写和降重&#xff0c;每一步都充满了挑战。而随着 AI 技术的不断发展&#…

作者头像 李华
网站建设 2026/4/18 5:32:52

蓝桥杯 嵌入式 客观题 [1000道]第二期 持续更新中

1. 在蓝桥杯嵌入式竞赛常用的CT117E-M4开发板上&#xff0c;为了控制LED灯&#xff08;LD1~LD8&#xff09;&#xff0c;使用了74HC573锁存器配合74LS138译码器进行片选。若要选通控制LED的锁存器&#xff08;通常连接在Y4&#xff09;&#xff0c;则74LS138的输入端 A2, A1, A…

作者头像 李华
网站建设 2026/4/18 8:39:12

【MongoDB实战】7.3 批量操作优化:BulkWrite

文章目录 7.3 批量操作优化:BulkWrite 前置准备 1. 环境要求 2. 基础连接代码 7.3.1 循环单条操作vs批量操作:性能差异对比 核心差异 实战性能对比(测试10000条插入) 典型输出结果(参考) 差异原因分析 7.3.2 BulkWrite实战:批量插入、更新、删除组合操作 核心语法 实战:…

作者头像 李华