查看: 30409|回复: 7

FreeModbus 移植于STM32 实现Modbus RTU通信

  [复制链接]
  • TA的每日心情
    奋斗
    2016-8-15 09:28
  • 签到天数: 222 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2014-9-22 16:58:50 | 显示全部楼层 |阅读模式
    分享到:
    毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像没有什么创新的地方,不过实现的方式绝对够创新的了...呵呵。自己写的开题报告中说了要有高级的通信功能。现在做以太网有点来不及了,CAN又感觉不搭调,硬件上也没准备。串口上跑Modbus感觉不错。本来西门子的S7-200就能跑Modbus,STM32-PLC当然也要支持Modbus 什么 组态软件,触摸屏都可以连上,不过FreeModbus只支持从机有点可惜,当然本来协议也不难而且也必要实现全协议栈。


    STM32移植FreeModbus的步骤:

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

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

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

    Demo 文件夹下都是官方移植好的其他芯片的版本。选BARE文件下的“赤裸”文件加入工程 同时添加全部的库文件,可参考下图
    1.jpg
    FreeModbus 移植于STM32 实现Modbus RTU通行

    需要移植修改的在 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调试精灵这样的软件。
    2.jpg
    FreeModbus 移植于STM32 实现Modbus RTU通行

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

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

    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2015-3-21 14:45
  • 签到天数: 64 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2014-9-22 17:52:05 | 显示全部楼层
    顶,前段时间也刚用到stm32上,官网不知道为什么,下载不下,在别的地方找了很久
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-9-15 06:28
  • 签到天数: 3747 天

    连续签到: 60 天

    [LV.Master]伴坛终老

    发表于 2014-9-22 18:30:06 | 显示全部楼层
    不错,谢谢分享!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-6-24 16:41
  • 签到天数: 709 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2014-9-28 08:06:42 | 显示全部楼层
    看看  好像还不错哦
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-7-4 13:51
  • 签到天数: 347 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2014-9-30 14:18:12 | 显示全部楼层
    这部分没接触过,支持下
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-11-30 14:39
  • 签到天数: 66 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2015-6-7 23:03:20 | 显示全部楼层
    学习了,多谢分享
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2015-12-11 22:20:36 | 显示全部楼层
    不知哪位网友有freemodbus 的原码版本,求分享一下,官网上不知咋的下载不了
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-9-8 18:33
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2016-12-29 20:31:19 | 显示全部楼层
    正好需要,必须支持一下,谢楼主
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-25 03:58 , Processed in 0.175746 second(s), 29 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.