/* * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ #include "aos/kernel.h" #include "mbmaster.h" #include "ulog/ulog.h" #if AOS_COMP_CLI #include "aos/cli.h" #endif /* Define the parameters */ #define SERIAL_PORT (1) /* uart port */ #define SERIAL_BAUD_RATE (9600) /* uart baud rate */ #define DEVICE1_SLAVE_ADDR_1 (0x1) /* remote deveice address */ #define DEVICE1_SLAVE_ADDR_2 (0x2) /* remote deveice address */ #define DEVICE1_REG1_ADDR (0x0) /* register address of remote device */ #define RECV_LEN_MAX (20) /* buffer len, must >= (REQ_REGISTER_NUMBER * 2) */ #define REQ_REGISTER_NUMBER (10) /* Number of registers requested */ /* mode name used by ulog */ #define MODBUSM_APP "modbus_app" void mb_master_main(void) { uint8_t buf[RECV_LEN_MAX]; uint8_t len; mb_status_t status; uint16_t simulator1 = 0, simulator2 = 0; uint16_t data_write = 0, data_resp = 0; uint16_t *register_buf; /* The handler is allocated by calling the aos_mbmaster_rtu_init */ mb_handler_t *mb_handler_master; /** * Initialize the modbus communication port, using rtu mode. * Need to set the appropriatet port number, baud rate, parity * according to the actual situation. */ status = mbmaster_rtu_init(&mb_handler_master, SERIAL_PORT, SERIAL_BAUD_RATE, MB_PAR_NONE, 500); LOGD(MODBUS_MOUDLE, "mbmaster_rtu_init status is %d\n", status); if (status != MB_SUCCESS) { LOGE(MODBUSM_APP, "mbmaster init error\n"); return; } /* note: This example loops every 2 seconds, first sending a write request, then sending a read request. */ while (1) { #if 1 /** * Initiate write single registers request. * data_resp: respond from the remote device. If the write operation succeeds, * it's equal to data_write. */ status = mbmaster_write_single_register(mb_handler_master, DEVICE1_SLAVE_ADDR_1, DEVICE1_REG1_ADDR, data_write, NULL, &data_resp, NULL, AOS_WAIT_FOREVER); if (status == MB_SUCCESS) { if (data_write != data_resp) { LOGE(MODBUSM_APP, "write single register error\n"); } else { LOGI(MODBUSM_APP, "write single register ok\n"); } } else { LOGE(MODBUSM_APP, "write single register error\n"); } data_write++; /* generate a new value */ aos_msleep(1000 * 3); #endif #if 1 memset(buf, 0, RECV_LEN_MAX); /** * Initiate read holding registers request * The buf length needs to be greater than or equal to (REQ_REGISTER_NUMBER * 2) */ status = mbmaster_read_holding_registers(mb_handler_master, DEVICE1_SLAVE_ADDR_2, DEVICE1_REG1_ADDR, REQ_REGISTER_NUMBER, buf, &len, AOS_WAIT_FOREVER); if (status == MB_SUCCESS) { /* The register length on modbus is 16 bits */ register_buf = (uint16_t *)buf; simulator1 = register_buf[0]; simulator2 = register_buf[1]; LOGI(MODBUSM_APP, "read holding register simulator1: %d,simulator2: %d\n", simulator1, simulator2); } else { LOGE(MODBUSM_APP, "read holding register error\n"); } #endif aos_msleep(1000 * 3); } } void mb_slave_main(uint8_t dev_addr) { uint8_t buf[RECV_LEN_MAX]; uint8_t len; mb_status_t status; uint16_t simulator1 = 0, simulator2 = 0; uint16_t data_write = 0, data_resp = 0; uint16_t *register_buf; /* The handler is allocated by calling the aos_mbmaster_rtu_init */ mb_handler_t *mb_handler_slave = NULL; /** * Initialize the modbus communication port, using rtu mode. * Need to set the appropriatet port number, baud rate, parity * according to the actual situation. */ status = mbmaster_rtu_init(&mb_handler_slave, SERIAL_PORT, SERIAL_BAUD_RATE, MB_PAR_NONE, 100); LOGD(MODBUS_MOUDLE, "mbmaster_rtu_init status is %d\n", status); if (status != MB_SUCCESS) { LOGE(MODBUSM_APP, "mbmaster init error\n"); return; } /* wait slave respond */ LOGD(MODBUS_MOUDLE, "device [0x%x] waiting for cmd\n", dev_addr); while (1) { /* frame recv */ status = mb_handler_slave->frame_recv(mb_handler_slave); if (status == MB_SUCCESS) { /* frame handle and response */ status = mb_handler_slave->adu_disassemble(mb_handler_slave); if (status == MB_SUCCESS) { uint8_t addr = mb_handler_slave->slave_addr; uint8_t len = mb_handler_slave->pdu_length; uint8_t offset = mb_handler_slave->pdu_offset; uint8_t *data = mb_handler_slave->mb_frame_buff; if (addr == dev_addr) { switch (addr) { case DEVICE1_SLAVE_ADDR_1: // no need to process 0x06 mb_handler_slave->pdu_length = len; break; case DEVICE1_SLAVE_ADDR_2: // 0x01 0x03 0x00 0x00 0x00 0x0a 0xc5 0xcd { uint16_t reg_start = data[2] << 8 | data[3]; uint16_t reg_len = data[4] << 8 | data[5]; mb_handler_slave->pdu_length = reg_len * 2 + 2; data[ADU_SER_PDU_OFF + 1] = reg_len * 2; for (uint16_t k = 0; k < reg_len; k++) { data[ADU_SER_PDU_OFF + 2 + k * 2] = 0x00; data[ADU_SER_PDU_OFF + 2 + k * 2 + 1] = k & 0xFF; } break; } default: LOGE(MODBUS_MOUDLE, "Unsupported device addr [0x%2X]\n", addr); } status = mb_handler_slave->adu_assemble(mb_handler_slave); status = mb_handler_slave->frame_send(mb_handler_slave, 100); if (status != MB_SUCCESS) { LOGD(MODBUS_MOUDLE, "Failed to send response to master\n"); } } } } } } int mbmaster_comp_example(int argc, char *argv[]) { aos_set_log_level(AOS_LL_DEBUG); LOGI(MODBUSM_APP, "mbmaster test\n"); mb_master_main(); return 0; } int mbslave_comp_example(int argc, char *argv[]) { aos_set_log_level(AOS_LL_DEBUG); if (argc == 1) { mb_slave_main(DEVICE1_SLAVE_ADDR_1); } else { mb_slave_main(*argv[1] - 48); } return 0; } #if AOS_COMP_CLI /* reg args: fun, cmd, description*/ ALIOS_CLI_CMD_REGISTER(mbmaster_comp_example, mbmaster_example, mbmaster component base master example) ALIOS_CLI_CMD_REGISTER(mbslave_comp_example, mbslave_example, mbmaster component base salve example) #endif