/* #include #include * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2025-10-20 Administrator the first version * 2025-11-12 Modified Switch to IDLE interrupt mode (no DMA, no ringbuffer) * 2025-11-21 Fixed Enable RX_IDLE mode correctly for RT-Thread 5.1 */ #include "rtthread.h" #include "modbus.h" #include "SC828_DATA_table.h" #define DBG_TAG "plc.rtu" #define DBG_LVL DBG_LOG #include static const mb_backend_param_t mb_bkd_prm = { .rtu.dev = "uart2", //设备名 .rtu.baudrate = 57600, //波特率 .rtu.parity = 0, //校验位, 0-无, 1-奇, 2-偶 .rtu.pin = -1, //控制引脚, <0 表示不使用 .rtu.lvl = 0 //控制发送电平 }; extern unsigned char sys_time[6]; static void mb_plc_read_regs(mb_inst_t *hinst) { if (mb_connect(hinst) < 0)//连接失败, 延时返回 { LOG_E("modbus connect fail."); return; } //输入m0000->rtu2000 uint8_t r_buffer[(DI_TABLE_SIZE + 7) / 8]; //读取 Modbus bits int mrx = mb_read_bits(hinst, 2000, DI_TABLE_SIZE, r_buffer); if (mrx > 0) { //解包到数据表 for (int i = 0; i < DI_TABLE_SIZE; i++) { di_table[i].current_state = (r_buffer[i / 8] >> (i % 8)) & 1; } }else { rt_thread_mdelay(500); } // 输出 m0256 -> RTU 2256 uint8_t w_buffer[(DO_TABLE_SIZE + 7) / 8]; // 关键:初始化为0 // 打包 do_table 到 bit_buffer for (int i = 0; i < DO_TABLE_SIZE; i++) { const int byte_idx = i / 8; const int bit_idx = i % 8; const uint8_t bit_mask = (1U << bit_idx); if (do_table[i].current_state) { w_buffer[byte_idx] |= bit_mask; } else { w_buffer[byte_idx] &= ~bit_mask; } } // 写入 Modbus int mwy = mb_write_bits(hinst, 2256, DO_TABLE_SIZE, w_buffer); if (mwy ==0) { rt_thread_mdelay(500); } //输入寄存器d0->6000 u16 r_regsD[AI_TABLE_SIZE]; // 读 Modbus int mrd = mb_read_regs(hinst, 6000, AI_TABLE_SIZE, r_regsD); if (mrd > 0) { for (int i = 0; i < AI_TABLE_SIZE; i++) { ai_table[i].current_Value = r_regsD[i]; } }else { rt_thread_mdelay(500); } //输出寄存器d100->6100 u16 w_regsD [AO_TABLE_SIZE]; for (int i = 0; i < AO_TABLE_SIZE; i++) { w_regsD [i] = ao_table[i].current_Value; } // 写入 Modbus int mwd = mb_write_regs(hinst, 6100, AO_TABLE_SIZE, w_regsD); if (mwd == 0) { rt_thread_mdelay(500); } } static void mb_plc_thread(void *args)//线程服务函数 { mb_inst_t *hinst = mb_create(MB_BACKEND_TYPE_RTU, &mb_bkd_prm); RT_ASSERT(hinst != NULL); mb_set_slave(hinst, 1);//修改从机地址, 默认地址为1, 可根据实际情况修改 mb_set_prot(hinst, MB_PROT_RTU);//修改通信协议类型, RTU后端默认使用MODBUS-RTU通信协议 mb_set_tmo(hinst, 500, 15);//修改超时时间, 应答超时500ms(默认300ms), 字节超时15ms(默认32ms) while(1) { mb_plc_read_regs(hinst); rt_thread_mdelay(50); } } extern struct rt_memheap sram_DTCMRAM; static struct rt_thread dat_plc_thread; static void *dat_plc_stack __attribute__((aligned(4)))= RT_NULL ; static int mb_rtu_master_startup(void) { rt_err_t db_err; dat_plc_stack = rt_memheap_alloc(&sram_DTCMRAM, 1024*2); db_err = rt_thread_init(&dat_plc_thread, "plc_rtu", mb_plc_thread, RT_NULL,dat_plc_stack, 1024*2, 10, 10); if(db_err != RT_EOK) { LOG_D("Failed to create SCCM_uart thread!"); return -1; } rt_thread_startup(&dat_plc_thread); LOG_I("Create SCCM_uart thread"); /*rt_thread_t tid = rt_thread_create("plc_rtu", mb_plc_thread, NULL, 2048, 5, 20); RT_ASSERT(tid != NULL); rt_thread_startup(tid);*/ return(0); } INIT_APP_EXPORT(mb_rtu_master_startup);