<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > FreeModbus 移植于STM32 實現(xiàn)Modbus RTU通信

          FreeModbus 移植于STM32 實現(xiàn)Modbus RTU通信

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

          Modbus中文協(xié)議.PDF

          本文引用地址:http://www.ex-cimer.com/article/201612/325168.htm

          STM32移植FreeModbus的步驟:

          首先去http://www.freemodbus.org下載文件 一定要是官方可靠的才行,我起先為了圖方便網(wǎng)上隨便下載了一個,結(jié)果白白浪費了一下午的時間

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

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

          Demo 文件夾下都是官方移植好的其他芯片的版本。選BARE文件下的“赤裸”文件加入工程 同時添加全部的庫文件,可參考下圖

          需要移植修改的在 port 目錄下
          porttimer.c
          中 xMBPortTimersInit( USHORT usTim1Timerout50us ) 負(fù)責(zé)配置一個 時基 ,vMBPortTimersEnable( ) 啟用這個時基。

          比如執(zhí)行

          xMBPortTimersInit( 10000 );
          vMBPortTimersEnable( );
          for( ;; );
          定時器按中斷內(nèi) 便會每500MS調(diào)用一次pxMBPortCBTimerExpired( );同時你也要檢測vMBPortTimersDisable( ) 是否可以可靠的關(guān)閉定時器。用仿真器 用LED燈都行的.


          portother.c

          //負(fù)責(zé)一個串口的配置 為了省事我只支持了波特率的修改

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

          vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )負(fù)責(zé)控制串口【收/發(fā)】中斷的禁止與使能

          pxMBFrameCBByteReceived( ); //在串口接收中斷內(nèi)調(diào)用 用于通訊偵測

          pxMBFrameCBTransmitterEmpty( ); //在串口發(fā)送中斷內(nèi)調(diào)用 用于告知完成了發(fā)送 發(fā)送緩沖為空

          xMBPortSerialGetByte( CHAR * pucByte ) xMBPortSerialPutByte( CHAR ucByte ) 兩個為 串口字節(jié)的收發(fā)

          port.h

          中定義了 全局中斷的開關(guān)

          #define ENTER_CRITICAL_SECTION( )   __set_PRIMASK(1) /*關(guān)中中斷*/
          #define EXIT_CRITICAL_SECTION( )    __set_PRIMASK(0) /*開總中斷*/
          __set_PRIMASK() 來源于 core_cm3.c 
          這個頭文件中添加了#include  assert() 斷言宏 freeModbus的作者有點意思,為此不可以定義NDEBUG 。#include "stm32f10x.h" 似乎要添加到#include 的后邊 不然編譯會有問題。
          port.C
          添加了些Modbus協(xié)議棧與寄存器的接口函數(shù) 這個也要自己寫。
          FreeModbus 通過 eMBRegInputCB eMBRegHoldingCB eMBRegCoilsCBeMBRegDiscreteCB 四個接口函數(shù)完成數(shù)據(jù)的讀寫操作
          其中最常用的是這個 eMBRegHoldingCB 為了方便測試可以構(gòu)造usRegHoldingBuf[]這樣的一個數(shù)組進(jìn)行讀寫調(diào)試。
          上位機可以用諸如Modbus調(diào)試精靈這樣的軟件。
          // 寄存器的讀寫函數(shù) 支持的命令為讀 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++]); //數(shù)據(jù)序轉(zhuǎn) 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++); //數(shù)據(jù)序轉(zhuǎn) REV16.W
          //  usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;// usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;// iRegIndex++; usNRegs--; } } } else { eStatus = MB_ENOREG; } return eStatus;}
          受到freeModbus作者使用“assert()”的影響在這個里我用了__REV16()這個函數(shù) 
          *PRT++ = __REV16(usRegHoldingBuf[iRegIndex++]);
          這是Cortex—M3中的一個匯編指令REV16 功能是交換一個字的高位和地位位的兩個字節(jié),若0x1234==__REV16(0x3412)。字節(jié)在*pucRegBuffer中的順序與串口發(fā)送的順序是一致的所以要有這么個轉(zhuǎn)換,當(dāng)然用代碼中注釋掉的部分也能實現(xiàn)同樣的功能。這是用__REV16()看起來更“酷”一些。當(dāng)然這樣編譯后的結(jié)果是大約減少4條指令,效率提升有限。
          序轉(zhuǎn)指令不少 功能非常強大~!__REV16()來源于core_cm3.c
          后邊只要想法將STM32_PLC 輸出的地址映射這個寄存器上邊可以了
          整個移植沒有什么難度 只是看官方的英文API文檔 生詞太多,其實意思非常簡單。而且剛開始又用了來路不明的FreeModbus庫文件,不倫怎樣都不工作,浪費不少時間。全部工作前后總共花了兩天的時間。
          我移植好的demo 注釋很全 應(yīng)該可以輕易看懂。
          DOWNLOAD:
          FreeModbus_For_STM32.7z
          115:
          FreeModbus_For_STM32.7z


          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();