Try   HackMD

如何看懂Open Source : 帶你閱讀一座程式III

tags: libmodbus

Copyright 2021, 月下麒麟


概念

文章回顧:
如何看懂Open Source : 帶你閱讀一座程式I
如何看懂Open Source : 帶你閱讀一座程式II

前面兩篇探討了一些,C語言的架構與基礎知識
此篇重點會著墨在Modbus的reply,
再帶到一些跟Modbus Specification有關的內容

以下會先提及一些libmodbus Header file,
主要會說明modbus_reply函式

會選擇modbus_reply()來探討,
主要原因為透由modbus回覆,可更清楚modbus行為與相關程式實作的對應關係

Learning Header file

reference:stephane/libmodbus/src/modbus.h
Modbus function code

#define MODBUS_FC_READ_COILS 0x01 #define MODBUS_FC_READ_DISCRETE_INPUTS 0x02 //... #define MODBUS_FC_MASK_WRITE_REGISTER 0x16 #define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17

定義Modbus function code,
function code就是用來定義modbus行為,
如0x01就是指讀取遠端設備的輸出值。

quantity of bit, register, input

/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) * Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0) * (chapter 6 section 11 page 29) * Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0) */ #define MODBUS_MAX_READ_BITS 2000 #define MODBUS_MAX_WRITE_BITS 1968

原著作者很貼心,還附上Spectification的出處來源
定義PDU(protocol data unit的)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

(Modbus對資料格式的框架圖示)

小結:
FC 0x01 -> quanlity: 1 to 2000 Read Coil
FC 0x02 -> quanlity: 1 to 2000 Read Discrete Input
FC 0x03 -> quanlity: 1 to 125 Read Holding Register
FC 0x04 -> quanlity: 1 to 125 Read Input Register
FC 0x05 -> quanlity: 1 to 255 Write Single Coil
FC 0x06 -> quanlity: 1 to 65535 Write Single Register
FC 0x10 -> quanlity: 1 to 123 Write Multiple register
FC 0x17 -> quanlity: 1 to 125/121 Read/Write Multiple register

referenceModbus_Application_Protocol_V1_1b.pdf

以上,對於libmodbus程式位置與modbus功能碼有一些基礎的對應關係,
那麼,接著往下看reply函式


reference:stephane/libmodbus/src/modbus.c

int modbus_reply(modbus_t *ctx, const uint8_t *req,
                 int req_length, modbus_mapping_t *mb_mapping)

在這個函式裡面會利用switch..case..來做一些進入哪個function code的判斷

MODBUS_FC_READ_COILS -> 0x01
MODBUS_FC_READ_DISCRETE_INPUTS -> 0x02
(小巧思,共用程式碼,故僅寫在0x02的case裡)

MODBUS_FC_READ_HOLDING_REGISTERS -> 0x03
MODBUS_FC_READ_INPUT_REGISTERS -> 0x04
(小巧思,共用程式碼,故僅寫在0x04的case裡)

MODBUS_FC_WRITE_SINGLE_COIL -> 0x05

MODBUS_FC_WRITE_SINGLE_REGISTER -> 0x06

MODBUS_FC_WRITE_MULTIPLE_COILS-> 0x0F

MODBUS_FC_WRITE_MULTIPLE_REGISTERS -> 0x10

MODBUS_FC_REPORT_SLAVE_ID -> 0x11

MODBUS_FC_READ_EXCEPTION_STATUS -> 0x07

MODBUS_FC_MASK_WRITE_REGISTER -> 0x16

MODBUS_FC_WRITE_AND_READ_REGISTERS -> 0x17

作者是怎麼做判斷的呢?

為什麼寫到這裡就斷了 我不是富堅阿~ 9/9復刊
作者利用switch..case..去回應function code

int offset; int slave; int function; uint16_t address; //... offset = ctx->backend->header_length; slave = req[offset - 1]; function = req[offset]; address = (req[offset + 1] << 8) + req[offset + 2]; //... /* Data are flushed on illegal number of values errors. */ switch (function)