Khái niệm về giao thức Modbus RTU kết nối phần cứng cho giao thức này đã được mình trình bày trong bài viết tại đây. Còn trong bài viết này, mình sẽ giới thiệu về cấu trúc của một khung truyền giao thức Modbus RTU.

Modbus RTU hoạt động dựa trên nguyên tắc master – slave, một thiết bị master sẽ điều khiển một hoặc nhiều thiết bị slave. Slave không thể truyền dữ liệu tự động được mà cần phải được Master yêu cầu. Master sẽ ghi hoặc đọc dữ liệu trong các thanh ghi của thiết bị Slave. Mỗi Slave có một địa chỉ 8 bit và không trùng với các Slave khác. 

I/CẤU HÌNH UART SỬ DỤNG CHO MODBUS RTU

Giao thức Modbus được sử dụng phổ biến nhất là Modbus RTU trên đường truyền vật lý RS-485. Modbus RTU là một giao thức truyền nối tiếp tương đối đơn giản dựa trên giao thức UART. Dữ liệu được truyền theo byte, tốc độ baudrate thường được cấu hình trong khoảng từ 1200bps đền 115200bps. Tham khảo thêm về giao thức truyền thông nối tiếp UART tại đây

Một bảng tin UART chuẩn sử dụng trong các thiết bị Modbus RTU sẽ có cấu hình khung truyền như sau: 1 bit bắt đầu; 8bit dữ liệu, trong đó bit có trọng số thấp nhất sẽ được gửi đi trước; có thể sử dụng 1 bit kiểm tra chẵn lẻ (parity) hoặc không; 1 bit stop nếu bit parity được sử dụng hoặc 2 bit stop nếu không sử dụng parity. 

Tuy nhiên, cũng có môt số thiết bị hỗ trợ khung truyền 10 bit – 8N1: 1 start bit, 8 bit data, không sử dụng bit parity, 1 bit stop.

II/CẤU TRÚC MỘT BẢNG TIN MODBUS

Một bảng tin Modbus được xây dựng dựa trên các bảng tin UART.  Các bảng tin Modbus khác nhau phải cách nhau một khoản thời gian được gọi là “silent interval” bằng ít nhất 3.5 thời gian một bảng tin UART.  Trong một bảng tin Modbus, các kí tự (bảng tin UART) phải được truyền liên tục. Nếu có môt khoảng “slient interval” lớn hơn 1.5 kí tự xuất hiện trong bảng tin, thì bảng tin đó sẽ được cho là không hoàn thành và thiết bị nhận sẽ bỏ qua nó.

Ví dụ cấu hình UART tốc độ 9600bps, 1 packet 10 bit thì sẽ truyền được 9600 kí tư trong 1 giây. Vậy thời gian để truyền 1 kí tự là 1000ms/9600/10 = 1.04167ms, khoảng thời gian bắt đầu một khung truyền sẽ phải lớn hơn thời gian truyền 3.5 kí tự là 3.5*1.04167 = 3.65ms

Bảng tin từ thiết bị Master gọi là Query, còn bảng tin Slave phản hồi được gọi là Response. Master có thể gửi bảng tin cho toàn bộ Slave thông qua bảng tin Broadcast, khi Slave nhận được bảng tin này thì không cần phản hồi ngược lại.

Bảng tin Query và Response sẽ có 4 trường: Device Address, Function Code, Data Bytes và Error Check.

  • Address Field: Trường địa chỉ này này giúp master xác định được nó đang làm việc là slave nào.  Các Slave sẽ được gắn địa chỉ từ 1-247 và phải đảm bảo không có Slave nào trùng địa chỉ với nhau.  Trường này nằm ở vị trí đầu tiên trong một bảng tin Modbus và có kích cỡ 8 bit.
    • Khi Master gửi Query thì thông tin đầu tiên sẽ là địa chỉ Slave nó muốn làm việc.
    • Trường Device Address của bảng tin Response cũng sẽ phải đúng địa chỉ của Slave đó để Master biết Slave nào gửi phản hồi.
    • Khi trường Device Address trong bảng tin Query của Master có địa chỉ 0x00, tức đó là bảng tin Broadcast, tất cả các Slave đều có thể nhận bảng tin đó.
  • Function Code: Trường này đi theo sau trường Device Address và có kích thước 8 bit, nó sẽ chỉ định hành động Master yêu cầu Slave thực hiện như đọc/ghi một hoặc nhiều dữ liệu trong thiết bị. Dữ liệu trong các thiết bị Modbus sẽ chia thành các kiểu dữ liệu khác nhau và nằm trong các Register Type như dưới.  Với các tin nhắn Response thông thường, Slave chỉ cần phản hồi đúng Function Code mà Master đã gửi.

  • Data: Trường Data của bảng tin Query chứa các thông tin bổ sung mà Slave phải sử dụng để thực hiện hành động theo Function Code. Còn đối với tin nhắn Response, trường Data sẽ chứa dữ liệu được yêu cầu bởi Master.
  • Error Check: Trường này dùng để kiểm tra lỗi khung truyền, nó chiếm 16-bit tương ứng với 2 byte. Modbus RTU sử dụng phương pháp Cyclical Redundancy Check. (tham khảo thêm tại.

III/CÁC KIỂU DỮ LIỆU 

Có 4 kiểu dữ liệu trong Modbus:

  • Coil (hay Discrete Output)
  • Discrete Input (hay Status Input)
  • Input Register
  • Holding Register.

Trong đó Coil và Discrete Input có kích thước 1 bit, giá trị của nó có thể là ON (1) hoặc OFF (0). Discrete Input thường chứa trạng thái của một số đầu vào vật lý, dữ liệu của chúng chỉ có thể đọc . Phần còn lại đại diện cho các đầu ra, gọi là Discrete Output Coils, chứa trạng thái của các các đầu ra vật lý, dữ liệu của chúng có thể đọc hoặc ghi.

Đối với các Register, chúng là những thanh ghi 16 bit. Giá trị của chúng nằm trong khoảng 0x0000 – 0xFFFF theo mã hexadecimal. Register được sử dụng phổ biến nhất là Holding Register, dữ liệu của chúng có thể được đọc hoặc ghi, có chức năng lưu trữ dữ liệu cho các thiết bị. Một kiểu khác là Analog Input Register, chỉ chứa dữ liệu đầu vào tương tự, người dùng chỉ có thể đọc dữ liệu từ loại Register này.

Việc một thiết bị cụ thể nào đó có bao gồm tất cả các loại dữ liệu này hay không hay bao gồm những loại dữ liệu nào tùy thuộc vào nhà sản xuất thiết bị.

Dữ liệu được lưu trong Slave sẽ được chia như sau:

Mỗi kiểu dữ liệu sẽ có 9999 giá trị. Có thể thấy địa chỉ dữ liệu của các kiểu dữ liệu đều từ  0x0000 đến 0x270E. Để phân biệt được chúng thì cần thêm các offset.

Ví dụ Holding Register đầu tiên với Register Number là 40001, thì Data Address của nó là 0 (tức 0x0000). Sự khác nhau giữa 2 giá trị này gọi là offset.

Mỗi kiểu dữ liệu sẽ có một offset khác nhau:

  • Với Coil thì offset = 1
  • Discrete Input có offset = 10001
  • Input Register có offset = 30001
  • Holding Register có offset = 40001.

Coil thứ 201 có giá trị là 1, tức là dữ liệu Coil tại địa chỉ 0xC8 có giá trị là 0x01.
Register thứ 40015 có giá trị 10000, tức là dữ liệu Holding Register tại địa chỉ 0x000F chứa giá trị 0x2710.

Như vậy qua bài viết này mình đã giới thiệu về khung truyền dữ liệu Modbus, các kiểu dữ liệu sử dụng trong Modbus. Bài viết sau mình trình bày với một ví dụ giao tiếp giữa máy tính với một cảm biến sử dụng chuẩn Modbus RTU.

Tài liệu tham khảo giao thức Modbus tại đây

 

Chúc các bạn thành công!

Đức Thắng

Tìm hiểu về khung truyền Modbus RTU
Facebook Comments: