最終更新日:2023/3/27
※W5500-EVB-Pico + MakerPiPico版を構築しました。
※改良版があります。
RP2040をModbusTCPSlaveとして使える様にたたき台コードを作成しました。
STM32MINIShieldEvaluation_ModbusSlaveに比べると可成り単純化したコードです。
- NICはWizNetのW5500chipとします。今回はW550ioを使って見ました。
- PicoShieldですが、MakerPiPicoとしています。このShieldは1500円程度で入力出力等のチェックがしやすいので使いやすいと思います。
- メモリ領域と実際のデバイス確認領域は異なります。
Coilとして CP16,17を割り当てています。
Discreteとして CP20,21,22を割り付けています。MakerPiPicoに入力ボタンスイッチが用意されているからです。
Inputとして CP26,27,28を割り当てています。アナログ入力端子に当たります。12bit分解能です。※Picoでは3ch分しか使えないようです。- Holdはメモリ内の値のみで扱っています。外部デバイスを扱う場合、I2C接続でアナログ出力(MCP4725等)を接続可能です。
実際の挙動ですが、
- シリアルモニタは使わなくても構いません。シリアルモニタを起動してからRUNボタンを押すと、シリアルモニタに設定IPアドレスが表示されます。ソースコードでは192.168.0.208にしています。
- 実行するとビルトインLED(CP25)が点滅します。
- 外部からModbusToolにて接続すると情報の読み書きが出来ます。
Coil_0のOn/OffでCP16のLEDの点灯/消灯が確認出来るはずです。
Coil_1のOn/OffでCP16のLEDの点灯/消灯が確認出来るはずです。
CP20のボタンを押すとDiscrete[0]の値が変化するはずです。
CP21のボタンを押すとDiscrete[1]の値が変化するはずです。
CP22のボタンを押すとDiscrete[2]の値が変化するはずです。
CP26から28にそれぞれリード線を接続し、人の指先で他端を挟むと電圧が変化しInput[]の値に変化が有るはずです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; }
免責事項
本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。本ソフトウエアの著作権は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社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。