http://ntn314.blog.163.com/blog/static/161743584201233084434579/

毕业设计自己要做个基于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文件下的“赤裸”文件加入工程 同时添加全部的库文件,可参考下图

需要移植修改的在 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.h> assert() 断言宏 freeModbus的作者有点意思,为此不可以定义NDEBUG 。#include "stm32f10x.h" 似乎要添加到#include <assert.h>的后边 不然编译会有问题。
port.C
添加了些Modbus协议栈与寄存器的接口函数 这个也要自己写。
FreeModbus 通过 
eMBRegInputCB eMBRegHoldingCB
eMBRegCoilsCB eMBRegDiscreteCB 四个接口函数完成数据的读写操作
其中最常用的是这个 eMBRegHoldingCB 为了方便测试可以构造usRegHoldingBuf[]这样的一个数组进行读写调试。
上位机可以用诸如Modbus调试精灵这样的软件。

// 寄存器的读写函数 支持的命令为读 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
后边只要想法将STM32_PLC 输出的地址映射这个寄存器上边可以了
 
整个移植没有什么难度 只是看官方的英文API文档 生词太多,其实意思非常简单。而且刚开始又用了来路不明的FreeModbus库文件,不伦怎样都不工作,浪费不少时间。全部工作前后总共花了两天的时间。
 
我移植好的demo 注释很全 应该可以轻易看懂。
115:

FreeModbus 移植于STM32 实现Modbus RTU通信的更多相关文章

  1. Modbus RTU 通信工具设计(转)

    Modbus RTU 通信工具设计 Modbus 是一个工业上常用的通讯协议.一种通讯约定. ModBus 协议是应用层报文传输协议(OSI 模型第7层),它定义了一个与通信层无关的协议数据单元(PD ...

  2. Modbus RTU 通信应用案例

    如何打开项目归档文件 例程中的TIA博途项目文件与STEP 7项目文件均为归档文件,需要按如下方式打开: TIA博途项目文件 1. 打开TIA博途软件,通过软件左下方“项目视图”按钮切换至项目视图: ...

  3. Modbus RTU新版本指令介绍

    Modbus RTU新版本指令介绍 TIA V13 SP1版本软件中提供了2个版本的Modbus RTU指令: 图1. 两个版本Modbus RTU指令 早期版本的Modbus RTU指令(图1. 中 ...

  4. Modbus RTU 介绍

    S7-1200 Modbus RTU 通信概述 Modbus具有两种串行传输模式:分别为ASCII和RTU.Modbus是一种单主站的主从通信模式,Modbus网络上只能有一个主站存在,主站在Modb ...

  5. C# NModbus RTU通信实现

    Modbus协议时应用于电子控制器上的一种通用语言.通过此协议,控制器相互之间.控制器经由网络/串口和其它设备之间可以进行通信.它已经成为了一种工业标准.有了这个通信协议,不同的厂商生成的控制设备就可 ...

  6. FreeModbus RTU slave & Modbus RTU master

    一.FreeModbus RTU 协议数据格式 FreeModbus RTU是开源的一个协议,并且使用FreeModbus RTU 只能当做从机Slave,RTU协议中的指令由地址码(一个字节),功能 ...

  7. C# 开发Modbus Rtu客户端 modbus测试Demo,Modbus 串口通信 , 虚拟MODBUS-RTU测试

    前言 本文将使用一个NuGet公开的组件技术来实现一个ModBus RTU的客户端,方便的对Modbus rtu的服务器进行读写,这个服务器可以是电脑端C#设计的,也可以是PLC实现的,也可以是其他任 ...

  8. 【HAL库每天一例】freemodbus移植

    例程下载:资料包括程序.相关说明资料以及软件使用截图 百度云盘:https://pan.baidu.com/s/1slN8rIt 密码:u6m1 360云盘:https://yunpan.cn/OcP ...

  9. 单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等(转)

    源:单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等 //modebus_rtu.c /***************************************** ...

随机推荐

  1. MySQL中字符串函数详细介绍

    MySQL字符串函数对于针对字符串位置的操作,第一个位置被标记为1. ASCII(str)返回字符串str的 最左面字符的ASCII代码值.如果str是空字符串, 返回0.如果str是NULL,返回N ...

  2. 3.5 spring-replaced-method 子元素的使用与解析

    1.replaced-method 子元素 方法替换: 可以在运行时用新的方法替换现有的方法,与之前的 look-up不同的是replace-method 不但可以动态地替换返回的实体bean,而且可 ...

  3. 【概率】BZOJ 3450:Tyvj1952 Easy

    Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则 有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连 ...

  4. [百度]数组A中任意两个相邻元素大小相差1,在其中查找某个数

    一.问题来源及描述 今天看了July的微博,发现了七月问题,有这个题,挺有意思的. 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4 ...

  5. hdu 4101

    比赛的时候先是受以前一个圣神海的题目 用了两遍DFS 第一遍标记出围墙  第二遍求围墙外和每块围墙降为1所需的攻击次数  结果爆栈  改为BFS后AC DFS的加了一句这个 #pragma comme ...

  6. orale--varchar2(5) vs varchar2(5 byte) vs varchar2(5 char)

    varchar2(5) == varchar2(5 byte)------> 'abcde' 但是中文不是5 个字符 varchar2(5 char)----> 'abcde'

  7. Unity3D开发之NGUI结合粒子系统的遮挡问题

    原地址:http://blog.csdn.net/lihandsome/article/details/22194025 我的是NGUI3.0.3版本,在加入粒子系统的时候发现一直都是在精灵的下面,所 ...

  8. Java Code Examples for org.springframework.http.HttpStatus

    http://www.programcreek.com/java-api-examples/index.php?api=org.springframework.http.HttpStatus

  9. hdu 4655 Cut Pieces

    这个解题报告讲的很详细了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> #in ...

  10. 【BZOJ 2453|bzoj 2120】 2453: 维护队列 (分块+二分)

    2453: 维护队列 Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有 ...