You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
6.4 KiB
C

/* 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_id1字节 + 后续PDU5字节功能码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, "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, "Modbus read len = %d\r\n", rxlen);
buf_print((char *)modbus.rxbuf, rxlen);
uint16_t trans_id = (modbus.rxbuf[0] << 8) + modbus.rxbuf[1];
if (trans_id == transaction_id
&& modbus.rxbuf[POS_UINT_ID] == unit_id)
{
return E_NONE;
}
}
return E_ERROR;
}
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;
}
int32_t _modbus_get_device_type(uint8_t unit, uint16_t *type)
{
uint16_t device_type = 0;
if (!_modbus_tcp_transaction(5, unit, MODBUS_DEVICE_TYPE_ADDR, 1))
{
device_type = modbus.rxbuf[9] << 8;
device_type += modbus.rxbuf[10];
}
*type = device_type;
return E_NONE;
}
int32_t _modbus_get_current(uint8_t unit, uint16_t addr, uint16_t len, uint32_t *current)
{
uint32_t cur = 0;
if (!_modbus_tcp_transaction(5, unit, addr, len))
{
//cur = modbus.rxbuf[9] << 24;
//cur += modbus.rxbuf[10] << 16;
//cur += modbus.rxbuf[11] << 8;
//cur += modbus.rxbuf[12];
memcpy(&cur, &modbus.rxbuf[9], sizeof(uint32_t));
}
*current = cur;
return E_NONE;
}
void _modbus_read_slot_stat(stat_t *pstat)
{
stat_t *ptmp = pstat;
for (int slot = 0; slot < MAX_SLOT; slot++)
{
//pstat[slot].status = 0;
ptmp->status = 0;
ptmp++;
}
ptmp = pstat;
gpio_val_get(gpio_dau1_idx, &ptmp->status);
ptmp++;
gpio_val_get(gpio_dau2_idx, &ptmp->status);
ptmp++;
gpio_val_get(gpio_dau3_idx, &ptmp->status);
ptmp++;
gpio_val_get(gpio_dau4_idx, &ptmp->status);
ptmp++;
gpio_val_get(gpio_dau5_idx, &ptmp->status);
ptmp++;
gpio_val_get(gpio_dau6_idx, &ptmp->status);
}
void *_modbus_send_handle()
{
stat_t *pstat = NULL;
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
pstat = modbus.stat;
_modbus_read_slot_stat(pstat);
for (int slot = 0; slot < MAX_SLOT; slot++)
{
if (pstat->status)
{
_modbus_get_device_type(pstat->unit_id, &pstat->type);
if (DEVICE_IR_TYPE == pstat->type)
{
_modbus_get_current(pstat->unit_id,
MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN, &pstat->current);
DBG(DBG_M_PD_MODBUS, "current:%d\n", pstat->current);
}
else if (DEVICE_DC_TYPE == pstat->type)
{
_modbus_get_current(pstat->unit_id,
MODBUS_DC_CURRENT_ADDR, MODBUS_DC_CURRENT_LEN, &pstat->current);
}
}
pstat++;
}
#endif
sleep(2);
}
if (modbus.fd > 0)
{
close(modbus.fd);
modbus.fd = -1;
}
}
int32_t modbus_handle_init(void)
{
memset(&modbus, 0, sizeof(modbus));
for (int slot = 0; slot < MAX_SLOT; slot++)
{
modbus.stat[slot].unit_id = slot + 1;
}
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, &param);
return E_NONE;
}
#endif