/* 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" /* 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_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); 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, ¶m); return E_NONE; } #endif