|
|
/* 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"
|
|
|
#include "pd_dau.h"
|
|
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
|
modbus_t modbus;
|
|
|
|
|
|
void _modbus_show(void)
|
|
|
{
|
|
|
card_t *pcard = NULL;
|
|
|
printh("UNIT STATUS CURRENT ALARM\r\n");
|
|
|
for (int slot = 0; slot < PD_SLOTS_MAX; slot++)
|
|
|
{
|
|
|
pcard = &modbus.card[slot];
|
|
|
printh("%-04d %3d %8d %6d\r\n", pcard->unit_id, pcard->status, pcard->current, pcard->alarm);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 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_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, "Modbus write len = %d\r\n", txlen);
|
|
|
DBG_ARRAY(DBG_M_PD_MODBUS, (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);
|
|
|
DBG_ARRAY(DBG_M_PD_MODBUS, (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;
|
|
|
}
|
|
|
return E_ERROR;
|
|
|
}
|
|
|
|
|
|
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 crash() {
|
|
|
int *ptr = NULL;
|
|
|
*ptr = 42; // 故意触发段错误
|
|
|
}
|
|
|
|
|
|
void *_modbus_send_handle()
|
|
|
{
|
|
|
card_t *pcard = NULL;
|
|
|
dau_t *dau = NULL;
|
|
|
while (1)
|
|
|
{
|
|
|
_modbus_read_slot_stat(modbus.card);
|
|
|
|
|
|
for (int slot = 0; slot < PD_SLOTS_MAX; slot++)
|
|
|
{
|
|
|
|
|
|
pcard = &modbus.card[slot];
|
|
|
dau = &daus[slot];
|
|
|
//DBG(DBG_M_PD_MODBUS, "slot%d unit_id:%d status:%d\n", slot, pcard->unit_id, pcard->status);
|
|
|
if (pcard->status)
|
|
|
{
|
|
|
sleep(1);
|
|
|
if (_modbus_get_device_type(pcard->unit_id, &dau->info.type_m, &dau->info.type_s) != E_NONE)
|
|
|
continue;
|
|
|
//DBG(DBG_M_PD_MODBUS, "slot%d typem:%d types:%d\n", slot, dau->info.type_m, dau->info.type_s);
|
|
|
|
|
|
if (DEVICE_IR_TYPE == dau->info.type_s && DEVICE_M_TYPE == dau->info.type_m)
|
|
|
{
|
|
|
dau->state.beat_cnt = 0;
|
|
|
dau->state.is_connect = TRUE;
|
|
|
sleep(1);
|
|
|
_modbus_get_current(pcard->unit_id,
|
|
|
MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN, &pcard->current);
|
|
|
|
|
|
_modbus_get_alarm(pcard->unit_id,
|
|
|
MODBUS_IR_ALARM_ADDR, MODBUS_IR_ALARM_LEN, &pcard->alarm);
|
|
|
}
|
|
|
else if (DEVICE_DC_TYPE == dau->info.type_s && DEVICE_M_TYPE == dau->info.type_m)
|
|
|
{
|
|
|
dau->state.beat_cnt = 0;
|
|
|
dau->state.is_connect = TRUE;
|
|
|
sleep(1);
|
|
|
_modbus_get_current(pcard->unit_id,
|
|
|
MODBUS_DC_CURRENT_ADDR, MODBUS_DC_CURRENT_LEN, &pcard->current);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (DEVICE_M_TYPE == dau->info.type_m &&
|
|
|
(DEVICE_IR_TYPE == dau->info.type_s || DEVICE_DC_TYPE == dau->info.type_s))
|
|
|
{
|
|
|
dau->state.beat_cnt = 0;
|
|
|
dau->state.is_connect = FALSE;
|
|
|
dau->state.is_insert = FALSE;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
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, ¶m);
|
|
|
return E_NONE;
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|