一宣蔚、以太網(wǎng)(modbus tcp/ip)
Modbus設(shè)備可分為主站(poll)和從站(slave)肚逸。主站只有一個,從站有多個聘萨,主站向各從站發(fā)送請求幀竹椒,從站給予響應(yīng)。在使用TCP通信時米辐,主站為client端胸完,主動建立連接;從站為server端翘贮,等待連接赊窥。
image.png
二、所需的libmobus API(server端)
- 使用modbus_new_tcp創(chuàng)建一個modbus的上下文狸页,ip地址為開發(fā)板自身的ip
modbus_t *ctx = modbus_new_tcp(const char *ip_address, int port); //開發(fā)板ip自行修改锨能,port常用502。
- 地址映射
使用modbus_mapping_new_start_address初始化從站地址的映射肴捉,即線圈狀態(tài)腹侣、離散輸入、保持寄存器齿穗、輸入寄存器的首地址和個數(shù)的映射傲隶。該首地址供主站進(jìn)行尋址讀取數(shù)值或?qū)懭霐?shù)值。
modbus_mapping_t *mb_mapping = modbus_mapping_new_start_address(
unsigned int start_bits, unsigned int nb_bits,
unsigned int start_input_bits, unsigned int nb_input_bits,
unsigned int start_registers, unsigned int nb_registers,
unsigned int start_input_registers, unsigned int nb_input_registers);
完成mb_mapping的映射后需要綁定table的地址空間窃页,即給相應(yīng)指針開辟空間跺株。該空間為后續(xù)寫入和讀取數(shù)據(jù)使用。
/* map 地址與存儲空間 */
mb_mapping->tab_bits = UT_BITS_TAB;
mb_mapping->tab_input_bits = UT_INPUT_BITS_TAB;
mb_mapping->tab_registers = UT_REGISTERS_TAB;
mb_mapping->tab_input_registers = UT_INPUT_REGISTERS_TAB;
3.監(jiān)聽連接
使用以上創(chuàng)建的modbus tcp server監(jiān)聽客戶的接入
int socket = modbus_tcp_listen(modbus_t *ctx, int nb_connection);
modbus_tcp_accept(modbus_t *ctx, int *s);
4.阻塞接收數(shù)據(jù)
接收主站的請求數(shù)據(jù)(原始數(shù)據(jù))并保存在req指定的空間中脖卖。
modbus_receive(modbus_t *ctx, uint8_t *req);
5.響應(yīng)接收
modbus_reply會自動解析modbus請求并做響應(yīng)
modbus_reply(modbus_t *ctx, const uint8_t *req,
int req_length, modbus_mapping_t *mb_mapping);
三乒省、從站(server)程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus/modbus.h>
int main(void)
{
int socket;
modbus_t *ctx;
modbus_mapping_t *mb_mapping;
ctx = modbus_new_tcp("127.0.0.1", 1502); //開發(fā)板ip自行修改
/* modbus_set_debug(ctx, TRUE); */
mb_mapping = modbus_mapping_new_start_address(
UT_BITS_ADDRESS, UT_BITS_NB,
UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX,
UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB);
if (mb_mapping == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
socket = modbus_tcp_listen(ctx, 1);
modbus_tcp_accept(ctx, &socket);
for (;;) {
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
int rc;
rc = modbus_receive(ctx, query);
if (rc != -1) {
/* rc is the query size */
modbus_reply(ctx, query, rc, mb_mapping);
printf("In the loop \n");
} else {
/* Connection closed by the client or error */
break;
}
}
printf("Quit the loop: %s\n", modbus_strerror(errno));
modbus_mapping_free(mb_mapping);
modbus_close(ctx);
modbus_free(ctx);
return 0;
}