|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CFG_DEV_TYPE_LAND_PD
|
|
|
|
|
/* 标准C库头文件. */
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
|
|
/* 用户代码头文件. */
|
|
|
|
|
#include "hwgpio.h"
|
|
|
|
|
#include "serial.h"
|
|
|
|
|
#include "pd_modbus.h"
|
|
|
|
|
|
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
|
|
|
modbus_t modbus;
|
|
|
|
|
|
|
|
|
|
int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id,
|
|
|
|
|
uint16_t start_addr, uint16_t data_num)
|
|
|
|
|
{
|
|
|
|
|
int txlen = 0;
|
|
|
|
|
int rxlen = 0;
|
|
|
|
|
modbus_tcp_t *frame = (modbus_tcp_t *)modbus.txbuf;
|
|
|
|
|
uint8_t *pdata = NULL;
|
|
|
|
|
uint8_t datalen = 0;
|
|
|
|
|
frame->transaction_id = htons(transaction_id);
|
|
|
|
|
frame->protocol_id = htons(0); // Modbus
|
|
|
|
|
// 长度:unit_id(1字节) + 后续PDU(5字节:功能码1 + 起始地址2 + 数量2)
|
|
|
|
|
frame->length = htons(6);
|
|
|
|
|
frame->unit_id = unit_id;
|
|
|
|
|
// PDU
|
|
|
|
|
frame->function_code = 0x03;
|
|
|
|
|
pdata = modbus.txbuf + sizeof(modbus_tcp_t);
|
|
|
|
|
pdata[datalen++] = (start_addr >> 8) & 0xFF; // 起始地址高字节
|
|
|
|
|
pdata[datalen++] = start_addr & 0xFF; // 起始地址低字节
|
|
|
|
|
pdata[datalen++] = (data_num >> 8) & 0xFF; // 数据数量高字节
|
|
|
|
|
pdata[datalen++] = data_num & 0xFF; // 数据数量低字节
|
|
|
|
|
|
|
|
|
|
txlen = datalen + sizeof(modbus_tcp_t);
|
|
|
|
|
|
|
|
|
|
// 发送请求帧
|
|
|
|
|
GPIO_485BUS(WRITE);
|
|
|
|
|
if (serial_write(modbus.fd, modbus.txbuf, txlen) < 0)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Modbus write error\r\n");
|
|
|
|
|
return E_ERROR;
|
|
|
|
|
}
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Modbus write len = %d\r\n", txlen);
|
|
|
|
|
buf_print((char *)modbus.txbuf, txlen);
|
|
|
|
|
|
|
|
|
|
// 等待传输完成
|
|
|
|
|
usleep(13000); // 13000
|
|
|
|
|
|
|
|
|
|
GPIO_485BUS(READ);
|
|
|
|
|
rxlen = serial_read(modbus.fd, modbus.rxbuf, sizeof(modbus.rxbuf));
|
|
|
|
|
if (rxlen > 0)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Modbus read len = %d\r\n", rxlen);
|
|
|
|
|
buf_print((char *)modbus.rxbuf, rxlen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t _modbus_rtu_transaction(void)
|
|
|
|
|
{
|
|
|
|
|
int sndlen = 0;
|
|
|
|
|
int rcvlen = 0;
|
|
|
|
|
uint8_t *ptxbuf = modbus.txbuf;
|
|
|
|
|
ptxbuf[sndlen++] = 0x05;
|
|
|
|
|
ptxbuf[sndlen++] = 0x03;
|
|
|
|
|
ptxbuf[sndlen++] = 0x00;
|
|
|
|
|
ptxbuf[sndlen++] = 0x34;
|
|
|
|
|
ptxbuf[sndlen++] = 0x00;
|
|
|
|
|
ptxbuf[sndlen++] = 0x02;
|
|
|
|
|
ptxbuf[sndlen++] = 0x84;
|
|
|
|
|
ptxbuf[sndlen++] = 0x41;
|
|
|
|
|
|
|
|
|
|
// 发送请求帧
|
|
|
|
|
GPIO_485BUS(WRITE);
|
|
|
|
|
if (serial_write(modbus.fd, ptxbuf, sndlen) < 0)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Modbus write error\r\n");
|
|
|
|
|
return E_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usleep(10000);
|
|
|
|
|
|
|
|
|
|
GPIO_485BUS(READ);
|
|
|
|
|
rcvlen = serial_read(modbus.fd, modbus.rxbuf, sizeof(modbus.rxbuf));
|
|
|
|
|
if (rcvlen > 0)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Modbus read len = %d\r\n", rcvlen);
|
|
|
|
|
buf_print((char *)modbus.rxbuf, rcvlen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *_modbus_send_handle()
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
|
|
|
|
for (int unit = 1; unit <= 6; unit++)
|
|
|
|
|
{
|
|
|
|
|
if (_modbus_tcp_transaction(0, unit, MODBUS_ADDR_CURRENT, MODBUS_CURRENT_LEN) > 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_modbus_tcp_transaction(0, unit, MODBUS_ADDR_CURRENT, MODBUS_CURRENT_LEN) > 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
//_modbus_rtu_transaction();
|
|
|
|
|
|
|
|
|
|
_modbus_tcp_transaction(5, MODBUS_UNIT_IR, MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN);
|
|
|
|
|
#endif
|
|
|
|
|
sleep(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (modbus.fd > 0)
|
|
|
|
|
{
|
|
|
|
|
close(modbus.fd);
|
|
|
|
|
modbus.fd = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t modbus_handle_init(void)
|
|
|
|
|
{
|
|
|
|
|
memset(&modbus, 0, sizeof(modbus));
|
|
|
|
|
modbus.fd = -1;
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t modbus_handle_init_after(void)
|
|
|
|
|
{
|
|
|
|
|
int baud_rate = 9600;
|
|
|
|
|
thread_param_t param = {0};
|
|
|
|
|
|
|
|
|
|
// 初始化串口
|
|
|
|
|
int fd = serial_open("/dev/ttyS0", baud_rate);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_MODBUS_ERR, "Failed to initialize serial port\n");
|
|
|
|
|
return E_ERROR;
|
|
|
|
|
}
|
|
|
|
|
modbus.fd = fd;
|
|
|
|
|
DBG(DBG_M_PD_MODBUS, "fd=%d\n", modbus.fd);
|
|
|
|
|
|
|
|
|
|
param.arg = NULL;
|
|
|
|
|
param.priority = 80;
|
|
|
|
|
param.log_module = LOG_MODBUS;
|
|
|
|
|
snprintf(param.thread_name, THREAD_NAME_LEN, "MODBUS_SEND");
|
|
|
|
|
create_thread(_modbus_send_handle, ¶m);
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|