新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > FreeModbus 移植于STM32 實現Modbus RTU通信

        FreeModbus 移植于STM32 實現Modbus RTU通信

        作者: 時間:2016-12-03 來源:網絡 收藏
        畢業設計自己要做個基于STM32的PLC能直接跑語句表的,現在看來好像沒有什么創新的地方,不過實現的方式絕對夠創新的了...呵呵。自己寫的開題報告中說了要有高級的通信功能。現在做以太網有點來不及了,CAN又感覺不搭調,硬件上也沒準備。串口上跑Modbus感覺不錯。本來西門子的S7-200就能跑Modbus,STM32-PLC當然也要支持Modbus 什么 組態軟件,觸摸屏都可以連上,不過FreeModbus只支持從機有點可惜,當然本來協議也不難而且也必要實現全協議棧。

        Modbus中文協議.PDF

        本文引用地址:http://www.104case.com/article/201612/325168.htm

        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() 斷言宏 freeModbus的作者有點意思,為此不可以定義NDEBUG 。#include "stm32f10x.h" 似乎要添加到#include 的后邊 不然編譯會有問題。
        port.C
        添加了些Modbus協議棧與寄存器的接口函數 這個也要自己寫。
        FreeModbus 通過 eMBRegInputCB eMBRegHoldingCB eMBRegCoilsCBeMBRegDiscreteCB 四個接口函數完成數據的讀寫操作
        其中最常用的是這個 eMBRegHoldingCB 為了方便測試可以構造usRegHoldingBuf[]這樣的一個數組進行讀寫調試。
        上位機可以用諸如Modbus調試精靈這樣的軟件。
        // 寄存器的讀寫函數 支持的命令為讀 0x03 和寫0x06
        eMBErrorCodeeMBRegHoldingCB( 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 注釋很全 應該可以輕易看懂。
        DOWNLOAD:
        FreeModbus_For_STM32.7z
        115:
        FreeModbus_For_STM32.7z


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 临沂市| 喀什市| 金山区| 城口县| 巴东县| 平阴县| 务川| 榆社县| 丹阳市| 蓬溪县| 太仆寺旗| 南木林县| 托里县| 通辽市| 和顺县| 寿阳县| 黔东| 林芝县| 蕉岭县| 都昌县| 罗源县| 公主岭市| 大同市| 镇安县| 开阳县| 芦溪县| 杂多县| 永州市| 龙岩市| 墨玉县| 鹰潭市| 花莲市| 黄梅县| 乌苏市| 嵊泗县| 洪江市| 尼玛县| 黎城县| 广丰县| 亳州市| 汶川县|