RP2040で動作するModbusTCPSlaveを作成してみました。

最終更新日:2023/3/27

W5500-EVB-Pico + MakerPiPico版を構築しました。

改良版があります

RP2040をModbusTCPSlaveとして使える様にたたき台コードを作成しました。
STM32MINIShieldEvaluation_ModbusSlaveに比べると可成り単純化したコードです。

実際の挙動ですが、

STM32MINIShieldEvaluation_ModbusSlave並の拡張が可能なはずですが、RP2040と互換のあるライブラリが少なく結構根気が必要だと思います。
ただ、Picoやそれ用のShieldの入手性を考えると移行したいところです。
また、W5500-EVB-Picoが入手出来たら是非利用したいです。現時点でW5500-EVB-Picoを入手出来ていません。

RP2040版とSTM32F1版ではRAMの容量が極端に違います。このためブラウザで設定画面に開いたときに余りに反応が違うことにびっくりします。ただ、MODBUSSLAVEに対する応答性はさほど遜色を感じませんでした。

/*
 * 2023/1/30 T.Wanibe
 * Sandeep Mistry氏のイーサネット Modbus TCP サーバー LEDを改造
 * MgsModbusをPiPicoで使えるよう検討中
 * MgsModbusはライブラリ内で設定している項目が多いのでオブジェクト生成 MgsModbus Mbのみにした方が良い
 * 最大1044480バイトのフラッシュメモリのうち、スケッチが63276バイト(6%)を使っています。
 * 最大262144バイトのRAMのうち、グローバル変数が8464バイト(3%)を使っていて、ローカル変数で253680バイト使うことができます。
 */
#include        <SPI.h>
#include        "MgsModbus.h"                                           //このSketchと同じ階層に置く
#define         MbCoilDataLen           2                               // length of the MbCoilDataLen array (Equivalent16bit*2)
#define         MbDiscreteDataLen       2                               // length of the MbDiscreteDataLen array(Equivalent16bit*2)
#define         MbHoldDataLen           16                              // length of the MbHoldDataLen array
#define         MbInputDataLen          48                              // length of the MbInputDataLen array
#define         OK                      0
#define         NG                      1
#define         BAUDRATE        115200
#define         CLK             18
#define         DIO             19
#define         NICReset        6
#define         NICInit         7
#define         SPI_SCK         2
#define         SPI_RX          4
#define         SPI_TX          3
#define         SPI_CS          5
// Ethernet settings (depending on MAC and Local network)
byte    mac[]           = {0x00,0x08,0xDC,0x54,0x4D,0xDD};              //WIZNET
byte    ip[]            = {192, 168, 0, 208};
byte    dns_server[]    = {192, 168, 0, 1};
byte    gateway[]       = {192, 168, 0, 1};
byte    subnet[]        = {255, 255, 255, 0};
bool    gMBusConnect    = false;                        //Modbus接続中はWebServer接続を502で逃げる
byte    fTogle1         = LOW;
int     dOsPins[]       = {16, 17};
int     dIsPins[]       = {20, 21, 22};
int     aIsPins[]       = {26, 27, 28};
//配列要素数を求めておく
int     DObits          = sizeof(dOsPins)/sizeof(int);
int     DIbits          = sizeof(dIsPins)/sizeof(int);
int     AIbits          = sizeof(aIsPins)/sizeof(int);
MgsModbus       Mb;
//----------------------------
int     GetDeviceInfo(){
        for (int i=0;i<DIbits;i++){
                Mb.SetBit(MB_FC_READ_DISCRETE_INPUT,i,!digitalRead(dIsPins[i]));        //bit 論理反転
        }
        for (int i=0;i<AIbits;i++){
                Mb.MbInputData[i]=analogRead(aIsPins[i]);                               //U16
        }
        return OK;            
}
//----------------------------
int     SetDeviceInfo(){
        for (int i=0;i<DObits;i++){          
                digitalWrite(dOsPins[i],!Mb.GetBit(MB_FC_READ_COILS,i));                 //LEDはLOWで点灯                            
        }
        return OK;
}
//--------------
void setup() {
        Serial.begin(BAUDRATE);
        /*
        while (!Serial) {
                ; // シリアルポートが接続されるのを待ちます。シリアルモニタを寄贈するまで待機します。
        }
        */
        Serial.println("Start Ethernet Modbus TCP Example");
        pinMode(LED_BUILTIN, OUTPUT);
        SPI.setSCK(SPI_SCK);
        SPI.setRX(SPI_RX);
        SPI.setTX(SPI_TX);
        SPI.setCS(SPI_CS);
        SPI.begin(); 
        //Ethernet3で使用可能なAPI
        pinMode(SPI_CS, OUTPUT);                                        //NIC_CS出力設定
        Ethernet.setCsPin(SPI_CS);                                      //NIC_CSアサイン
        Ethernet.setRstPin(NICReset);                                   //NIC_RSTアサイン
        //NICリセット処理
        pinMode(NICReset, OUTPUT);
        digitalWrite(NICReset, LOW);
        delay(10);                                                      //10msecパルス幅で初期化
        digitalWrite(NICReset, HIGH);
        Ethernet.begin(mac, ip);
        delay(100);
        Serial.print(F("My IP address: "));Serial.println(Ethernet.localIP());// print your local IP address:
        //ModBusメモリ 初期化
        for(int i = 0;i<MbCoilDataLen;i++)      Mb.MbCoilData[i]=0x0000;//メモリ初期化
        for(int i = 0;i<MbDiscreteDataLen;i++)  Mb.MbDiscreteData[i]=0; //メモリ初期化
        for(int i = 0;i<MbHoldDataLen;i++)      Mb.MbHoldData[i]=0;     //メモリ初期化
        for(int i = 0;i<MbInputDataLen;i++)     Mb.MbInputData[i]=0;    //メモリ初期化
        //Serial.println(F("ModBusメモリ 初期化"));
        //出力LED初期化
        for (int i=0;i<DObits;i++){          
                Mb.SetBit(MB_FC_READ_COILS,i,false);                    //メモリマップはMb.MbData[0]
                pinMode(dOsPins[i],OUTPUT);
                digitalWrite(dOsPins[i], LOW);                         //LEDはHIGHで点灯                            
        }
        //入力pin初期化
        for (int i=0;i<DIbits;i++){
                pinMode(dIsPins[i],INPUT);
                Mb.SetBit(MB_FC_READ_DISCRETE_INPUT,i,!digitalRead(dIsPins[i]));        //bit メモリマップはMb.MbData[1]
        }
        for (int i=0;i<AIbits;i++){
                Mb.MbInputData[i] = analogRead(aIsPins[i]);             //U16
        }
}
//-------------------
void loop() {
        // listen for incoming clients
        GetDeviceInfo();
        // start the Modbus TCP server
        gMBusConnect = Mb.MbsRun();                                      //SlaveServer
        Serial.print("gMBusConnect=");Serial.println(gMBusConnect);
        SetDeviceInfo();
        /*
        if (gMBusConnect) {
                Serial.println("Failed to start Modbus TCP Server!");
                while (1);
        }
        */
        // configure the LED
        digitalWrite(LED_BUILTIN, fTogle1);
        fTogle1 = !fTogle1;
        delay(100);
}

MgsModbus.h

/*
 * 2021/04/23 T.Wanibe Retouch
 * 20191029 T.Wanibe 保持メモリを個別に持たないとうまくゆかない
 * 個別に4つのメモリを保持するように変更
 * 20191028 T.Wanibe 一般的なModbusデバイスとして構築出来るように
 * MgsModbusをレタッチすることにした。『ModbusPoll』とかLabVIEWの
 * Modbusライブラリを元に調査したところ、MgsModbusはスレーブサーバ
 * としてちゃんと機能するライブラリだと云う事が確認出来た。
 * STM32duinoとしてコンパイル出来ないライブラリが殆ど。ライブラリ側で
 * Arduinoしか意識していない為と思われる。
 * MgsModbusはシンプルであるが故にSTM32duinoでもコンパイルが通り実行
 * 可能となる。
 * が、アドレスマップがゼロベースであったり、4つのブロックの内Coilブロック
 * しかうまくアクセス出来ない点も確認出来た。
 * 一般的なModbusデバイスとして認識出来るように大胆なデバッグを実施する
 * ことにした。
 * まず、Localな扱いとした。inoと同じフォルダに配置すること。
 * Slave機能のコードのみ残して(Masterのコードは削除)
 * 
 * MgsModbus.h-Modbus TCPマスターおよびスレーブ用のArduinoライブラリ。
 * V-0.1.1著作権(C)2013 Marco Gerritse
 * Arduino 1.0で作成およびテスト済み
 * 
 * このライブラリは、
 *  MgsModbus.h-Modbus TCPマスターおよびスレーブ用のArduinoライブラリ。
 * を原点としています。
 * 
 * テストに使用される外部ソフトウェア:
 * ★Modbus Poll 
 *      Modbus Poll x64 version 9.1.0 Build 1286, self-installing
 * ★LabVIEW Modbusライブラリ     
 *      NI Modbus Library v1.1.5.39 by National Instruments
 * ??
 * このライブラリは、すべてのmodbusデータ(mbData []配列)に単一のメモリブロック
 * を使用します。
 * 16ビットアクセスまたはアクセスビットを介して、いくつかのmodbus機能を介して同じ
 * データに到達できます。 MbDataの長さは少なくとも1でなければなりません。
 * ●スレーブの場合、次のmodbus機能が実装されます:1、2、3、4、5、6、15、16
 * ●内部および外部アドレスは1ベースに修正しています。
 * ●EtherNetライブラリは『Ethernet3』を採用しています。W5500を安定して使用する為です。
 */

#include "Arduino.h"
#include <SPI.h>
#include <Ethernet3.h>
#ifndef MgsModbus_h
#define MgsModbus_h
#define MbCoilDataLen           2       // length of the MbCoilDataLen array (Equivalent16bit*2)
#define MbDiscreteDataLen       2       // length of the MbDiscreteDataLen array(Equivalent16bit*2)
#define MbHoldDataLen           64      // length of the MbHoldDataLen array
#define MbInputDataLen          40      // length of the MbInputDataLen array
#define MB_PORT                 502
enum MB_FC {
        MB_FC_NONE                     = 0,
        MB_FC_READ_COILS               = 1,
        MB_FC_READ_DISCRETE_INPUT      = 2,
        MB_FC_READ_REGISTERS           = 3,
        MB_FC_READ_INPUT_REGISTER      = 4,
        MB_FC_WRITE_COIL               = 5,
        MB_FC_WRITE_REGISTER           = 6,
        MB_FC_WRITE_MULTIPLE_COILS     = 15,
        MB_FC_WRITE_MULTIPLE_REGISTERS = 16
};
enum MB_XC {
        MB_XC_NONE                      = 0,
        MB_XC_Illegal_Function          = 1,
        MB_XC_Illegal_Data_Address      = 2,
        MB_XC_Illegal_Data_Value        = 3,
        MB_XC_Slave_Device_Failure      = 4,
        MB_XC_Acknowledge               = 5,
        MB_XC_Slave_Device_Busy         = 6,
        MB_XC_Negative_Acknowledge      = 7,
        MB_XC_Memory_Parity_Error       = 8,
        MB_XC_Gateway_Path_Unavailable  = 10,
        MB_XC_Gateway_Target_Failed     = 11
};
class MgsModbus
{
        public:
                // general
                MgsModbus();
                word MbCoilData[MbCoilDataLen];                 // memory block that holds all the modbus user data
                word MbDiscreteData[MbDiscreteDataLen];         // memory block that holds all the modbus user data
                word MbHoldData[MbHoldDataLen];                 // memory block that holds all the modbus user data
                word MbInputData[MbInputDataLen];               // memory block that holds all the modbus user data                
                boolean GetBit(MB_FC fc,word Number);
                boolean SetBit(MB_FC fc,word Number,boolean Data);       // returns true when the number is in the MbData range
                // modbus master
                //void Req(MB_FC FC, word Ref, word Count, word Pos);
                //void MbmRun();
                //IPAddress remSlaveIP;
                // modbus slave
                bool MbsRun();  
                word GetDataLen();
        private: 
                // general
                MB_FC SetFC(int fc);
                // modbus master
                //uint8_t MbmByteArray[260];                    // send and recieve buffer
                //MB_FC MbmFC;
                //int MbmCounter;
                //void MbmProcess();
                //word MbmPos;
                //word MbmBitCount;
                //modbus slave
                uint8_t MbsByteArray[260];                      // send and recieve buffer
                MB_FC MbsFC;
                MB_XC MbsXC;
};
#endif

MgsModbus.cpp

/* 
 *  2021/04/23 T.Wanibe Retouch
 */
#include "MgsModbus.h"
//
EthernetServer MbServer(MB_PORT);
EthernetClient MbmClient;
#define DEBUG   1
MgsModbus::MgsModbus()
{
}
char buf[32];
//****************** Recieve data for ModBusSlave ****************
//      2021/3/5 接続が有った場合はtrueをない場合はfalseを返すように変更
bool MgsModbus::MbsRun()
{ 
        bool    flagConnected   = false;
        MbsXC                   = MB_XC_NONE;
        //****************** Read from socket ****************
        EthernetClient client   = MbServer.available();
        flagConnected           = client.available();
        if(flagConnected){
                digitalWrite(LED_BUILTIN, LOW);
                delay(1);
                int i = 0;
                while(client.available()){
                        MbsByteArray[i] = client.read();
                        i++;
                }
                MbsFC = SetFC(MbsByteArray[7]);  //Byte 7 of request is FC
#if DEBUG
                Serial.print(F("\nREQUEST:"));
                for(int j = 0;j<i;j++){
                        sprintf(buf,"%02x ",MbsByteArray[j]);
                        Serial.print(buf);
                }
                Serial.println(F(""));
                digitalWrite(LED_BUILTIN, HIGH);
#endif                
        }
        int Start, WordDataLength, ByteDataLength, CoilDataLength, MessageLength;
        //SwitchCaseに変更しようとしたがコンパイルエラーが発生するので諦めた
        if(MbsFC == MB_FC_READ_COILS) {                                                 //****************** Read Coils (1) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);                //StartAddress確認
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
#if DEBUG
                sprintf(buf,"01StartADRS=%d Length=%d",Start,CoilDataLength);
                Serial.println(buf);
#endif  
                if((Start<0) || ((CoilDataLength + Start) > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = CoilDataLength / 8;
                        if(ByteDataLength * 8 < CoilDataLength) ByteDataLength++;      
                        CoilDataLength  = ByteDataLength * 8;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < ByteDataLength ; i++){
                                MbsByteArray[9 + i] = 0;                                // To get all remaining not written bits zero
                                for(int j = 0; j < 8; j++){
                                        bitWrite(MbsByteArray[9 + i], j, GetBit(MB_FC_READ_COILS,Start + i * 8 + j));
                                }
                        }
                        MessageLength = ByteDataLength + 9;
                }      
                //
        }else if(MbsFC == MB_FC_READ_DISCRETE_INPUT) {                                  //****************** Read Coils (2) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);                //StartAddress確認
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
#if DEBUG
                sprintf(buf,"02StartADRS=%d Length=%d",Start,CoilDataLength);
                Serial.println(buf);
#endif
                if((Start<0) || ((CoilDataLength + Start) > (MbDiscreteDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = CoilDataLength / 8;
                        if(ByteDataLength * 8 < CoilDataLength) ByteDataLength++;      
                        CoilDataLength  = ByteDataLength * 8;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < ByteDataLength ; i++){
                                MbsByteArray[9 + i] = 0;                                // To get all remaining not written bits zero
                                for(int j = 0; j < 8; j++){
                                        bitWrite(MbsByteArray[9 + i], j, GetBit(MB_FC_READ_DISCRETE_INPUT,Start + i * 8 + j));
                                }
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_READ_REGISTERS) {                                       //****************** Read Registers (3) ******************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength  = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbInputDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < WordDataLength; i++){
                                MbsByteArray[ 9 + i * 2] =      highByte(MbHoldData[Start + i]);
                                MbsByteArray[10 + i * 2] =      lowByte(MbHoldData[Start + i]);
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_READ_INPUT_REGISTER) {                                  //****************** Read Registers (4) ******************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength  = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < WordDataLength; i++){
                                MbsByteArray[ 9 + i * 2] =      highByte(MbInputData[Start + i]);
                                MbsByteArray[10 + i * 2] =      lowByte(MbInputData[Start + i]);
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_COIL) {                                           //****************** Write Coil (5) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
#if DEBUG
                sprintf(buf,"05StartADRS=%d",Start);
                Serial.println(buf);
#endif  
                if((Start<0) || (Start > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength   = 9;
                }else{
                        if (word(MbsByteArray[10],MbsByteArray[11]) == 0xFF00){SetBit(MB_FC_WRITE_COIL,Start,true);}
                        if (word(MbsByteArray[10],MbsByteArray[11]) == 0x0000){SetBit(MB_FC_WRITE_COIL,Start,false);}
                        MbsByteArray[5] = 2;                                            //Number of bytes after this one.
                        MessageLength   = 8;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_REGISTER) {                                       //****************** Write Register (6) ******************
                Start                   = word(MbsByteArray[8],MbsByteArray[9]);
                if((Start<0) || (Start > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        MbHoldData[Start]       = word(MbsByteArray[10],MbsByteArray[11]);
                        MbsByteArray[5]         = 6;                                    //Number of bytes after this one.
                        MessageLength           = 12;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_MULTIPLE_COILS) {                                 //****************** Write Multiple Coils (15) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
                if((Start<0) || ((CoilDataLength + Start) > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength   = 9;
                }else{
                        MbsByteArray[5] = 6;
                        for(int i = 0; i < CoilDataLength; i++){
                                SetBit(MB_FC_WRITE_MULTIPLE_COILS,Start + i,bitRead(MbsByteArray[13 + (i/8)],i-((i/8)*8)));
                        }
                        MessageLength = 12;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_MULTIPLE_REGISTERS) {                             //****************** Write Multiple Registers (16) ******************
                Start                   = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength          = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = 6;
                        for(int i = 0; i < WordDataLength; i++){
                                MbHoldData[Start + i] =  word(MbsByteArray[ 13 + i * 2],MbsByteArray[14 + i * 2]);
                        }
                        MessageLength = 12;
                }
        }else{
                //Exception 01:IllegalFunction
                MbsXC           = MB_XC_Illegal_Function;
                ByteDataLength  = 0;
                MbsByteArray[7] = 0x10 + MbsByteArray[7];
                MbsByteArray[8] = MbsXC;
                MessageLength = 9 + ByteDataLength;
        }
        //
        MbsFC = MB_FC_NONE;
        client.write(MbsByteArray, MessageLength);
#if DEBUG
        Serial.print(F("\nRESPONS:"));
        for(int i = 0;i<MessageLength;i++){
                sprintf(buf,"%02x ",MbsByteArray[i]);
                Serial.print(buf);
        }
        Serial.println(F(""));
#endif 
        return flagConnected;
}
//****************** ?? ****************** 20210423 retouch
MB_FC MgsModbus::SetFC(int fc){
        MB_FC FC;
        switch(fc){
                case 1:
                        FC = MB_FC_READ_COILS;
                        break;
                case 2:
                        FC = MB_FC_READ_DISCRETE_INPUT;
                        break;
                case 3:
                        FC = MB_FC_READ_REGISTERS;
                        break;
                case 4:
                        FC = MB_FC_READ_INPUT_REGISTER;
                        break;
                case 5:
                        FC = MB_FC_WRITE_COIL;
                        break;
                case 6:
                        FC = MB_FC_WRITE_REGISTER;
                        break;
                case 15:
                        FC = MB_FC_WRITE_MULTIPLE_COILS;
                        break;
                case 16:
                        FC = MB_FC_WRITE_MULTIPLE_REGISTERS;
                        break;
                default:
                        FC = MB_FC_NONE;
        }
        return FC;
}
//---------------------
word MgsModbus::GetDataLen(){
        int MbDataLen;
        switch(MbsFC){
                case MB_FC_READ_COILS:
                case MB_FC_WRITE_COIL:
                case MB_FC_WRITE_MULTIPLE_COILS:
                        MbDataLen = MbCoilDataLen;
                        break;
                case MB_FC_READ_DISCRETE_INPUT:
                        MbDataLen = MbDiscreteDataLen;
                        break;
                case MB_FC_READ_REGISTERS:
                case MB_FC_WRITE_REGISTER:
                case MB_FC_WRITE_MULTIPLE_REGISTERS:
                        MbDataLen = MbHoldDataLen;
                        break;
                case MB_FC_READ_INPUT_REGISTER:
                        MbDataLen = MbInputDataLen;
                        break;
                default:
                        MbDataLen = 0;
        }
        return MbDataLen;
}
//---------------------
boolean MgsModbus::GetBit(MB_FC fc,word Number){
        boolean Tmp;
        int ArrayPos = Number / 16;
        int BitPos = Number - ArrayPos * 16;
        if(fc == MB_FC_READ_DISCRETE_INPUT){
                Tmp = bitRead(MbDiscreteData[ArrayPos],BitPos);
        }else{
                Tmp = bitRead(MbCoilData[ArrayPos],BitPos);
        }
        return Tmp;
}
//---------------------
boolean MgsModbus::SetBit(MB_FC fc,word Number,boolean Data){
        boolean Overrun;
        int ArrayPos = Number / 16;
        int BitPos = Number - ArrayPos * 16;
        if(fc == MB_FC_READ_DISCRETE_INPUT){
                Overrun = ArrayPos > MbDiscreteDataLen * 16;                            // check for data overrun
                if (!Overrun){                 
                        bitWrite(MbDiscreteData[ArrayPos],BitPos,Data);
                }
        }else{
                Overrun = ArrayPos > MbCoilDataLen * 16;                                // check for data overrun
                if (!Overrun){                 
                        bitWrite(MbCoilData[ArrayPos],BitPos,Data);
                }                        
        }
        return Overrun;
}


戯言(nonsense)に戻る


問い合わせ頁の表示


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。

商標・登録商標

Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。