/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-04-23 lijian the first version */ #include "modbus_rtu.h" #include Modbus_RTU_t Modbus_RTU; /** * 设置modbus从机地址 * @param modbus_addr */ void set_Modbus_Addr(rt_uint16_t modbus_addr) { Modbus_RTU.modbus_addr = modbus_addr; } /** * @brief 获取Modbus从机地址 * @return rt_uint16 */ rt_uint16_t get_Modbus_Addr() { return Modbus_RTU.modbus_addr; } /** * 设置modbus寄存器地址 * @param modbus_reg_addr */ void set_Modbus_Reg_Addr(rt_uint16_t modbus_reg_addr) { Modbus_RTU.modbus_reg_addr = modbus_reg_addr; } /** * @brief 获取Modbus读取寄存器起始地址 * @return rt_uint16 */ rt_uint16_t get_Modbus_Reg_Addr() { return Modbus_RTU.modbus_reg_addr; } /** * @brief 设置Modbus读寄存器数量 * @return rt_uint16 */ void set_Modbus_Reg_Num(rt_uint16_t modbus_reg_num) { Modbus_RTU.modbus_reg_num = modbus_reg_num; } /** * @brief 获取Modbus读寄存器数量 * @return rt_uint16 */ rt_uint16_t get_Modbus_Reg_Num() { return Modbus_RTU.modbus_reg_num; } //功能码01(0x01): 读线圈状态(Read Coils) //功能码02(0x02): 读离散输入状态(Read Discrete Inputs) //功能码03(0x03): 读保持寄存器(Read Holding Registers) //功能码04(0x04): 读输入寄存器(Read Input Registers) //功能码05(0x05): 写单个线圈(Write Single Coil) //功能码06(0x06): 写单个保持寄存器(Write Single Holding Register) //功能码15(0x0F): 写多个线圈(Write Multiple Coils) //功能码16(0x10): 写多个保持寄存器(Write Multiple Holding Registers) /** * modbus初始化 */ void Modbus_init() { // Modbus_RTU.modbus_addr = (rt_uint16_t)0x01; // Modbus_RTU.modbus_reg_addr = (rt_uint16_t)0x00; // Modbus_RTU.modbus_reg_num = (rt_uint16_t)0x02; rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE, RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL); if (hinst == RT_NULL) { rt_kprintf("create rs485 instance fail.\n"); return; } rs485_set_recv_tmo(hinst, 1000); if (rs485_connect(hinst) != RT_EOK) { rs485_destory(hinst); rt_kprintf("rs485 connect fail.\n"); return; } rt_uint8_t ctx_send_buf[AGILE_MODBUS_MAX_ADU_LENGTH]; rt_uint8_t ctx_read_buf[AGILE_MODBUS_MAX_ADU_LENGTH]; agile_modbus_rtu_t ctx_rtu; agile_modbus_t *ctx = &ctx_rtu._ctx; agile_modbus_rtu_init(&ctx_rtu, ctx_send_buf, sizeof(ctx_send_buf), ctx_read_buf, sizeof(ctx_read_buf)); agile_modbus_set_slave(ctx, Modbus_RTU.modbus_addr); //地址 rt_kprintf("Modbus Running.\n"); rt_int8_t send_len; rt_int8_t read_len; rt_uint8_t i; rt_int8_t rc; // while (1) { rt_thread_mdelay(1000); //if(Modbus_RTU.modbus_func == 3){ send_len = agile_modbus_serialize_read_registers(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num); // // } else if(Modbus_RTU.modbus_func == 1){ // send_len = agile_modbus_serialize_read_bits(ctx, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num); // // } // rt_kprintf("rs485 send %d datas : ", send_len); // for (i = 0; i < send_len; i++) { // rt_kprintf("%02X ", ctx->send_buf[i]); // } // rt_kprintf("\n"); read_len = rs485_send_then_recv(hinst, (void *) ctx->send_buf, send_len, ctx->read_buf, ctx->read_bufsz); if (read_len < 0) { // rt_kprintf("rs485 send datas error.\n"); break; } if (read_len == 0) { // rt_kprintf("rs485 recv timeout.\n"); continue; } ctx->read_buf[read_len] = 0; // Bsp_Rs485_Tx(ctx->send_buf, send_len); // // int read_len = Bsp_Rs485_Rx(ctx->read_buf, ctx->read_bufsz); // if (read_len == 0) { // rt_kprintf("Receive timeout.\n"); continue; } rc = agile_modbus_deserialize_read_registers(ctx, read_len, Modbus_RTU.hold_register); if (rc < 0) { Modbus_RTU.modbus_rec = 0; rt_kprintf("Receive failed.\n"); if (rc != -1) rt_kprintf("Error code:%d\n", -128 - rc); continue; } Modbus_RTU.modbus_rec = 1; if (Modbus_RTU.log) { rt_kprintf("Hold Registers:"); for (i = 0; i < 10; i++) rt_kprintf("Register [%d]: 0x%04X\n", i, Modbus_RTU.hold_register[i]); } if (Modbus_RTU.modbus_rec) { //get_modbus_rec(); // MQTT_Send_Modbus(get_modbus_rec()); } rt_kprintf("\r\n\r\n\r\n"); } } void set_modbus_log(rt_uint8_t log){ Modbus_RTU.log = log; } /** * 获取modbus读取数据的转换后返回值 * @return */ rt_uint16_t get_modbus_rec(){ if (Modbus_RTU.modbus_rec) { rt_uint8_t high_d=0; rt_uint8_t low_d=0; if (Modbus_RTU.modbus_reg_num == 2) { high_d = Modbus_RTU.hold_register[0]; low_d = Modbus_RTU.hold_register[1]; rt_uint16_t rec = (high_d << 8) | low_d; return rec; } Modbus_RTU.modbus_rec =0; } return 0; } //void Bsp_Rs485_Tx(){ // //} // //void Bsp_Rs485_Rx(){ // //} // //static void rs485_sample_master(void *args) //{ // const char read_cmd[] = "read datas test\r\n"; // static rt_uint8_t buf[256]; // rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE, // RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL); // // if (hinst == RT_NULL) // { // LOG_E("create rs485 instance fail."); // return; // } // // rs485_set_recv_tmo(hinst, 1000); // if (rs485_connect(hinst) != RT_EOK) // { // rs485_destory(hinst); // LOG_E("rs485 connect fail."); // return; // } // // while (1) // { // int len = strlen(read_cmd); // len = rs485_send_then_recv(hinst, (void *) read_cmd, len, buf, sizeof(buf)); // if (len < 0) // { // LOG_E("rs485 send datas error."); // break; // } // // if (len == 0) // { // LOG_D("rs485 recv timeout."); // continue; // } // // buf[len] = 0; // LOG_D("rs485 recv %d datas : %s", len, buf); // } // //} // //#define PORT_NUM MB_MASTER_USING_PORT_NUM //#define PORT_BAUDRATE MB_MASTER_USING_PORT_BAUDRATE // //#define PORT_PARITY MB_PAR_EVEN // //#define MB_POLL_CYCLE_MS 500 // //#define func_Coil 1 //#define func_Holding 3 // //#define MODBUS_REG_NUM 30 //rt_uint16_t buffer[MODBUS_REG_NUM]; // ///* // * // * // */ // //void Copy_Holding(rt_uint16_t * Holding, rt_uint16_t reg_num){ // rt_uint16_t * a = get_modbus_03(); // for (rt_uint8_t var = 0; var < reg_num; var++) { // Holding[var] = a[var]; // } //} // //void Copy_Coil(rt_uint16_t * Coil, rt_uint16_t reg_num){ // unsigned char * a = get_modbus_01(); // for (rt_uint8_t var = 0; var < reg_num; var++) { // Coil[var] = a[var]; // } //} // // // //void Modbus_Read_Holding_Registers(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Holding){ // // while(1){ // eMBMasterPoll(); // // /* // * ucSndAddr 请求的从机地址,0代表广播。 // usRegAddr 读寄存器的地址 // usRegData 读寄存器的数量 // lTimeOut 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 // */ // eMBMasterReqReadHoldingRegister(addr, reg_addr, reg_num, 1000); // // rt_thread_mdelay(MB_POLL_CYCLE_MS); // // if (get_Holding_flag()) { // Copy_Holding(Holding, reg_num); // Modbus_RTU.modbus_rec =1; // get_modbus_rec(); // } // // } //} // //void Modbus_Read_Coils(rt_uint16_t addr, rt_uint16_t reg_addr, rt_uint16_t reg_num, rt_uint16_t * Coil){ // // while(1){ // eMBMasterPoll(); // // /* // * ucSndAddr 请求的从机地址,0代表广播。 // usCoilAddr 读线圈的地址 // usNCoils 读线圈的数量 // lTimeOut 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可 // */ // eMBMasterReqReadCoils(addr, reg_addr, reg_num, 1000); // // rt_thread_mdelay(MB_POLL_CYCLE_MS); // if (get_Coil_flag()) { // Copy_Coil(Coil , reg_num); // Modbus_RTU.modbus_rec =1; // } // } //} // // //void Modbus_config(void){ // // eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); // eMBMasterEnable(); // //// if(Modbus_RTU.modbus_func == func_Holding){ // Modbus_Read_Holding_Registers(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num ,buffer); //// } else if(Modbus_RTU.modbus_func == func_Coil){ //// Modbus_Read_Coils(Modbus_RTU.modbus_addr, Modbus_RTU.modbus_reg_addr, Modbus_RTU.modbus_reg_num , buffer); //// } // //} //