forked from xuos/xiuos
feat add modbus tcp protocol for control framework
This commit is contained in:
parent
9b334f90e0
commit
56a014fe98
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 4g_app.c
|
||||
* @brief support get data from and send data to 4g server
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.12
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
#include <adapter.h>
|
||||
|
||||
static uint8_t adapter_4g_status = 0;
|
||||
static pthread_t recv_4g_heart_task;
|
||||
struct Adapter *adapter_4g;
|
||||
|
||||
static const uint8_t server_addr[] = "xxx.xxx.xxx.xxx";
|
||||
static const uint8_t server_port[] = "xxx";
|
||||
|
||||
#define ADAPTER_4G_HEART "HEART"
|
||||
|
||||
int Adapter4GConnectFunction(struct Adapter *adapter, uint8_t reconnect)
|
||||
{
|
||||
int ret = 0;
|
||||
int baud_rate = BAUD_RATE_115200;
|
||||
|
||||
if (1 != reconnect) {
|
||||
ret = AdapterDeviceOpen(adapter);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = AdapterDeviceConnect(adapter, CLIENT, server_addr, server_port, IPV4);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
AdapterDeviceClose(adapter);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Adapter4gSend(uint8_t *send_data, size_t length)
|
||||
{
|
||||
if (adapter_4g_status) {
|
||||
AdapterDeviceSend(adapter_4g, send_data, length);
|
||||
}
|
||||
}
|
||||
|
||||
static void *Receive4gHeartTask(void* parameter)
|
||||
{
|
||||
char recv_msg[16] = {0};
|
||||
ssize_t recv_length = 0;
|
||||
uint8_t net_status_cnt = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
SetTaskStatus(0x01);
|
||||
|
||||
if (net_status_cnt > 5) {
|
||||
adapter_4g_status = 0;
|
||||
|
||||
while (Adapter4GConnectFunction(adapter_4g, 1) < 0) {
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
net_status_cnt = 0;
|
||||
}
|
||||
|
||||
adapter_4g_status = 1;
|
||||
|
||||
recv_length = AdapterDeviceRecv(adapter_4g, recv_msg, 6);
|
||||
if (recv_length > 0) {
|
||||
//if (0 == strcmp(recv_msg, ADAPTER_4G_HEART)) {
|
||||
net_status_cnt = 0;
|
||||
//}
|
||||
} else {
|
||||
printf("4G recv heart error re-recv cnt %d\n", net_status_cnt);
|
||||
net_status_cnt++;
|
||||
}
|
||||
memset(recv_msg, 0, sizeof(recv_msg));
|
||||
}
|
||||
}
|
||||
|
||||
int Adapter4GActive(void)
|
||||
{
|
||||
int ret = 0;
|
||||
adapter_4g = AdapterDeviceFindByName(ADAPTER_4G_NAME);
|
||||
|
||||
#ifdef ADAPTER_EC200T
|
||||
adapter_4g->socket.socket_id = 0;
|
||||
|
||||
ret = Adapter4GConnectFunction(adapter_4g, 0);
|
||||
if (ret < 0) {
|
||||
printf("Adapter4GConnect failed %d\n", ret);
|
||||
}
|
||||
|
||||
adapter_4g_status = 1;
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = 22;
|
||||
attr.stacksize = 2048;
|
||||
|
||||
PrivTaskCreate(&recv_4g_heart_task, &attr, &Receive4gHeartTask, NULL);
|
||||
PrivTaskStartup(&recv_4g_heart_task);
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := 4g_app.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -10,6 +10,10 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
||||
|
||||
ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y)
|
||||
SRC_DIR += 4g_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
SRC_DIR += socket_demo
|
||||
endif
|
||||
|
|
|
@ -18,6 +18,47 @@
|
|||
* @date 2022.9.27
|
||||
*/
|
||||
|
||||
|
||||
#include <control.h>
|
||||
|
||||
extern int Adapter4GActive(void);
|
||||
|
||||
void ControlFx3uTest(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
int read_data_length = 0;
|
||||
uint8_t read_data[128] = {0};
|
||||
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
Adapter4GActive();
|
||||
#endif
|
||||
|
||||
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||
if (NULL == modbus_tcp_protocol) {
|
||||
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||
|
||||
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||
ControlProtocolOpen(modbus_tcp_protocol);
|
||||
|
||||
for (;;) {
|
||||
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||
if (read_data_length) {
|
||||
for (j = 0; j < read_data_length; j ++) {
|
||||
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
memset(read_data, 0, sizeof(read_data));
|
||||
PrivTaskDelay(10000);
|
||||
}
|
||||
|
||||
//ControlProtocolClose(modbus_tcp_protocol);
|
||||
}
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(ControlFx3uTest, Mitsubishi fx3u Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
config CONTROL_PROTOCOL_MODBUS_TCP
|
||||
bool "Using modbus_tcp control protocol"
|
||||
default n
|
||||
if CONTROL_PROTOCOL_MODBUS_TCP
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig"
|
||||
endif
|
||||
|
||||
config CONTROL_PROTOCOL_MODBUS_UART
|
||||
bool "Using modbus_uart control protocol"
|
||||
default n
|
||||
|
||||
if CONTROL_PROTOCOL_MODBUS_UART
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/modbus_uart/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modbus_tcp.h
|
||||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_TCP_H
|
||||
#define MODBUS_TCP_H
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MODBUS_TCP_UNIT_ID 0x00
|
||||
#define MODBUS_TCP_READ_CMD_LENGTH 0x0C
|
||||
#define MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH 0x0C
|
||||
|
||||
#define MODBUS_TCP_WRITE_MULTI_HEAD 0x07
|
||||
|
||||
typedef enum
|
||||
{
|
||||
READ_COIL_STATUS = 0x01, //read coil cmd
|
||||
READ_INPUT_STATUS = 0x02, //read input colr cmd
|
||||
READ_HOLDING_REGISTER = 0x03, //read register info cmd
|
||||
READ_INPUT_REGISTER = 0x04, //read input register cmd
|
||||
WRITE_SINGLE_COIL = 0x05, //write coil cmd
|
||||
WRITE_SINGLE_REGISTER = 0x06, //write single register cmd
|
||||
WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd
|
||||
WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd
|
||||
}ModbusTcpFunctionCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BasicPlcDataInfo base_data_info;
|
||||
ModbusTcpFunctionCode function_code;
|
||||
}ModbusTcpDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModbusTcpDataInfo data_info;
|
||||
|
||||
UniformValueType value_type;
|
||||
char value_name[20];
|
||||
|
||||
uint16_t start_address;
|
||||
uint16_t quantity;
|
||||
}ModbusTcpReadItem;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -15,6 +15,436 @@
|
|||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
* @date 2022.12.09
|
||||
*/
|
||||
|
||||
#include <modbus_tcp.h>
|
||||
|
||||
/*using cirtular area to receive write-data*/
|
||||
#define CA_DATA_LENGTH 512
|
||||
struct CircularAreaApp *g_write_data;
|
||||
|
||||
static BasicSocketPlc plc_socket = {0};
|
||||
static uint8_t recv_buff[1024] = {0};
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Data Transform from Receive Buffer To Control-Data
|
||||
* @param p_read_item - read item pointer
|
||||
* @param recv_buff - receive buff
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff)
|
||||
{
|
||||
uint8_t *data_buffer;
|
||||
ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info);
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code;
|
||||
uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data;
|
||||
|
||||
printf("Receive data is ");
|
||||
|
||||
uint8_t bytes_count = recv_buff[8];
|
||||
data_buffer = recv_buff + 9;//remove head data
|
||||
|
||||
if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) {
|
||||
for (int i = 0;i < bytes_count;i ++) {
|
||||
for (int j = 0;j < 8;j ++) {
|
||||
if ((i * 8 + j) < p_read_item->quantity) {
|
||||
*(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0;
|
||||
printf("0x%x", *(uint8_t *)(p_data + i * 8 + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint16_t i = 0; i < quantity; i ++) {
|
||||
((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1];
|
||||
printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Get Data From Socket
|
||||
* @param socket - socket
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item)
|
||||
{
|
||||
uint8_t try_count = 0;
|
||||
int32_t write_error = 0;
|
||||
|
||||
ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_modbus_tcp_data_info->base_data_info);
|
||||
|
||||
if (!p_base_data_info->command_ready) {
|
||||
//command not ready, just return
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
while (try_count < 10) {
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
try_count++;
|
||||
|
||||
write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
if (write_error < 0) {
|
||||
printf("Write socket error, errno is %d!", errno);
|
||||
} else {
|
||||
PrivTaskDelay(20);
|
||||
|
||||
int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff));
|
||||
if (recv_length < 0) {
|
||||
printf("Read socket error, errno is %d!", errno);
|
||||
} else {
|
||||
ControlPrintfList("RECV", recv_buff, recv_length);
|
||||
return ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
}
|
||||
}
|
||||
|
||||
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
printf("Send command failed, errno is %d!", errno);
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Data Info Init
|
||||
* @param p_read_item - read item pointer
|
||||
* @param index - read item index
|
||||
* @param p_data - control-data pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusTcpInitialDataInfo(ModbusTcpReadItem *p_read_item, uint16_t index, uint8_t *p_data)
|
||||
{
|
||||
uint16_t command_index = 0;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
uint16_t start_address = p_read_item->start_address;
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case READ_COIL_STATUS:
|
||||
case READ_INPUT_STATUS:
|
||||
case READ_HOLDING_REGISTER:
|
||||
case READ_INPUT_REGISTER:
|
||||
p_base_data_info->command_length = MODBUS_TCP_READ_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->command_ready = 1;
|
||||
break;
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
p_base_data_info->command_length = MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = 2;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
//"quantity" define how many coil need to be written,"n_byte" define the bytes of write-data(counted by bit)
|
||||
uint16_t n_byte = (quantity - 1) / 8 + 1;
|
||||
p_base_data_info->command_length = n_byte + MODBUS_TCP_WRITE_MULTI_HEAD + 6;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
|
||||
//13th command define the bytes of write-data
|
||||
p_base_data_info->p_command[12] = ((quantity - 1) / 8 + 1);
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = n_byte;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
if (p_data == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
//"quantity" define how many register need to be written
|
||||
p_base_data_info->command_length = quantity * 2 + MODBUS_TCP_WRITE_MULTI_HEAD + 6;
|
||||
p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length);
|
||||
|
||||
//13th command define the bytes of write-data
|
||||
p_base_data_info->p_command[12] = 2 * quantity;
|
||||
p_base_data_info->p_data = p_data;
|
||||
p_base_data_info->data_size = quantity * 2;
|
||||
p_base_data_info->command_ready = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
command_index = 0;
|
||||
p_base_data_info->p_command[command_index++] = index >> 8;
|
||||
p_base_data_info->p_command[command_index++] = index;
|
||||
p_base_data_info->p_command[command_index++] = 0x00;
|
||||
p_base_data_info->p_command[command_index++] = 0x00;
|
||||
p_base_data_info->p_command[command_index++] = 0x00;
|
||||
|
||||
if (function_code < 5) {
|
||||
p_base_data_info->p_command[command_index++] = 0x06;
|
||||
} else {
|
||||
p_base_data_info->p_command[command_index++] = 0x09;
|
||||
}
|
||||
|
||||
p_base_data_info->p_command[command_index++] = MODBUS_TCP_UNIT_ID;
|
||||
p_base_data_info->p_command[command_index++] = function_code;
|
||||
p_base_data_info->p_command[command_index++] = start_address >> 8;
|
||||
p_base_data_info->p_command[command_index++] = start_address;
|
||||
|
||||
if (function_code != WRITE_SINGLE_COIL || function_code != WRITE_SINGLE_REGISTER) {
|
||||
p_base_data_info->p_command[command_index++] = quantity >> 8;
|
||||
p_base_data_info->p_command[command_index++] = quantity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Format write data from "g_write_data"
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item)
|
||||
{
|
||||
int i = 0;
|
||||
uint16_t command_index = 0;
|
||||
int write_data_length = 0;
|
||||
uint8_t write_data_buffer[32] = {0};
|
||||
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
|
||||
uint8_t *p_command = p_base_data_info->p_command;
|
||||
uint8_t function_code = p_read_item->data_info.function_code;
|
||||
|
||||
if (function_code < WRITE_SINGLE_COIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size);
|
||||
if (p_base_data_info->data_size != write_data_length) {
|
||||
printf("%s get write data %d [should be %d]failed!", __func__, write_data_length, p_base_data_info->data_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (function_code)
|
||||
{
|
||||
case WRITE_SINGLE_COIL:
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
command_index = 10;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
command_index = 13;
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < write_data_length; i ++) {
|
||||
p_base_data_info->p_command[command_index++] = write_data_buffer[i];
|
||||
}
|
||||
|
||||
return write_data_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Receive Plc Data Task
|
||||
* @param parameter - parameter pointer
|
||||
* @return
|
||||
*/
|
||||
void *ReceivePlcDataTask(void *parameter)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t try_count = 0;
|
||||
uint16_t data_length = 0;
|
||||
uint8_t *modbus_tcp_data;
|
||||
uint16_t read_item_size = sizeof(ModbusTcpReadItem);
|
||||
|
||||
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
ModbusTcpReadItem *modbus_tcp_read_item = (ModbusTcpReadItem *)control_protocol->recipe->read_item;
|
||||
modbus_tcp_data = control_protocol->recipe->protocol_data.data;
|
||||
data_length = control_protocol->recipe->protocol_data.data_length;
|
||||
|
||||
memset(&plc_socket, 0, sizeof(BasicSocketPlc));
|
||||
memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4);
|
||||
plc_socket.port = control_protocol->recipe->socket_config.port;
|
||||
plc_socket.socket = -1;
|
||||
plc_socket.secondary_connect_flag = 0;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
/*only connect socket when close socket or init*/
|
||||
while (ControlConnectSocket(&plc_socket) < 0) {
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
ModbusTcpForamatWriteData((ModbusTcpReadItem *)modbus_tcp_read_item + i);
|
||||
|
||||
ModbusTcpGetData(plc_socket.socket, (ModbusTcpReadItem *)modbus_tcp_read_item + i);
|
||||
}
|
||||
|
||||
/*read all variable item data, put them into circular_area*/
|
||||
if (i == control_protocol->recipe->read_item_count) {
|
||||
printf("%s get %d item %d length modbus_tcp_data %p\n", __func__, i, data_length, modbus_tcp_data);
|
||||
CircularAreaAppWrite(circular_area, modbus_tcp_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Open
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusTcpOpen(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
ControlProtocolOpenDef(control_protocol);
|
||||
|
||||
g_write_data = CircularAreaAppInit(CA_DATA_LENGTH);
|
||||
if (NULL == g_write_data) {
|
||||
printf("%s CircularAreaInit error\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Close
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusTcpClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CircularAreaAppRelease(g_write_data);
|
||||
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Read Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - read data buffer
|
||||
* @param len - read data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||
{
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
return CircularAreaAppRead(circular_area, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Write Data
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param buf - write data buffer
|
||||
* @param len - write data length
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len)
|
||||
{
|
||||
CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Tcp Protocol Ioctl
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param cmd - ioctl cmd
|
||||
* @param args - ioctl args
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusTcpIoctl(struct ControlProtocol *control_protocol, int cmd, void *args)
|
||||
{
|
||||
//to do
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ControlDone modbustcp_protocol_done =
|
||||
{
|
||||
._open = ModbusTcpOpen,
|
||||
._close = ModbusTcpClose,
|
||||
._read = ModbusTcpRead,
|
||||
._write = ModbusTcpWrite,
|
||||
._ioctl = ModbusTcpIoctl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Cmd Generate
|
||||
* @param p_recipe - recipe pointer
|
||||
* @param protocol_format_info - protocol format info pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusTcpProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
ModbusTcpReadItem *modbustcp_read_item = (ModbusTcpReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
modbustcp_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
strncpy(modbustcp_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||
modbustcp_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint;
|
||||
modbustcp_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint;
|
||||
modbustcp_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint;
|
||||
|
||||
ret = ModbusTcpInitialDataInfo(modbustcp_read_item,
|
||||
protocol_format_info->read_item_index,
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", modbustcp_read_item->data_info.base_data_info.p_command, modbustcp_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(modbustcp_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus TCP Protocol Init
|
||||
* @param p_recipe - recipe pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
p_recipe->read_item = PrivMalloc(sizeof(ModbusTcpReadItem) * p_recipe->read_item_count);
|
||||
if (NULL == p_recipe->read_item) {
|
||||
PrivFree(p_recipe->read_item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(ModbusTcpReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = ModbusTcpProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &modbustcp_protocol_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modbus_tcp.h
|
||||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_TCP_H
|
||||
#define MODBUS_TCP_H
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"device_id": 4,
|
||||
"device_name": "GJ2",
|
||||
"communication_type": 0,
|
||||
"socket_config": {
|
||||
"plc_ip": "192.168.250.9",
|
||||
"local_ip": "192.168.250.233",
|
||||
"gateway": "192.168.250.1",
|
||||
"netmask": "255.255.254.0",
|
||||
"port": 502
|
||||
},
|
||||
"protocol_type": 2,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8192,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M1",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":8193,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M102",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8294,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M200",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8392,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M201",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address":8393,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M202",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8394,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M203",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8395,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M204",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8396,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M205",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8397,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "M206",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8398,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D20",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 20,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D21",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 21,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D22",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 22,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D23",
|
||||
"value_type": 3,
|
||||
"function_code": 3,
|
||||
"start_address": 23,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D202",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 202,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D204",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 204,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D206",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 206,
|
||||
"quantity": 2
|
||||
},
|
||||
{
|
||||
"value_name": "D208",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 208,
|
||||
"quantity": 2
|
||||
}
|
||||
]
|
||||
}
|
|
@ -328,7 +328,7 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
CircularAreaAppWrite(circular_area, fins_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 200ms*/
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +390,8 @@ static struct ControlDone fins_protocol_done =
|
|||
int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
FinsReadItem *fins_read_item = (FinsReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
|
@ -405,11 +407,13 @@ int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *pr
|
|||
ret = FinsInitialDataInfo(fins_read_item,
|
||||
p_recipe->socket_config.plc_ip[3],
|
||||
p_recipe->socket_config.local_ip[3],
|
||||
protocol_format_info->p_read_item_data + protocol_format_info->last_item_size);
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", fins_read_item->data_info.base_data_info.p_command, fins_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(fins_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -426,6 +430,8 @@ int FinsProtocolInit(struct ControlRecipe *p_recipe)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(FinsReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = FinsProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &fins_protocol_done;
|
||||
|
|
|
@ -566,7 +566,7 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
CircularAreaAppWrite(circular_area, melsec_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single read_period*/
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
@ -628,6 +628,9 @@ static struct ControlDone melsec_protocol_done =
|
|||
int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint8_t last_item_size = 0;
|
||||
uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size;
|
||||
|
||||
MelsecReadItem *melsec_read_item = (MelsecReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
melsec_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
|
@ -639,12 +642,13 @@ int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *
|
|||
strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6);
|
||||
melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint;
|
||||
|
||||
ret = MelsecInitialDataInfo(melsec_read_item,
|
||||
protocol_format_info->p_read_item_data + protocol_format_info->last_item_size);
|
||||
ret = MelsecInitialDataInfo(melsec_read_item, p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", melsec_read_item->data_info.base_data_info.p_command, melsec_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(melsec_read_item->value_type);
|
||||
|
||||
last_item_size += protocol_format_info->last_item_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -661,6 +665,8 @@ int MelsecProtocolInit(struct ControlRecipe *p_recipe)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memset(p_recipe->read_item, 0, sizeof(MelsecReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &melsec_protocol_done;
|
||||
|
|
|
@ -37,6 +37,10 @@ extern int FinsProtocolInit(struct ControlRecipe *p_recipe);
|
|||
extern int MelsecProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_TCP
|
||||
extern int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
/*
|
||||
CONTROL FRAMEWORK READ DATA FORMAT:
|
||||
| HEAD |device_id|read data length|read item count| data |
|
||||
|
@ -66,6 +70,9 @@ static struct ControlProtocolInitParam protocol_init[] =
|
|||
{ PROTOCOL_MELSEC_1C, MelsecProtocolInit },
|
||||
{ PROTOCOL_MELSEC_3C, MelsecProtocolInit },
|
||||
#endif
|
||||
#ifdef CONTROL_PROTOCOL_MODBUS_TCP
|
||||
{ PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit },
|
||||
#endif
|
||||
|
||||
{ PROTOCOL_END, NULL },
|
||||
};
|
||||
|
|
|
@ -69,6 +69,7 @@ typedef struct
|
|||
{
|
||||
uint16_t command_length;
|
||||
uint16_t data_size;
|
||||
uint8_t command_ready;
|
||||
uint8_t *p_command;
|
||||
uint8_t *p_data;
|
||||
}BasicPlcDataInfo;
|
||||
|
|
Loading…
Reference in New Issue