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.

309 lines
8.3 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"
#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_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);
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, &param);
return E_NONE;
}
#endif