feat add melsec protocol for control framework

This commit is contained in:
Liu_Weichao 2022-11-29 17:11:51 +08:00
parent e5bf0cee41
commit 0b49dd1a3c
6 changed files with 806 additions and 3 deletions

View File

@ -1,15 +1,27 @@
config CONTROL_PROTOCOL_FINS config CONTROL_PROTOCOL_FINS
bool "Using fins control protocol" bool "Using fins control protocol"
default n default n
if CONTROL_PROTOCOL_FINS
source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig"
endif
config CONTROL_PROTOCOL_MELSEC config CONTROL_PROTOCOL_MELSEC
bool "Using melsec control protocol" bool "Using melsec control protocol"
default n default n
if CONTROL_PROTOCOL_MELSEC
source "$APP_DIR/Framework/control/plc_protocol/melsec/Kconfig"
endif
config CONTROL_PROTOCOL_OPCUA config CONTROL_PROTOCOL_OPCUA
bool "Using opcua control protocol" bool "Using opcua control protocol"
default n default n
if CONTROL_PROTOCOL_OPCUA
source "$APP_DIR/Framework/control/plc_protocol/opcua/Kconfig"
endif
config CONTROL_PROTOCOL_S7 config CONTROL_PROTOCOL_S7
bool "Using s7 control protocol" bool "Using s7 control protocol"
default n default n
if CONTROL_PROTOCOL_S7
source "$APP_DIR/Framework/control/plc_protocol/s7/Kconfig"
endif

View File

@ -15,5 +15,98 @@
* @brief plc protocol melsec * @brief plc protocol melsec
* @version 3.0 * @version 3.0
* @author AIIT XUOS Lab * @author AIIT XUOS Lab
* @date 2022-10-08 * @date 2022-11-29
*/ */
#ifndef MELSEC_H
#define MELSEC_H
#include <control_def.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SUB_HEADER 0x5000
#define NETWORK_NUMBER 0x00
#define PC_NUMBER 0xFF
#define QEQUEST_DESTINSTION_MODULE_IO_NUMBER 0x03FF
#define QEQUEST_DESTINSTION_MODULE_STATION_NUMBER 0x00
#define STATION_NUMBER 0x00
#define FRAME_NUMBER 0x4639
#define SELF_STATION_NUMBER 0x00
#define MELSEC_NAK 0x15
#define MELSEC_STX 0x02
#define MELSEC_ETX 0x03
#define MELSEC_ENQ 0x05
#define MELSEC_1E_FRAME_RB 0x00
#define MELSEC_1E_FRAME_RW 0x01
#define MELSEC_1E_FRAME_WB 0x02
#define MELSEC_1E_FRAME_WW 0x03
#define MELSEC_1C_FRAME_RB 0x4252
#define MELSEC_1C_FRAME_RW 0x5752
#define MELSEC_1C_FRAME_WB 0x4257
#define MELSEC_1C_FRAME_WW 0x5757
//same as MELSEC_3E_Q_L_FRAME
#define MELSEC_3C_FRAME_RB 0x04010001
#define MELSEC_3C_FRAME_RW 0x04010000
#define MELSEC_3C_FRAME_WB 0x14010001
#define MELSEC_3C_FRAME_WW 0x14010000
//same as MELSEC_3C_FRAME
#define MELSEC_3E_Q_L_FRAME_RB 0x04010001
#define MELSEC_3E_Q_L_FRAME_RW 0x04010000
#define MELSEC_3E_Q_L_FRAME_WB 0x14010001
#define MELSEC_3E_Q_L_FRAME_WW 0x14010000
#define MELSEC_3E_IQ_R_FRAME_RB 0x04010003
#define MELSEC_3E_IQ_R_FRAME_RW 0x04010002
#define MELSEC_3E_IQ_R_FRAME_WB 0x14010003
#define MELSEC_3E_IQ_R_FRAME_WW 0x14010002
typedef enum {
READ_IN_BITS,
READ_IN_WORD,
WRITE_IN_BITS,
WRITE_IN_WORD,
TEST_IN_BIT,
TEST_IN_WORD
}MelsecCommandType;
typedef enum {
MELSEC_1E_FRAME,
MELSEC_3E_Q_L_FRAME,
MELSEC_3E_IQ_R_FRAME,
MELSEC_1C_FRAME,
MELSEC_3C_FRAME
}MelsecFrameType;
typedef struct
{
BasicPlcDataInfo base_data_info;
MelsecCommandType command_type;
MelsecFrameType frame_type;
}MelsecDataInfo;
typedef struct
{
MelsecDataInfo data_info;
UniformValueType value_type;
uint8_t value_name[20];
uint16_t monitoring_timer;
uint16_t device_code;
uint8_t head_device_number_string[6];
uint16_t device_points_count;
}MelsecReadItem;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,2 +1,20 @@
choice
prompt "select melsec protocol"
default CONTROL_PROTOCOL_MELSEC_1E
config CONTROL_PROTOCOL_MELSEC_1E
bool "support melsec_1e protocol, using TCP"
config CONTROL_PROTOCOL_MELSEC_3E_Q_L
bool "support melsec_3e_q_l protocol, using TCP"
config CONTROL_PROTOCOL_MELSEC_3E_IQ_R
bool "support melsec_3e_iq_r protocol, using TCP"
config CONTROL_PROTOCOL_MELSEC_1C
bool "support melsec_1c protocol, using SERIAL"
config CONTROL_PROTOCOL_MELSEC_3C
bool "support melsec_3c protocol, using SERIAL"
endchoice

View File

@ -1,4 +1,4 @@
SRC_FILES := SRC_FILES := melsec.c
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,669 @@
/*
* 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 melsec.c
* @brief plc protocol melsec, support 1E3E_Q_L3E_IQ_R1C3C
* @version 3.0
* @author AIIT XUOS Lab
* @date 2022-11-29
*/
#include <melsec.h>
static BasicSocketPlc plc_socket = {0};
static uint8_t recv_buff[1024] = {0};
/**
* @description: Melsec Get Check Sum
* @param p_command - p_command pointer
* @param command_length - command length
* @return checksum
*/
static uint8_t GetCheckSum(uint8_t *p_command, uint16_t command_length)
{
uint8_t checksum = 0;
for (uint16_t i = 0; i < command_length; i++) {
checksum += p_command[i];
}
return checksum;
}
/**
* @description: Melsec Transform from Hex to Ascii
* @param hex - hex
* @return ascii
*/
static uint8_t TransformHexToAscii(uint8_t hex)
{
hex %= 0x10;
return hex < 0xA ? hex + '0' : hex - 10 + 'A';
}
/**
* @description: Melsec Transform from Ascii to Hex
* @param ascii - ascii
* @return hex
*/
static uint8_t TransformAsciiToHex(uint8_t ascii)
{
if (ascii > 'F' || ascii < '0' || (ascii > '9' && ascii < 'A'))
return 0;
else
return ascii < 'A' ? ascii - '0' : ascii - 'A' + 10;
}
/**
* @description: Melsec Get Device Code
* @param frame_type - melsec frame type
* @param device_string - device string
* @return device code
*/
static int MelsecGetDeviceCode(MelsecFrameType frame_type, char device_string[2])
{
switch (frame_type) {
case MELSEC_1C_FRAME:
if (strcmp(device_string, "M") == 0)
return 0x4D;
if (strcmp(device_string, "D") == 0)
return 0x44;
if (strcmp(device_string, "B") == 0)
return 0x22;
if (strcmp(device_string, "W") == 0)
return 0x57;
if (strcmp(device_string, "X") == 0)
return 0x58;
if (strcmp(device_string, "Y") == 0)
return 0x59;
case MELSEC_1E_FRAME:
if (strcmp(device_string, "M") == 0)
return 0x4D20;
if (strcmp(device_string, "D") == 0)
return 0x4420;
if (strcmp(device_string, "B") == 0)
return 0x2220;
if (strcmp(device_string, "W") == 0)
return 0x5720;
if (strcmp(device_string, "X") == 0)
return 0x5820;
if (strcmp(device_string, "Y") == 0)
return 0x5920;
case MELSEC_3C_FRAME:
if (strcmp(device_string, "M") == 0)
return 0x4D2A;
if (strcmp(device_string, "D") == 0)
return 0x442A;
if (strcmp(device_string, "B") == 0)
return 0x222A;
if (strcmp(device_string, "W") == 0)
return 0x572A;
case MELSEC_3E_IQ_R_FRAME:
if (strcmp(device_string, "M") == 0)
return 0x0090;
if (strcmp(device_string, "D") == 0)
return 0x00A8;
if (strcmp(device_string, "B") == 0)
return 0x00A0;
if (strcmp(device_string, "W") == 0)
return 0x00B4;
if (strcmp(device_string, "X") == 0)
return 0x009C;
if (strcmp(device_string, "Y") == 0)
return 0x009D;
case MELSEC_3E_Q_L_FRAME:
if (strcmp(device_string, "M") == 0)
return 0x90;
if (strcmp(device_string, "D") == 0)
return 0xA8;
if (strcmp(device_string, "B") == 0)
return 0xA0;
if (strcmp(device_string, "W") == 0)
return 0xB4;
if (strcmp(device_string, "X") == 0)
return 0x9C;
if (strcmp(device_string, "Y") == 0)
return 0x9D;
}
}
/**
* @description: Melsec Get Command Base Length
* @param frame_type - melsec frame type
* @return command length
*/
static int MelsecGetCommandBaseLength(MelsecFrameType frame_type)
{
switch (frame_type) {
case MELSEC_1C_FRAME:
return 17;
case MELSEC_1E_FRAME:
return 12;
case MELSEC_3C_FRAME:
return 33;
case MELSEC_3E_IQ_R_FRAME:
case MELSEC_3E_Q_L_FRAME:
return 21;
default:
return -1;
}
}
/**
* @description: Melsec Get Command Code
* @param frame_type - melsec frame type
* @param command_type - melsec command type
* @return command code
*/
static uint32_t MelsecGetCommandCode(MelsecFrameType frame_type, MelsecCommandType command_type)
{
switch (frame_type) {
case MELSEC_1C_FRAME:
switch (command_type) {
case READ_IN_BITS:
return MELSEC_1C_FRAME_RB;
case READ_IN_WORD:
return MELSEC_1C_FRAME_RW;
case WRITE_IN_BITS:
return MELSEC_1C_FRAME_WB;
case WRITE_IN_WORD:
return MELSEC_1C_FRAME_WW;
}
case MELSEC_1E_FRAME:
return command_type;
case MELSEC_3C_FRAME:
case MELSEC_3E_Q_L_FRAME:
switch (command_type) {
case READ_IN_BITS:
return MELSEC_3E_Q_L_FRAME_RB;
case READ_IN_WORD:
return MELSEC_3E_Q_L_FRAME_RW;
case WRITE_IN_BITS:
return MELSEC_3E_Q_L_FRAME_WB;
case WRITE_IN_WORD:
return MELSEC_3E_Q_L_FRAME_WW;
}
case MELSEC_3E_IQ_R_FRAME:
switch (command_type) {
case READ_IN_BITS:
return MELSEC_3E_IQ_R_FRAME_RB;
case READ_IN_WORD:
return MELSEC_3E_IQ_R_FRAME_RW;
case WRITE_IN_BITS:
return MELSEC_3E_IQ_R_FRAME_WB;
case WRITE_IN_WORD:
return MELSEC_3E_IQ_R_FRAME_WW;
}
}
}
/**
* @description: Melsec_1E Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t Melsec1eGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
uint16_t index = 0;
p_command[index++] = command_code;
p_command[index++] = PC_NUMBER;
p_command[index++] = p_read_item->monitoring_timer / 250;
p_command[index++] = (p_read_item->monitoring_timer / 250) >> 8;
uint16_t head_device_number = 0;
for (uint8_t i = 0; i < 6; i++) {
if (0 != p_read_item->head_device_number_string[i])
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x5820 == p_read_item->device_code) || (0x5920 == p_read_item->device_code)) ? 8 : 10);
else
break;
}
p_command[index++] = head_device_number;
p_command[index++] = head_device_number >> (8 * 1);
p_command[index++] = head_device_number >> (8 * 2);
p_command[index++] = head_device_number >> (8 * 3);
p_command[index++] = p_read_item->device_code;
p_command[index++] = p_read_item->device_code >> 8;
p_command[index++] = p_read_item->device_points_count;
p_command[index++] = 0x00;
return index;
}
/**
* @description: Melsec_3E_Q_L Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t Melsec3eqlGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
p_read_item->monitoring_timer /= 250;
uint16_t index = 0;
p_command[index++] = SUB_HEADER >> 8;
p_command[index++] = (uint8_t)SUB_HEADER;
p_command[index++] = NETWORK_NUMBER;
p_command[index++] = PC_NUMBER;
p_command[index++] = (uint8_t)QEQUEST_DESTINSTION_MODULE_IO_NUMBER;
p_command[index++] = (uint8_t)(QEQUEST_DESTINSTION_MODULE_IO_NUMBER >> 8);
p_command[index++] = QEQUEST_DESTINSTION_MODULE_STATION_NUMBER;
p_command[index++] = 0x0c;
p_command[index++] = 0x00;
p_command[index++] = p_read_item->monitoring_timer;
p_command[index++] = p_read_item->monitoring_timer >> 8;
p_command[index++] = command_code >> (8 * 2);
p_command[index++] = command_code >> (8 * 3);
p_command[index++] = command_code;
p_command[index++] = command_code >> (8 * 1);
uint16_t head_device_number = 0;
for (uint8_t i = 0; i < 6; i++) {
if (0 != p_read_item->head_device_number_string[i])
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10);
else
break;
}
p_command[index++] = head_device_number;
p_command[index++] = head_device_number >> (8 * 1);
p_command[index++] = head_device_number >> (8 * 2);
p_command[index++] = p_read_item->device_code;
p_command[index++] = p_read_item->device_points_count;
p_command[index++] = p_read_item->device_points_count >> 8;
return index;
}
/**
* @description: Melsec_3E_IQ_R Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t Melsec3eiqrGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
uint16_t index = Melsec3eqlGenerateCommand(p_command, command_code, p_read_item) - 6;
uint16_t head_device_number = 0;
for (uint8_t i = 0; i < 6; i++) {
if (0 != p_read_item->head_device_number_string[i])
head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10);
else
break;
}
p_command[index++] = head_device_number;
p_command[index++] = head_device_number >> (8 * 1);
p_command[index++] = head_device_number >> (8 * 2);
p_command[index++] = head_device_number >> (8 * 3);
p_command[index++] = p_read_item->device_code;
p_command[index++] = p_read_item->device_code >> 8;
p_command[index++] = p_read_item->device_points_count;
p_command[index++] = p_read_item->device_points_count >> 8;
return index;
}
/**
* @description: Melsec_1C Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t Melsec1cGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
p_read_item->monitoring_timer /= 10;
uint16_t index = 0;
uint8_t checksum = 0;
p_command[index++] = MELSEC_ENQ;
p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(STATION_NUMBER);
p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(PC_NUMBER);
p_command[index++] = command_code >> 8;
p_command[index++] = command_code;
p_command[index++] = TransformHexToAscii(p_read_item->monitoring_timer);
p_command[index++] = p_read_item->device_code;
uint8_t head_device_number_string_length = 0;
for (uint8_t i = 0; i < 6; i++) {
if (0 == p_read_item->head_device_number_string[i])
break;
else
head_device_number_string_length++;
}
p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4];
p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3];
p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2];
p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1];
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> 4);
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count);
checksum = GetCheckSum(p_command + 1, index - 1);
p_command[index++] = TransformHexToAscii(checksum >> 4);
p_command[index++] = TransformHexToAscii(checksum);
return index;
}
/**
* @description: Melsec_3C Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t Melsec3cGenerateCommand(uint8_t* p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
uint16_t index = 0;
uint8_t checksum = 0;
p_command[index++] = MELSEC_ENQ;
p_command[index++] = FRAME_NUMBER >> 8;
p_command[index++] = (uint8_t)FRAME_NUMBER;
p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(STATION_NUMBER);
p_command[index++] = TransformHexToAscii(NETWORK_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(NETWORK_NUMBER);
p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(PC_NUMBER);
p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER >> 4);
p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER);
p_command[index++] = TransformHexToAscii(command_code >> (7 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (6 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (5 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (4 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (3 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (2 * 4));
p_command[index++] = TransformHexToAscii(command_code >> (1 * 4));
p_command[index++] = TransformHexToAscii(command_code);
p_command[index++] = p_read_item->device_code >> 8;
p_command[index++] = p_read_item->device_code;
uint8_t head_device_number_string_length = 0;
for (uint8_t i = 0; i < 6; i++) {
if (0 == p_read_item->head_device_number_string[i])
break;
else
head_device_number_string_length++;
}
p_command[index++] = (head_device_number_string_length - 6 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 6];
p_command[index++] = (head_device_number_string_length - 5 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 5];
p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4];
p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3];
p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2];
p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1];
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (3 * 8));
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (2 * 8));
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (1 * 8));
p_command[index++] = TransformHexToAscii(p_read_item->device_points_count);
checksum = GetCheckSum(p_command + 1, index - 1);
p_command[index++] = TransformHexToAscii(checksum >> 4);
p_command[index++] = TransformHexToAscii(checksum);
return index;
}
/**
* @description: Melsec Cmd Genetare
* @param p_command - command pointer
* @param command_code - command code
* @param p_read_item - p_read_item pointer
* @return success : index error : 0
*/
static uint16_t MelsecGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item)
{
uint16_t (*GenerateMelsecCommandFunction)(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item);
switch (p_read_item->data_info.frame_type) {
case MELSEC_1E_FRAME:
GenerateMelsecCommandFunction = Melsec1eGenerateCommand;
break;
case MELSEC_3E_IQ_R_FRAME:
GenerateMelsecCommandFunction = Melsec3eiqrGenerateCommand;
break;
case MELSEC_3E_Q_L_FRAME:
GenerateMelsecCommandFunction = Melsec3eqlGenerateCommand;
break;
case MELSEC_1C_FRAME:
GenerateMelsecCommandFunction = Melsec1cGenerateCommand;
break;
case MELSEC_3C_FRAME:
GenerateMelsecCommandFunction = Melsec3cGenerateCommand;
break;
default:
return 0;
}
return GenerateMelsecCommandFunction(p_command, command_code, p_read_item);
}
/**
* @description: Melsec Data Info Init
* @param p_read_item - read item pointer
* @param p_data - control-data pointer
* @return success : 0 error : -1
*/
int MelsecInitialDataInfo(MelsecReadItem *p_read_item, uint8_t *p_data)
{
uint8_t check_sum = 0;
BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info);
int command_base_length = MelsecGetCommandBaseLength(p_read_item->data_info.frame_type);
if (command_base_length < 0) {
printf("%s Not supported device code!\n", __func__);
return -1;
}
switch (p_read_item->data_info.command_type) {
case READ_IN_BITS:
p_base_data_info->command_length = command_base_length;
p_base_data_info->p_command = PrivMalloc(command_base_length);
p_base_data_info->data_size = p_read_item->device_points_count;
p_base_data_info->p_data = p_data;
break;
case READ_IN_WORD:
p_base_data_info->command_length = command_base_length;
p_base_data_info->p_command = PrivMalloc(command_base_length);
p_base_data_info->data_size = p_read_item->device_points_count * 2;
p_base_data_info->p_data = p_data;
break;
case WRITE_IN_BITS:
p_base_data_info->command_length = command_base_length + p_read_item->device_points_count;
p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count);
command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0;
memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count);
break;
case WRITE_IN_WORD:
p_base_data_info->command_length = command_base_length + p_read_item->device_points_count * 2;
p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count * 2);
command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0;
memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count * 2);
break;
default:
return -1;
}
uint32_t command_code = MelsecGetCommandCode(p_read_item->data_info.frame_type, p_read_item->data_info.command_type);
MelsecGenerateCommand(p_base_data_info->p_command, command_code, p_read_item);
return 0;
}
/**
* @description: Melsec 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 MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *recv_buff)
{
}
/**
* @description: Melsec Get Data From Socket
* @param socket - socket
* @param p_read_item - read item pointer
* @return success : 0 error : -1 -2
*/
static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item)
{
}
/**
* @description: Melsec Get Data From Serial
* @param p_read_item - read item pointer
* @return success : 0 error : -1 -2
*/
static int MelsecGetDataBySerial(MelsecReadItem *p_read_item)
{
}
/**
* @description: Melsec 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 *melsec_data;
uint16_t read_item_size = sizeof(MelsecReadItem);
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
MelsecReadItem *melsec_read_item = (MelsecReadItem *)control_protocol->recipe->read_item;
melsec_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;
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);
}
MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_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\n", __func__, i, data_length);
CircularAreaAppWrite(circular_area, melsec_data, data_length, 0);
}
/*read data every single read_period*/
PrivTaskDelay(control_protocol->recipe->read_period);
}
}
/**
* @description: Melsec Protocol Open
* @param control_protocol - control protocol pointer
* @return success : 0 error
*/
int MelsecOpen(struct ControlProtocol *control_protocol)
{
ControlProtocolOpenDef(control_protocol);
return 0;
}
/**
* @description: Melsec Protocol Close
* @param control_protocol - control protocol pointer
* @return success : 0 error
*/
int MelsecClose(struct ControlProtocol *control_protocol)
{
ControlDisconnectSocket(&plc_socket);
ControlProtocolCloseDef();
return 0;
}
/**
* @description: Melsec 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 MelsecRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
{
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
return CircularAreaAppRead(circular_area, buf, len);
}
static struct ControlDone melsec_protocol_done =
{
._open = MelsecOpen,
._close = MelsecClose,
._read = MelsecRead,
._write = NULL,
._ioctl = NULL,
};
/**
* @description: Melsec Protocol Cmd Generate
* @param p_recipe - recipe pointer
* @param protocol_format_info - protocol format info pointer
* @return success : 0 error : -1
*/
int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
{
int ret = 0;
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;
strncpy(melsec_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
melsec_read_item->data_info.command_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "command_type")->valueint;
melsec_read_item->data_info.frame_type = p_recipe->protocol_type - PROTOCOL_MELSEC_1E;
melsec_read_item->monitoring_timer = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "monitoring_timer")->valueint;
melsec_read_item->device_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_code")->valuestring;
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);
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);
return ret;
}
/**
* @description: Melsec Protocol Init
* @param p_recipe - recipe pointer
* @return success : 0 error : -1
*/
int MelsecProtocolInit(struct ControlRecipe *p_recipe)
{
p_recipe->read_item = PrivMalloc(sizeof(MelsecReadItem) * p_recipe->read_item_count);
if (NULL == p_recipe->read_item) {
PrivFree(p_recipe->read_item);
return -1;
}
p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd;
p_recipe->done = &melsec_protocol_done;
return 0;
}

View File

@ -33,6 +33,10 @@ extern void *ReceivePlcDataTask(void *parameter);
extern int FinsProtocolInit(struct ControlRecipe *p_recipe); extern int FinsProtocolInit(struct ControlRecipe *p_recipe);
#endif #endif
#ifdef CONTROL_PROTOCOL_MELSEC
extern int MelsecProtocolInit(struct ControlRecipe *p_recipe);
#endif
/* /*
CONTROL FRAMEWORK READ DATA FORMAT: CONTROL FRAMEWORK READ DATA FORMAT:
| HEAD |device_id|read data length|read item count| data | | HEAD |device_id|read data length|read item count| data |
@ -55,6 +59,13 @@ static struct ControlProtocolInitParam protocol_init[] =
#ifdef CONTROL_PROTOCOL_FINS #ifdef CONTROL_PROTOCOL_FINS
{ PROTOCOL_FINS, FinsProtocolInit }, { PROTOCOL_FINS, FinsProtocolInit },
#endif #endif
#ifdef CONTROL_PROTOCOL_MELSEC
{ PROTOCOL_MELSEC_1E, MelsecProtocolInit },
{ PROTOCOL_MELSEC_3E_Q_L, MelsecProtocolInit },
{ PROTOCOL_MELSEC_3E_IQ_R, MelsecProtocolInit },
{ PROTOCOL_MELSEC_1C, MelsecProtocolInit },
{ PROTOCOL_MELSEC_3C, MelsecProtocolInit },
#endif
{ PROTOCOL_END, NULL }, { PROTOCOL_END, NULL },
}; };