0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Modbus TCP編程與實(shí)驗(yàn)

瑞薩MCU小百科 ? 來源:瑞薩MCU小百科 ? 2025-01-03 09:27 ? 次閱讀

11.7 Modbus TCP編程與實(shí)驗(yàn)

本課程并沒有支持Modbus TCP協(xié)議的傳感器,所以使用將會編寫2個程序:

①modbus_server_tcp.c:模擬一個Modbus TCP傳感器

②modbus_client_tcp.c:操作傳感器

程序結(jié)構(gòu)如下圖所示:

9c14dd12-c8be-11ef-9310-92fbcf53809c.png

在硬件上無需進(jìn)行任何特殊的連接。

本節(jié)源碼位于如下目錄:

9c34e8b4-c8be-11ef-9310-92fbcf53809c.png

下面以情景分析的方法講解代碼。假設(shè)在開發(fā)板上執(zhí)行如下命令:

左右滑動查看完整內(nèi)容

# ./modbus_server_tcp 127.0.0.1 &
# ./modbus_client_tcp 127.0.0.1 led1 on

11.7.1 server初始化與等待連接

在“modbus_server_tcp.c”中,代碼如下:

左右滑動查看完整內(nèi)容

41 ctx = modbus_new_tcp(argv[1], 1502);
42 if (ctx == NULL) {
43 fprintf(stderr, "Unable to allocate libmodbus context
");
44 return -1;
45 }
46
47 //modbus_set_slave(ctx, SERVER_ID);
48
49 mb_mapping = modbus_mapping_new_start_address(0,
50 NB_BITS, /* 5 個 DO 寄存器,對應(yīng) beep1,beep2,led1,led2,led3 */
51 0,
52 NB_INPUT_BITS,
53 0,
54 NB_REGISTERS,
55 0,
56 NB_INPUT_REGISTERS); /* 2 個 AI 寄存器,對應(yīng)溫度和濕度 */
57 memset(mb_mapping->tab_bits, 0, NB_BITS);
58 memset(mb_mapping->tab_input_registers, 0, NB_INPUT_REGISTERS*2);
59
60 memset(old_bits, 0, NB_BITS);
61 memset(old_regs, 0, NB_INPUT_REGISTERS*2);
62
63 s = modbus_tcp_listen(ctx, 1);
64 modbus_tcp_accept(ctx, &s);

第41行:分配一個modbus_t結(jié)構(gòu)體,里面含有IP和端口。

第47行:設(shè)置自己的傳感器地址,這行被注釋掉了,在Modbus TCP協(xié)議里,即使客戶端使用不同的設(shè)備地址發(fā)來請求,server端都會接收到這些所有請求(它忽略設(shè)備地址)。

第49~56行:分配Modbus寄存器。它根據(jù)《11.5.2 傳感器點(diǎn)表》來模擬一個傳感器。

第57~58行:設(shè)置DO、AI寄存器初始值為0。

第60~61行:設(shè)置2個數(shù)組的值為0,這2個數(shù)組將用來跟Modbus寄存器進(jìn)行比較,這樣才能知道Client 程序有沒有修改這些值。

第63~64行:這是跟Modbus RTU協(xié)議不同的地方,它們初始化socket,等待客戶端連接。

11.7.2 client初始化與發(fā)起連接

在“modbus_client_tcp.c”中,代碼如下:

左右滑動查看完整內(nèi)容

33 ctx = modbus_new_tcp(argv[1], 1502);
34 if (ctx == NULL) {
35 fprintf(stderr, "Unable to allocate libmodbus context
");
36 return -1;
37 }
38
39 modbus_set_slave(ctx, SERVER_ID);
40
41 if (modbus_connect(ctx) == -1) {
42 fprintf(stderr, "Connection failed: %s
", modbus_strerror(errno));
43 modbus_free(ctx);
44 return -1;
45 }

第33行:分配一個modbus_t結(jié)構(gòu)體,設(shè)置IP和端口。

第39行:設(shè)置要訪問的Modbus傳感器地址。

第41行:發(fā)出連接請求。

11.7.3 server等待請求

在“modbus_server_tcp.c”中,代碼如下:

左右滑動查看完整內(nèi)容

66 while (1)
67 {
68 do {
69 rc = modbus_receive(ctx, query);
70 /* Filtered queries return 0 */
71 } while (rc == 0);
72

第69行:等待client發(fā)來請求。

11.7.4 client 發(fā)出請求

在“modbus_client_tcp.c”中,代碼如下:

左右滑動查看完整內(nèi)容

65 if (!strcmp(argv[2], "beep1"))
66 addr = 0;
67 if (!strcmp(argv[2], "beep2"))
68 addr = 1;
69 if (!strcmp(argv[2], "led1"))
70 addr = 2;
71 if (!strcmp(argv[2], "led2"))
72 addr = 3;
73 if (!strcmp(argv[2], "led3"))
74 addr = 4;
75
76 if (addr == -1)
77 {
78 usage(argv[0]);
79 return -1;
80 }
81
82 if (!strcmp(argv[3], "on"))
83 status = 1;
84 else
85 status = 0;
86
87 rc = modbus_write_bit(ctx, addr, status);
88 if (rc == 1)
89 {
90 printf("modbus_write_bit ok
");
91 }
92 else
93 {
94 printf("modbus_write_bit err: %d, %s
", rc, strerror(errno));
95 }

第65~85行:根據(jù)參數(shù)設(shè)置addr、status。

第87行:發(fā)出“寫AO寄存器的請求”。

11.7.5 server處理請求并回應(yīng)

在“modbus_server_tcp.c”中,代碼如下:

左右滑動查看完整內(nèi)容

75 if (rc >= 0) {
76
77 printf("Get query for UID %d
", query[6]);
78
79 /* 使用隨機(jī)數(shù)模擬溫度、濕度 */
80 mb_mapping->tab_input_registers[0] = rand() % 1000; /* 溫度,單位:0.1C */
81 mb_mapping->tab_input_registers[1] = rand() % 1000; /* 濕度,單位:0.1% */
82
83 rc = modbus_reply(ctx, query, rc, mb_mapping);
84 }
85 if (rc == -1) {
86 printf("Connection closed!
");
87 modbus_close(ctx);
88 modbus_tcp_accept(ctx, &s);
89 }
90
91 /* 根據(jù) client 設(shè)置的數(shù)值,假裝操作蜂鳴器和 LED */
92 if (mb_mapping->tab_bits[0] != old_bits[0])
93 {
94 printf("set beep1 %s
", mb_mapping->tab_bits[0] ? "on" : "off");
95 old_bits[0] = mb_mapping->tab_bits[0];
96 }
97
98 if (mb_mapping->tab_bits[1] != old_bits[1])
99 {
100 printf("set beep2 %s
", mb_mapping->tab_bits[1] ? "on" : "off");
101 old_bits[1] = mb_mapping->tab_bits[1];
102 }
103
104 if (mb_mapping->tab_bits[2] != old_bits[2])
105 {
106 printf("set led1 %s
", mb_mapping->tab_bits[2] ? "on" : "off");
107 old_bits[2] = mb_mapping->tab_bits[2];
108 }
109
110 if (mb_mapping->tab_bits[3] != old_bits[4])
111 {
112 printf("set led2 %s
", mb_mapping->tab_bits[4] ? "on" : "off");
113 old_bits[3] = mb_mapping->tab_bits[4];
114 }
115
116 if (mb_mapping->tab_bits[4] != old_bits[4])
117 {
118 printf("set led3 %s
", mb_mapping->tab_bits[4] ? "on" : "off");
119 old_bits[4] = mb_mapping->tab_bits[4];
120 }

第77行:打印client端發(fā)來的請求包里的“設(shè)備地址”,你可以根據(jù)這個“設(shè)備地址”去操作不同的設(shè)備,本程序未使用它。

第80~81行:使用隨機(jī)數(shù)填充AO寄存器模擬溫濕度。如果client讀取溫濕度的話,下面第83行的“modbus_reply”就會回復(fù)這些溫濕度值。

第83行:使用“modbus_reply”發(fā)出回復(fù)包給client。

第85~89行:如果出錯,重新等待client建立連接。

第91~120行:根據(jù)client發(fā)來的數(shù)據(jù),操作硬件(這里僅僅是打印信息)。

11.7.6 上機(jī)實(shí)驗(yàn)

把代碼上傳到Ubuntu。

然后,在Ubuntu下執(zhí)行如下命令進(jìn)行編譯:

左右滑動查看完整內(nèi)容

$ source /opt/remi-sdk/environment-setup-aarch64-poky-linux
$ make
$ scp modbus_client_tcp root@192.168.5.9:/home/root
$ scp modbus_server_tcp root@192.168.5.9:/home/root

最后,在開發(fā)板上執(zhí)行如下命令(先執(zhí)行 modbus_server):

左右滑動查看完整內(nèi)容

# cd /home/root
# ./modbus_server_tcp 127.0.0.1 &
# ./modbus_client_tcp 127.0.0.1 led1 on
Get query for UID 4
set led1 on
modbus_write_bit ok
Connection closed!
# ./modbus_client_tcp 127.0.0.1 read
Get query for UID 4
Temprature = 38.6C, Humity = 49.2%
Get query for UID 4
Temprature = 64.9C, Humity = 42.1%
Get query for UID 4
Temprature = 36.2C, Humity = 2.7%

需要產(chǎn)品及方案支持

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 傳感器
    +關(guān)注

    關(guān)注

    2551

    文章

    51184

    瀏覽量

    754334
  • MODBUS
    +關(guān)注

    關(guān)注

    28

    文章

    1810

    瀏覽量

    77069
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3621

    瀏覽量

    93795
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1370

    瀏覽量

    79126

原文標(biāo)題:Modbus TCP編程與實(shí)驗(yàn) - RZ MPU工業(yè)控制教程連載(44)

文章出處:【微信號:瑞薩MCU小百科,微信公眾號:瑞薩MCU小百科】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Modbus TCP通信報(bào)文解析

    Modbus TCP是在TCP/IP網(wǎng)絡(luò)上運(yùn)行的Modbus的實(shí)現(xiàn),旨在允許Modbus ASCII/RTU協(xié)議在基于
    發(fā)表于 09-20 15:55 ?3w次閱讀
    <b class='flag-5'>Modbus</b> <b class='flag-5'>TCP</b>通信報(bào)文解析

    LabVIEW Modbus TCP通訊

    觸摸屏與上位機(jī)通訊,HMI支持Modbus TCP,上位機(jī)是LabVIEW編程實(shí)現(xiàn),下載了Modbus library,但是無法通訊,請高手指教 1、硬件如何連接,是不是用網(wǎng)線直接將電
    發(fā)表于 12-14 08:49

    Modbus TCP轉(zhuǎn)Modbus RTU的實(shí)現(xiàn)

    使用ZLSN2040、NETCOM2040實(shí)現(xiàn)Modbus TCPModbus RTU的轉(zhuǎn)化。1.Modbus TCP
    發(fā)表于 08-10 10:04

    Modbus TCP如何使用

    大家好。我有ApIC32 MX575 F512L,它使用了Modbus TCP在從配置(它完美地工作)。現(xiàn)在,我需要實(shí)現(xiàn)另一個軟件(也就是FPIC32 MX575 F512L),使主板工作在主模式中
    發(fā)表于 01-08 14:25

    如何快速實(shí)現(xiàn)Modbus RTU和Modbus TCP協(xié)議轉(zhuǎn)換?

    采集多種設(shè)備邊緣計(jì)算過濾、報(bào)警、跳變、公式、本地編程等云端適配接入各種平臺,支持定制化適配遠(yuǎn)程運(yùn)維遠(yuǎn)程管理、遠(yuǎn)程運(yùn)維網(wǎng)關(guān)及現(xiàn)場設(shè)備特色功能串口轉(zhuǎn)發(fā)、Modbus TCP轉(zhuǎn)發(fā)、設(shè)備校時、防拆鎖定
    發(fā)表于 08-18 18:36

    Modbus/TCP通訊配置

    MODBUSTCP 是簡單的、中立廠商的用于管理和控制自動化設(shè)備的MODBUS 系列通訊協(xié)議的派生產(chǎn)品,它覆蓋了使用TCP/IP 協(xié)議的Intranet和Internet環(huán)境中MODBUS 報(bào)文
    發(fā)表于 09-30 09:13 ?38次下載
    <b class='flag-5'>Modbus</b>/<b class='flag-5'>TCP</b>通訊配置

    Modbus TCP通訊協(xié)議概述

    1? Modbus TCP通訊概述 MODBUS/TCP是簡單的、中立廠商的用于管理和控制自動化設(shè)備的MODBUS系列訊協(xié)議的派生產(chǎn)品,顯而
    的頭像 發(fā)表于 01-04 17:51 ?3w次閱讀
    <b class='flag-5'>Modbus</b> <b class='flag-5'>TCP</b>通訊協(xié)議概述

    Modbus RTU和Modbus TCP的區(qū)別

    Modbus RTU和Modbus TCP的區(qū)別: 1.概念不同:MODBUS是一種標(biāo)準(zhǔn)的工業(yè)控制數(shù)據(jù)交換協(xié)議,可以通過RTU和ASCII交換協(xié)議數(shù)據(jù)。RTU通過二進(jìn)制數(shù)據(jù)直接傳輸數(shù)據(jù)
    發(fā)表于 08-03 17:00 ?5.4w次閱讀

    S7-1200 Modbus TCP通信指令塊編程教程

    S7-1200 Modbus TCP通信指令塊編程教程免費(fèi)下載。
    發(fā)表于 03-28 16:08 ?10次下載

    Modbus TCP常見問題

    Modbus RTU和 Modbus TCP的區(qū)別?
    的頭像 發(fā)表于 12-19 14:57 ?3361次閱讀

    ModBus RTU 與 ModBus TCP

    一、兩個密切相關(guān)的協(xié)議:RTU 與 TCP ModBus RTU和ModBus TCP作為ModBus協(xié)議的兩個主要變體,傳統(tǒng)上,
    的頭像 發(fā)表于 02-07 10:05 ?3035次閱讀

    如何仿真Modbus_TCP

    仿真Modbus_TCP
    的頭像 發(fā)表于 02-07 10:16 ?5045次閱讀
    如何仿真<b class='flag-5'>Modbus_TCP</b>

    Ethernet/IP轉(zhuǎn)Modbus TCP網(wǎng)關(guān)

    Ethernet/IP轉(zhuǎn)Modbus TCP網(wǎng)關(guān),YC-EIP-TCP工業(yè)級EtherNet/IP 網(wǎng)關(guān),支持ModBus主從站,即插即用 無需編程
    的頭像 發(fā)表于 02-27 17:50 ?492次閱讀
    Ethernet/IP轉(zhuǎn)<b class='flag-5'>Modbus</b> <b class='flag-5'>TCP</b>網(wǎng)關(guān)

    EtherCAT轉(zhuǎn)Modbus TCP協(xié)議網(wǎng)關(guān)(JM-ECT-TCP

    JM-ECT-TCP網(wǎng)關(guān)實(shí)現(xiàn)EtherCAT網(wǎng)絡(luò)與Modbus TCP網(wǎng)絡(luò)之間的數(shù)據(jù)通訊,即將Modbus TCP設(shè)備轉(zhuǎn)換為EtherCAT
    的頭像 發(fā)表于 09-07 17:05 ?354次閱讀
    EtherCAT轉(zhuǎn)<b class='flag-5'>Modbus</b> <b class='flag-5'>TCP</b>協(xié)議網(wǎng)關(guān)(JM-ECT-<b class='flag-5'>TCP</b>)

    MODBUS TCP 轉(zhuǎn) CANOpen

    產(chǎn)品概述 SG-TCP-COE-210 網(wǎng)關(guān)可以實(shí)現(xiàn)將 CANOpen 接口設(shè)備連接到 MODBUS TCP 網(wǎng)絡(luò)中。用戶不需要了解具體的 CANOpen 和 Modbus
    的頭像 發(fā)表于 09-24 13:59 ?286次閱讀
    <b class='flag-5'>MODBUS</b> <b class='flag-5'>TCP</b> 轉(zhuǎn) CANOpen