/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_PD /* 标准C库头文件. */ #include /* 用户代码头文件. */ #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