forked from xuos/xiuos
feat add modbus uart protocol for control framework, compile OK
This commit is contained in:
parent
6010fe5654
commit
e4742a480c
|
@ -2,12 +2,15 @@ menuconfig SUPPORT_CONTROL_FRAMEWORK
|
|||
bool "support control framework"
|
||||
default n
|
||||
select TRANSFORM_LAYER_ATTRIUBUTE
|
||||
select BSP_USING_LWIP
|
||||
select BSP_USING_SDIO
|
||||
select MOUNT_SDCARD_FS
|
||||
select LIB_USING_CJSON
|
||||
|
||||
if SUPPORT_CONTROL_FRAMEWORK
|
||||
config BSP_USING_SERIAL_485
|
||||
bool
|
||||
default n
|
||||
|
||||
config CONTROL_RECIPE_FILE
|
||||
string "control framework recipe file name"
|
||||
default "test_recipe.json"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
config CONTROL_PROTOCOL_MODBUS_TCP
|
||||
bool "Using modbus_tcp control protocol"
|
||||
default n
|
||||
select BSP_USING_LWIP
|
||||
if CONTROL_PROTOCOL_MODBUS_TCP
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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_uart.h
|
||||
* @brief support modbus_uart function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.29
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_UART_H
|
||||
#define MODBUS_UART_H
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MODBUS_UART_READ_CMD_LENGTH 0x08
|
||||
#define MODBUS_UART_WRITE_CMD_LENGTH 0x08
|
||||
|
||||
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
|
||||
}ModbusUartFunctionCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BasicPlcDataInfo base_data_info;
|
||||
ModbusUartFunctionCode function_code;
|
||||
}ModbusUartDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModbusUartDataInfo data_info;
|
||||
|
||||
UniformValueType value_type;
|
||||
char value_name[20];
|
||||
|
||||
uint8_t station;
|
||||
uint16_t start_address;
|
||||
uint16_t quantity;
|
||||
}ModbusUartReadItem;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,2 +1,37 @@
|
|||
if ADD_XIZI_FETURES
|
||||
config CONTROL_FRAMEWORK_UART_485_DIR
|
||||
int "control framework 485 direction pin number"
|
||||
default "2"
|
||||
|
||||
config CONTROL_FRAMEWORK_PIN_DEV
|
||||
string "control framework device pin dev path"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
bool "Using extra uart to control framework"
|
||||
default n
|
||||
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device uart dev path"
|
||||
default "/dev/uart3_dev3"
|
||||
depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
|
||||
if CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device extra uart dev path"
|
||||
default "/dev/extuart_dev0"
|
||||
|
||||
config CONTROL_FRAMEWORK_DEV_EXT_PORT
|
||||
int "if control framework device using extuart, choose port"
|
||||
default "0"
|
||||
endif
|
||||
endif
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
|
||||
endif
|
||||
|
||||
if ADD_RTTHREAD_FETURES
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_FILES :=
|
||||
SRC_FILES := modbus_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* 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_uart.c
|
||||
* @brief support modbus_uart function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.12.29
|
||||
*/
|
||||
|
||||
#include <modbus_uart.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: CRC16 check
|
||||
* @param data data buffer
|
||||
* @param length data length
|
||||
* @return check code
|
||||
*/
|
||||
static uint16_t ModbusUartCrc16(uint8_t *data, uint32_t length)
|
||||
{
|
||||
int j;
|
||||
uint16_t reg_crc = 0xFFFF;
|
||||
|
||||
while (length--) {
|
||||
reg_crc ^= *data++;
|
||||
for (j = 0;j < 8;j ++) {
|
||||
if(reg_crc & 0x01)
|
||||
reg_crc = reg_crc >> 1 ^ 0xA001;
|
||||
else
|
||||
reg_crc = reg_crc >> 1;
|
||||
}
|
||||
}
|
||||
printf(" crc = [0x%x]\n", reg_crc);
|
||||
return reg_crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart 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 ModbusUartTransformRecvBuffToData(ModbusUartReadItem *p_read_item, uint8_t *recv_buff)
|
||||
{
|
||||
uint8_t head_length = 3;
|
||||
uint8_t *data_buffer;
|
||||
ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info);
|
||||
uint16_t quantity = p_read_item->quantity;
|
||||
|
||||
ModbusUartFunctionCode function_code = p_modbus_uart_data_info->function_code;
|
||||
uint8_t *p_data = p_modbus_uart_data_info->base_data_info.p_data;
|
||||
|
||||
uint8_t bytes_count = recv_buff[2];
|
||||
|
||||
if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code)) {
|
||||
head_length = 4;
|
||||
if (p_modbus_uart_data_info->base_data_info.command_ready) {
|
||||
p_modbus_uart_data_info->base_data_info.command_ready = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data_buffer = recv_buff + head_length;//remove head data
|
||||
|
||||
if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) {
|
||||
printf("Receive data is ");
|
||||
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 if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) {
|
||||
printf("Receive data is ");
|
||||
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");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Get Data From Serial
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartGetDataBySerial(ModbusUartReadItem *p_read_item)
|
||||
{
|
||||
uint32_t read_length = 0;
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
|
||||
ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info);
|
||||
BasicPlcDataInfo *p_base_data_info = &(p_modbus_uart_data_info->base_data_info);
|
||||
|
||||
ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length);
|
||||
|
||||
read_length = SerialRead(recv_buff, sizeof(recv_buff));
|
||||
if (read_length) {
|
||||
ControlPrintfList("RECV", recv_buff, read_length);
|
||||
return ModbusUartTransformRecvBuffToData(p_read_item, recv_buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Data Info Init
|
||||
* @param p_read_item - read item pointer
|
||||
* @param station - uart station number
|
||||
* @param p_data - control-data pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartInitialDataInfo(ModbusUartReadItem *p_read_item, uint8_t station, uint8_t *p_data)
|
||||
{
|
||||
uint16_t command_crc = 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_UART_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_UART_WRITE_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:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
//to do
|
||||
printf("%s unsupported function code %d\n", __func__, function_code);
|
||||
return -1;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
memset(p_base_data_info->p_command, 0, p_base_data_info->command_length);
|
||||
|
||||
p_base_data_info->p_command[0] = station;
|
||||
p_base_data_info->p_command[1] = function_code;
|
||||
p_base_data_info->p_command[2] = start_address >> 8;
|
||||
p_base_data_info->p_command[3] = start_address;
|
||||
if ((function_code != WRITE_SINGLE_COIL) && (function_code != WRITE_SINGLE_REGISTER)) {
|
||||
p_base_data_info->p_command[4] = quantity >> 8;
|
||||
p_base_data_info->p_command[5] = quantity;
|
||||
command_crc = ModbusUartCrc16(p_base_data_info->p_command, 6);
|
||||
p_base_data_info->p_command[6] = command_crc & 0xFF;
|
||||
p_base_data_info->p_command[7] = (command_crc >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Format write data from "g_write_data"
|
||||
* @param p_read_item - read item pointer
|
||||
* @return success : 0 error : -1 -2
|
||||
*/
|
||||
static int ModbusUartForamatWriteData(ModbusUartReadItem *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!\n", __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 = 4;
|
||||
break;
|
||||
case WRITE_MULTIPLE_COIL:
|
||||
case WRITE_MULTIPLE_REGISTER:
|
||||
printf("%s unsupported function code %d\n", __func__, function_code);
|
||||
return -1;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (i = 0; i < write_data_length; i ++) {
|
||||
p_base_data_info->p_command[command_index + i] = write_data_buffer[i];
|
||||
}
|
||||
|
||||
p_base_data_info->command_ready = 1;
|
||||
|
||||
return write_data_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart 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_uart_data;
|
||||
uint16_t read_item_size = sizeof(ModbusUartReadItem);
|
||||
|
||||
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||
ModbusUartReadItem *modbus_uart_read_item = (ModbusUartReadItem *)control_protocol->recipe->read_item;
|
||||
modbus_uart_data = control_protocol->recipe->protocol_data.data;
|
||||
data_length = control_protocol->recipe->protocol_data.data_length;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < control_protocol->recipe->read_item_count; i ++) {
|
||||
|
||||
ModbusUartForamatWriteData((ModbusUartReadItem *)modbus_uart_read_item + i);
|
||||
|
||||
ModbusUartGetDataBySerial((ModbusUartReadItem *)modbus_uart_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_uart_data %p\n", __func__, i, data_length, modbus_uart_data);
|
||||
CircularAreaAppWrite(circular_area, modbus_uart_data, data_length, 0);
|
||||
}
|
||||
|
||||
/*read data every single 'read_period' ms*/
|
||||
PrivTaskDelay(control_protocol->recipe->read_period);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Open
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusUartOpen(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 Uart Protocol Close
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success : 0 error
|
||||
*/
|
||||
int ModbusUartClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CircularAreaAppRelease(g_write_data);
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart 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 ModbusUartRead(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 Uart 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 ModbusUartWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len)
|
||||
{
|
||||
CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Modbus Uart Protocol Ioctl
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @param cmd - ioctl cmd
|
||||
* @param args - ioctl args
|
||||
* @return success : data length error : 0
|
||||
*/
|
||||
int ModbusUartIoctl(struct ControlProtocol *control_protocol, int cmd, void *args)
|
||||
{
|
||||
//to do
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ControlDone modbusuart_protocol_done =
|
||||
{
|
||||
._open = ModbusUartOpen,
|
||||
._close = ModbusUartClose,
|
||||
._read = ModbusUartRead,
|
||||
._write = ModbusUartWrite,
|
||||
._ioctl = ModbusUartIoctl,
|
||||
};
|
||||
|
||||
/**
|
||||
* @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 ModbusUartProtocolFormatCmd(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;
|
||||
|
||||
ModbusUartReadItem *modbusuart_read_item = (ModbusUartReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index;
|
||||
|
||||
modbusuart_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||
strncpy(modbusuart_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||
modbusuart_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint;
|
||||
modbusuart_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint;
|
||||
modbusuart_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint;
|
||||
|
||||
ret = ModbusUartInitialDataInfo(modbusuart_read_item,
|
||||
p_recipe->serial_config.station,
|
||||
p_read_item_data);
|
||||
|
||||
ControlPrintfList("CMD", modbusuart_read_item->data_info.base_data_info.p_command, modbusuart_read_item->data_info.base_data_info.command_length);
|
||||
protocol_format_info->last_item_size = GetValueTypeMemorySize(modbusuart_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 ModbusUartProtocolInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
p_recipe->read_item = PrivMalloc(sizeof(ModbusUartReadItem) * 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(ModbusUartReadItem));
|
||||
|
||||
p_recipe->ControlProtocolFormatCmd = ModbusUartProtocolFormatCmd;
|
||||
|
||||
p_recipe->done = &modbusuart_protocol_done;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"device_id": 1,
|
||||
"device_name": "GJ2",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 9600,
|
||||
"data_bits": 8,
|
||||
"stop_bits": 1,
|
||||
"check_mode": 0
|
||||
},
|
||||
"protocol_type": 3,
|
||||
"read_period": 100,
|
||||
"read_item_list": [
|
||||
{
|
||||
"value_name": "M0",
|
||||
"value_type": 1,
|
||||
"function_code": 1,
|
||||
"start_address": 8192,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"value_name": "D208",
|
||||
"value_type": 9,
|
||||
"function_code": 3,
|
||||
"start_address": 208,
|
||||
"quantity": 2
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
config CONTROL_PROTOCOL_FINS
|
||||
bool "Using fins control protocol"
|
||||
default n
|
||||
select BSP_USING_LWIP
|
||||
if CONTROL_PROTOCOL_FINS
|
||||
source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig"
|
||||
endif
|
||||
|
|
|
@ -4,17 +4,61 @@ choice
|
|||
|
||||
config CONTROL_PROTOCOL_MELSEC_1E
|
||||
bool "support melsec_1e protocol, using TCP"
|
||||
select BSP_USING_LWIP
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3E_Q_L
|
||||
bool "support melsec_3e_q_l protocol, using TCP"
|
||||
select BSP_USING_LWIP
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3E_IQ_R
|
||||
bool "support melsec_3e_iq_r protocol, using TCP"
|
||||
select BSP_USING_LWIP
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_1C
|
||||
bool "support melsec_1c protocol, using SERIAL"
|
||||
select BSP_USING_SERIAL_485
|
||||
|
||||
config CONTROL_PROTOCOL_MELSEC_3C
|
||||
bool "support melsec_3c protocol, using SERIAL"
|
||||
select BSP_USING_SERIAL_485
|
||||
endchoice
|
||||
|
||||
if BSP_USING_SERIAL_485
|
||||
if ADD_XIZI_FETURES
|
||||
config CONTROL_FRAMEWORK_UART_485_DIR
|
||||
int "control framework 485 direction pin number"
|
||||
default "2"
|
||||
|
||||
config CONTROL_FRAMEWORK_PIN_DEV
|
||||
string "control framework device pin dev path"
|
||||
default "/dev/pin_dev"
|
||||
|
||||
config CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
bool "Using extra uart to control framework"
|
||||
default n
|
||||
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device uart dev path"
|
||||
default "/dev/uart3_dev3"
|
||||
depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
|
||||
if CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
config CONTROL_FRAMEWORK_UART_DEV
|
||||
string "control framework device extra uart dev path"
|
||||
default "/dev/extuart_dev0"
|
||||
|
||||
config CONTROL_FRAMEWORK_DEV_EXT_PORT
|
||||
int "if control framework device using extuart, choose port"
|
||||
default "0"
|
||||
endif
|
||||
endif
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
|
||||
endif
|
||||
|
||||
if ADD_RTTHREAD_FETURES
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -575,6 +575,7 @@ static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *r
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BSP_USING_LWIP
|
||||
/**
|
||||
* @description: Melsec Get Data From Socket
|
||||
* @param socket - socket
|
||||
|
@ -619,6 +620,7 @@ static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item)
|
|||
}
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Melsec Get Data From Serial
|
||||
|
@ -673,12 +675,14 @@ void *ReceivePlcDataTask(void *parameter)
|
|||
if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) {
|
||||
MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i);
|
||||
} else {
|
||||
#ifdef BSP_USING_LWIP
|
||||
/*only connect socket when close socket or init*/
|
||||
while (ControlConnectSocket(&plc_socket) < 0) {
|
||||
PrivTaskDelay(1000);
|
||||
}
|
||||
|
||||
MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -712,8 +716,12 @@ int MelsecOpen(struct ControlProtocol *control_protocol)
|
|||
*/
|
||||
int MelsecClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
|
||||
if ((PROTOCOL_MELSEC_1C != control_protocol->protocol_type) && (PROTOCOL_MELSEC_3C != control_protocol->protocol_type)) {
|
||||
#ifdef BSP_USING_LWIP
|
||||
ControlDisconnectSocket(&plc_socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
ControlProtocolCloseDef();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"device_name": "S01",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 19200,
|
||||
"data_bits": 7,
|
||||
"stop_bits": 1,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"device_name": "S02",
|
||||
"communication_type": 1,
|
||||
"serial_config": {
|
||||
"station": 1,
|
||||
"baud_rate": 19200,
|
||||
"data_bits": 7,
|
||||
"stop_bits": 1,
|
||||
|
|
|
@ -143,12 +143,13 @@ static uint16_t GetRecipeTotalDataLength(cJSON* read_item_list_json)
|
|||
static void ControlBasicSerialConfig(struct ControlRecipe *p_recipe, cJSON *p_recipe_file_json)
|
||||
{
|
||||
cJSON *p_serial_config_json = cJSON_GetObjectItem(p_recipe_file_json, "serial_config");
|
||||
p_recipe->serial_config.station = cJSON_GetObjectItem(p_serial_config_json, "station")->valueint;
|
||||
p_recipe->serial_config.baud_rate = cJSON_GetObjectItem(p_serial_config_json, "baud_rate")->valueint;
|
||||
p_recipe->serial_config.data_bits = cJSON_GetObjectItem(p_serial_config_json, "data_bits")->valueint;
|
||||
p_recipe->serial_config.stop_bits = cJSON_GetObjectItem(p_serial_config_json, "stop_bits")->valueint;
|
||||
p_recipe->serial_config.check_mode = cJSON_GetObjectItem(p_serial_config_json, "check_mode")->valueint;
|
||||
printf("Serial_config: baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n",
|
||||
p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
printf("Serial_config:station: %d baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n",
|
||||
p_recipe->serial_config.station, p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,6 +210,7 @@ void ControlPrintfList(char name[5], uint8_t *number_list, uint16_t length)
|
|||
printf("\n**************************************\n");
|
||||
}
|
||||
|
||||
#ifdef BSP_USING_LWIP
|
||||
/**
|
||||
* @description: Control Framework Connect Socket
|
||||
* @param p_plc - basic socket plc pointer
|
||||
|
@ -285,6 +287,7 @@ int ControlDisconnectSocket(BasicSocketPlc *p_plc)
|
|||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Control Framework Protocol Open for Sub_Protocol, Init Circular Area and Receive Data Task
|
||||
|
|
|
@ -90,6 +90,7 @@ struct ProtocolData
|
|||
|
||||
struct SerialConfig
|
||||
{
|
||||
uint8_t station;
|
||||
uint32_t baud_rate;
|
||||
uint8_t data_bits;
|
||||
uint8_t stop_bits;
|
||||
|
|
|
@ -20,6 +20,92 @@
|
|||
|
||||
#include <control_io.h>
|
||||
|
||||
#ifdef BSP_USING_SERIAL_485
|
||||
static int pin_fd = 0;
|
||||
static int uart_fd = 0;
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Input
|
||||
* @return
|
||||
*/
|
||||
static void Set485Input(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
pin_stat.val = GPIO_LOW;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Output
|
||||
* @return
|
||||
*/
|
||||
static void Set485Output(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
pin_stat.val = GPIO_HIGH;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Uart 485 Init
|
||||
* @param baud_rate - baud rate
|
||||
* @param data_bits - data bits
|
||||
* @param stop_bits - stop bits
|
||||
* @param check_mode - check mode, even、odd、none
|
||||
* @return
|
||||
*/
|
||||
void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pin_fd = PrivOpen(CONTROL_FRAMEWORK_PIN_DEV, O_RDWR);
|
||||
if (pin_fd < 0) {
|
||||
printf("open %s error\n", CONTROL_FRAMEWORK_PIN_DEV);
|
||||
return;
|
||||
}
|
||||
|
||||
struct PinParam pin_param;
|
||||
pin_param.cmd = GPIO_CONFIG_MODE;
|
||||
pin_param.mode = GPIO_CFG_OUTPUT;
|
||||
pin_param.pin = CONTROL_FRAMEWORK_UART_485_DIR;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
|
||||
ioctl_cfg.args = &pin_param;
|
||||
PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg);
|
||||
|
||||
uart_fd = open(CONTROL_FRAMEWORK_UART_DEV, O_RDWR);
|
||||
if (uart_fd < 0) {
|
||||
printf("open fd error %d\n", uart_fd);
|
||||
return;
|
||||
}
|
||||
printf("Uart485Init open fd %d\n", uart_fd);
|
||||
|
||||
struct SerialDataCfg cfg;
|
||||
cfg.serial_baud_rate = baud_rate;
|
||||
cfg.serial_data_bits = data_bits;
|
||||
cfg.serial_stop_bits = stop_bits;
|
||||
cfg.serial_buffer_size = 128;
|
||||
cfg.serial_parity_mode = check_mode;
|
||||
cfg.serial_bit_order = 0;
|
||||
cfg.serial_invert_mode = 0;
|
||||
#ifdef CONTROL_FRAMEWORK_DRIVER_EXTUART
|
||||
cfg.ext_uart_no = 0;
|
||||
cfg.port_configure = PORT_CFG_INIT;
|
||||
#endif
|
||||
cfg.serial_timeout = 10000;
|
||||
|
||||
if (ret != PrivIoctl(uart_fd, OPE_INT, &cfg)) {
|
||||
printf("ioctl fd error %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s done!\n", __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @description: Control Framework Socket Init
|
||||
* @param ip - local ip pointer
|
||||
|
@ -48,7 +134,9 @@ void SocketInit(char *ip, char *mask, char *gw)
|
|||
*/
|
||||
void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode)
|
||||
{
|
||||
// Uart485Init(baud_rate, data_bits, stop_bits, check_mode);
|
||||
#ifdef BSP_USING_SERIAL_485
|
||||
Uart485Init(baud_rate, data_bits, stop_bits, check_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,16 +147,41 @@ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_
|
|||
*/
|
||||
void SerialWrite(uint8_t *write_data, int length)
|
||||
{
|
||||
//to do
|
||||
#ifdef BSP_USING_SERIAL_485
|
||||
Set485Output();
|
||||
PrivTaskDelay(20);
|
||||
|
||||
PrivWrite(uart_fd, write_data, length);
|
||||
|
||||
PrivTaskDelay(10);
|
||||
Set485Input();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Serial Read
|
||||
* @param read_data - read data
|
||||
* @param length - length
|
||||
* @return
|
||||
* @return read data size
|
||||
*/
|
||||
int SerialRead(uint8_t *read_data, int length)
|
||||
{
|
||||
//to do
|
||||
#ifdef BSP_USING_SERIAL_485
|
||||
int data_size = 0;
|
||||
int data_recv_size = 0;
|
||||
|
||||
while (data_size < length) {
|
||||
data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length);
|
||||
// for (int i = 0; i < data_recv_size; i ++) {
|
||||
// printf("idx %d data 0x%x\n", i, recv_data[i + data_size]);
|
||||
// }
|
||||
|
||||
data_size += data_recv_size;
|
||||
}
|
||||
|
||||
//need to wait 25ms , make sure write cmd again and receive data successfully
|
||||
PrivTaskDelay(25);
|
||||
|
||||
return data_size;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue