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.

298 lines
7.8 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* 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;
void _modbus_show(void)
{
card_t *pcard = modbus.card;
printh("ID ST IN CO M S\r\n");
for (int slot = 0; slot < PD_SLOTS_MAX; slot++)
{
printh("%-02d %-02d %-02d %-02d %d %d\r\n", pcard->unit_id, pcard->status,
pcard->is_insert, pcard->is_connect, pcard->type_m, pcard->type_s);
pcard++;
}
}
/* modbus 状态显示 */
CMD(modbus_show,
modbus_show_cmd,
"show modbus",
"Show\n"
"Modbus\n")
{
_modbus_show();
return CMD_SUCCESS;
}
int32_t _modbus_tcp_transaction(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;
static uint16_t transaction_id = 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)
{
uint16_t length;
//DBG(DBG_M_PD_MODBUS, "Modbus read len = %d\r\n", rxlen);
//buf_print((char *)modbus.rxbuf, rxlen);
length = modbus.rxbuf[POS_DATA_LEN] << 8;
length += modbus.rxbuf[POS_DATA_LEN + 1];
if (rxlen == length + 6)
{
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, uint8_t *typem, uint8_t *types)
{
if (!_modbus_tcp_transaction(unit, MODBUS_DEVICE_TYPE_ADDR, MODBUS_DEVICE_TYPE_LEN))
{
*typem = modbus.rxbuf[9];
*types = modbus.rxbuf[10];
}
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(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;
}
int32_t _modbus_get_alarm(uint8_t unit, uint16_t addr, uint16_t len, uint16_t *alarm)
{
uint16_t val = 0;
if (!_modbus_tcp_transaction(unit, addr, len))
{
memcpy(&val, &modbus.rxbuf[9], sizeof(uint16_t));
}
*alarm = val;
return E_NONE;
}
void _modbus_read_slot_stat(card_t *pcard)
{
card_t *ptmp = pcard;
for (int slot = 0; slot < PD_SLOTS_MAX; slot++)
{
ptmp->status = 0;
ptmp++;
}
ptmp = pcard;
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()
{
card_t *pcard = 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
pcard = modbus.card;
_modbus_read_slot_stat(pcard);
for (int slot = 0; slot < PD_SLOTS_MAX; slot++)
{
if (pcard->status)
{
_modbus_get_device_type(pcard->unit_id, &pcard->type_m, &pcard->type_s);
if (DEVICE_IR_TYPE == pcard->type_s && DEVICE_M_TYPE == pcard->type_m)
{
pcard->is_connect = TRUE;
_modbus_get_current(pcard->unit_id,
MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN, &pcard->current);
//DBG(DBG_M_PD_MODBUS, "current:%d\n", pcard->current);
_modbus_get_alarm(pcard->unit_id,
MODBUS_IR_ALARM_ADDR, MODBUS_IR_ALARM_LEN, &pcard->alarm);
//DBG(DBG_M_PD_MODBUS, "alarm:%d\n", pcard->alarm);
}
else if (DEVICE_DC_TYPE == pcard->type_s && DEVICE_M_TYPE == pcard->type_m)
{
pcard->is_connect = TRUE;
_modbus_get_current(pcard->unit_id,
MODBUS_DC_CURRENT_ADDR, MODBUS_DC_CURRENT_LEN, &pcard->current);
}
}
pcard++;
}
#endif
sleep(5);
}
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 < PD_SLOTS_MAX; slot++)
{
modbus.card[slot].unit_id = slot + 1;
}
modbus.fd = -1;
cmd_install_element(COMMON_NODE, &modbus_show_cmd);
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;
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