FreeModbus 移植于STM32 实现Modbus RTU通信

发布者:dst2015最新更新时间:2016-10-05 来源: eefocus关键字:FreeModbus  移植  STM32  Modbus  RTU通信 手机看文章 扫描二维码
随时随地手机看文章
       毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像没有什么创新的地方,不过实现的方式绝对够创新的了...呵呵。自己写的开题报告中说了要有高级的通信功能。现在做以太网有点来不及了,CAN又感觉不搭调,硬件上也没准备。串口上跑Modbus感觉不错。本来西门子的S7-200就能跑Modbus,STM32-PLC当然也要支持Modbus 什么 组态软件,触摸屏都可以连上,不过FreeModbus只支持从机有点可惜,当然本来协议也不难而且也必要实现全协议栈。

Modbus中文协议.PDF

STM32移植FreeModbus的步骤:

首先去 http://www.freemodbus.org 下载文件 一定要是官方可靠的才行,我起先为了图方便网上随便下载了一个,结果白白浪费了一下午的时间

不知道是哪里被改动了。目前最新的版本是1.5。

http://115.com/file/bee0jrth#freemodbus-v1.5.0.zip 这是官方的可靠版本。

Demo 文件夹下都是官方移植好的其他芯片的版本。选BARE文件下的“赤裸”文件加入工程 同时添加全部的库文件,可参考下图

FreeModbus 移植于STM32 实现Modbus RTU通行 - java - stm32学习日志

需要移植修改的在 port 目录下
porttimer.c
中 xMBPortTimersInit( USHORT usTim1Timerout50us ) 负责配置一个 时基 ,vMBPortTimersEnable(  ) 启用这个时基。

比如执行

xMBPortTimersInit( 10000 );
vMBPortTimersEnable( );
for( ;; );
定时器按中断内 便会每500MS调用一次pxMBPortCBTimerExpired(  );同时你也要检测vMBPortTimersDisable( ) 是否可以可靠的关闭定时器。用仿真器 用LED灯都行的.


portother.c

//负责一个串口的配置 为了省事我只支持了波特率的修改

xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )

vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )负责控制串口【收/发】中断的禁止与使能

pxMBFrameCBByteReceived(  ); //在串口接收中断内调用 用于通讯侦测

pxMBFrameCBTransmitterEmpty(  ); //在串口发送中断内调用 用于告知完成了发送 发送缓冲为空

xMBPortSerialGetByte( CHAR * pucByte ) xMBPortSerialPutByte( CHAR ucByte ) 两个为 串口字节的收发

port.h

中定义了 全局中断的开关

#define ENTER_CRITICAL_SECTION( )   __set_PRIMASK(1) /*关中中断*/
#define EXIT_CRITICAL_SECTION( )    __set_PRIMASK(0) /*开总中断*/
__set_PRIMASK() 来源于 core_cm3.c 
这个头文件中添加了#include  assert() 断言宏 freeModbus的作者有点意思,为此不可以定义NDEBUG 。#include "stm32f10x.h" 似乎要添加到#include 的后边 不然编译会有问题。
port.C
添加了些Modbus协议栈与寄存器的接口函数 这个也要自己写。
FreeModbus 通过 
eMBRegInputCB eMBRegHoldingCB 
eMBRegCoilsCB eMBRegDiscreteCB 四个接口函数完成数据的读写操作
其中最常用的是这个 eMBRegHoldingCB 为了方便测试可以构造usRegHoldingBuf[]这样的一个数组进行读写调试。
上位机可以用诸如Modbus调试精灵这样的软件。

FreeModbus 移植于STM32 实现Modbus RTU通行 - java - stm32学习日志
// 寄存器的读写函数 支持的命令为读 0x03 和写0x06
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;
 u16 *PRT=(u16*)pucRegBuffer;
    if( ( usAddress >= REG_HOLDING_START ) && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegHoldingStart );
        switch ( eMode )
        {
        case MB_REG_READ:
            while( usNRegs > 0 )
            {
                *PRT++ = __REV16(usRegHoldingBuf[iRegIndex++]); //数据序转 REV16.W
//       *pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
//              *pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
//      iRegIndex++;
                usNRegs--;
            }
            break;
        case MB_REG_WRITE:
            while( usNRegs > 0 )
            {
                usRegHoldingBuf[iRegIndex++] = __REV16(*PRT++); //数据序转 REV16.W
//      usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
//              usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
//              iRegIndex++;
                usNRegs--;
            }
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}
 受到freeModbus作者使用“assert()”的影响在这个里我用了__REV16()这个函数 
*PRT++ = __REV16(usRegHoldingBuf[iRegIndex++]);
这是Cortex—M3中的一个汇编指令REV16 功能是交换一个字的高位和地位位的两个字节,若0x1234==__REV16(0x3412)。字节在*pucRegBuffer中的顺序与串口发送的顺序是一致的所以要有这么个转换,当然用代码中注释掉的部分也能实现同样的功能。这是用__REV16()看起来更“酷”一些。当然这样编译后的结果是大约减少4条指令,效率提升有限。
序转指令不少 功能非常强大~!__REV16()来源于core_cm3.c
FreeModbus 移植于STM32 实现Modbus RTU通行 - java - stm32学习日志
后边只要想法将STM32_PLC 输出的地址映射这个寄存器上边可以了
 
FreeModbus 移植于STM32 实现Modbus RTU通行 - java - stm32学习日志
整个移植没有什么难度 只是看官方的英文API文档 生词太多,其实意思非常简单。而且刚开始又用了来路不明的FreeModbus库文件,不伦怎样都不工作,浪费不少时间。全部工作前后总共花了两天的时间。
 
我移植好的demo 注释很全 应该可以轻易看懂。
DOWNLOAD:
115:
关键字:FreeModbus  移植  STM32  Modbus  RTU通信 引用地址:FreeModbus 移植于STM32 实现Modbus RTU通信

上一篇:STM32 的看门狗
下一篇:STM32 _I _0 _IO volatile const

推荐阅读最新更新时间:2024-03-16 15:13

意法半导体的STM32微控制器助力美国August开发智能门锁系统
横跨多重电子应用领域、全球领先的半导体供应商、世界领先的物联网(IoT, Internet of Things)芯片供应商意法半导体宣布其STM32微控制器被美国August公司采用,用于设计新一代智能门锁(Smart Lock) 系统。 STM32嵌入式微控制器的高性能和高能效让August智能门锁用户可通过智能手机或电脑直接控制家中门锁,无需实体钥匙。除提供32位的处理性能和安全信号处理功能外,STM32微控制器的实时响应和能效也非常出色。 意法半导体美洲区微控制器市场应用副总裁 Tony Keirouz 表示:“基于STM32微控制器的 August智能门锁是一项前所未有的创新装置,彻底改变了人们原本熟悉的家庭门禁系
[单片机]
STM32 USB DFU设备固件升级 工程讲解
说到STM32 USB的UDF,其实就是我们常说的IAP(In Application Programming)在应用编程。IAP有很多方法,我之前就用过串口IAP,网络IAP。而这里我们使用的是USB IAP,就是通过USB更新代码。所以这里有必要线了解IAP。 IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,
[单片机]
<font color='red'>STM32</font> USB DFU设备固件升级 工程讲解
20种PLC元件编号和Modbus编号地址对应表分享
曾经做过单片机和以下20种PLC的Modbus RTU串口通信,现将这20种PLC输入、输出和寄存器元件与Modbus编号地址对应表分享出来。 三菱FX3G-40MR/ES-A、西门子S7-200 CPU226 AC/DC/RLY、欧姆龙CP1H-X40DR-A、松下AFPX-C40R、台达DVP-12SA2、信捷XC5-48、永宏FBs-40MC、产电XBC-DR40S、汇川H2u-2416MT-XP、英威腾IVC2H-1616MAT6、基恩士KV-N40AR、施耐德电气TM218LDAE40DRPHN、海为H40S2R系列、维控LX3V1212MT系列、和利时LE5109、台安AP-340BR-A、罗克韦尔1766-L32
[嵌入式]
20种PLC元件编号和<font color='red'>Modbus</font>编号地址对应表分享
第十一章、Tiny4412 U-BOOT移植十一 DDR3简单介绍
由于Tiny4412所用的芯片是DDR3,我从网上找一片介绍DDR3的原理的博文,虽然很多原理是一致的,但还是想着这些资料难搜集,而且多看一次除了费点时间外,我想不到别的坏处,那就在看一次,以便以后在修改代码时,已能对DDR3的所有参数非常清楚,网址 http://blog.csdn.net/wshini7316/article/details/8508836 此博文以是镁光的(Micron MT41J128M8 1Gb DDR3 SDRAM芯片为例说明的。内容如下: 一、内存工作流程 首先,我们先了解一下内存的大体结构工作流程,这样会比较容量理解这些参数在其中所起到的作用。这部分的讲述运用DDR3的简化时序图。 DDR3的
[单片机]
第十一章、Tiny4412 U-BOOT<font color='red'>移植</font>十一 DDR3简单介绍
STM32单片机GPIO口的学习
  GPIO:   STM32的(64引脚的)IO口一共有3个,分别是PA、PB、PC.   STM32的IO端口可以由软件配置成8种模式:   1,输入浮空   2,输入上拉   3,输入下拉   4,模拟输入   5,开漏输出   6,推挽输出   7,推挽复用功能   8,开漏复用功能   STM32的每个IO端口都有7个寄存器来控制。他们分别是:配置模式的2个32位的端口配置寄存器CRL和CRH;2个32位的数据寄存器IDR和ODR;1个32位的置位/复位寄存器BSRR;一个16位的复位寄存器BRR;1个32位的锁存寄存器LCKR;我们常用的IO端口寄存器只有4个:CRL、CRH、IDR、ODR。   注意(在配置ST
[单片机]
ucos-ii学习笔记——s12移植成功main函数
Created on: 2012-10-9 Author: zhang bin 学习笔记 for ucos-ii MC9S12XS128 redesigned by zhang bin 2012-10-9 versions :V-0.1 All Rights Reserved #include includes.h #include pll.h #include string.h #define TASK_STK_SIZE 128 //定义任务堆栈长度 #define TASK_START_PRIO 5 // 此版本的uC/
[单片机]
STM32 USB断开连接代码停止运行
这段时间做USB固件升级,使用ST官方固件,最开始按照ST的做法通过检测按键进入DFU模式。后来由于别人觉得这种方式做不好,要改成检测USB的而不是检测按键的。但是当我改好了测试的时候却发现当我把USB初始化之后断开了USB连接程序停止了运行,接上USB程序才会继续跑。连使用Jlink调试都没用了。然而根据打印调试,USB接上的时候MCU并没有复位,硬件出错其实也不太像,总之觉得一切很诡异。至少在当时我根本就没办法解释我所观察到的这个现象。百度也没有结果,大多数情况下百度其实很废但是没办法。 想了很久我觉得是不是MCU休眠去了?带着这样的猜测到初始化过程中去找相关初始化,因为在我印象当中,睡眠模式也是需要初始化寄
[单片机]
U-Boot在基于ADSP BF533的嵌入式Linux系统上的移植
1 引言 Boot Loader(内核引导程序)是在操作系统内核运行之前运行的一段自举程序,用于初始化硬件设备、改变处理器运行模式、重组中断向量和建立内存空间映射图,从而将系统的软硬件带到一个合适的状态或者用户定制的特定状态,以便为最终加载操作系统内核准备好正确的环境 。 嵌入式Linux系统常用的Boot Loader有arm-boot、redboot、U-Boot等。U-Boot (全称Universal Boot Loader)是当前比较流行的遵循GPL条件的开放源码项目。U-Boot具有源码公开的特点,开发人员可根据自身需要进行裁减;支持多种处理器和嵌入式操作系统内核;具有多种设备驱动源码:支持种引导方式;具有功能强大
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved