#include "modbus_485.h" uint32_t tick_start = 0; uint32_t tick_middle = 0; uint32_t tick_end = 0; //uint32_t trans_log_rx = 0; uint32_t trans_log_tx = 0; TRANS_PROCESS st_flag = TRANSPARENT_WAIT; void parse_scom_485(st_scom *scom) { if ((scom == &scom2_rs485) && (scom->rx_flag == TRUE)) { scom->rx_flag = FALSE; if ((scom->rx_buff[0] == 0xff) && (scom->rx_buff[1] == 0xff) && (scom->rx_buff[scom->rx_len - 1] == 0xaa)) { vTaskDelay(10); HAL_UART_Transmit(&huart2, scom->rx_buff, scom->rx_len, 0xFFFF); } scom->rx_len = 0; } } void transparent_tim(void) { switch (sig_trans) { case TRANS_NONE: {} break; case TRANS_HART_TO_PC: { trans_hart2pc(); } break; case TRANS_PC_TO_HART: { trans_pc2hart(); } break; case TRANS_BLE_TO_PC: { trans_ble2pc(); } break; case TRANS_PC_TO_BLE: { trans_pc2ble(); } break; case TRANS_MODBUS_PC_TO_SIG: { trans_modbus_pc2sig(); } break; case TRANS_MODBUS_SIG_TO_SLAVE: { trans_modbus_sig2slave(); } break; default: break; } } void trans_hart2pc(void) { //来自HART设备的数据是否接收完成 if (scom1_hart.rx_flag == TRUE) { scom1_hart.rx_flag = FALSE; //接收到的数据是否符合HART数据报,符合则写入485的tx,准备发送至上位机 if ((scom1_hart.rx_buff[0] == 0xff) && (scom1_hart.rx_buff[1] == 0xff) && (scom1_hart.rx_buff[scom1_hart.rx_len - 1] == 0xAA)) { memcpy(scom2_rs485.tx_buff, scom1_hart.rx_buff, scom1_hart.rx_len); scom2_rs485.tx_len = scom1_hart.rx_len; scom2_rs485.tx_flag = TRUE; } if(scom2_rs485.tx_flag == TRUE) { scom2_rs485.tx_flag = FALSE; //将数据发送至上位机 HAL_UART_Transmit_DMA(&huart2, scom2_rs485.tx_buff, scom2_rs485.tx_len); } //清空缓存区,等待新的数据 memset(scom1_hart.rx_buff, 0, scom1_hart.rx_len); scom1_hart.rx_len = 0; } } void trans_pc2hart(void) { if (scom2_rs485.rx_flag == TRUE) { scom2_rs485.rx_flag = FALSE; if ((scom2_rs485.rx_buff[0] == 0xff) && (scom2_rs485.rx_buff[1] == 0xff) && (scom2_rs485.rx_buff[scom2_rs485.rx_len - 1] == 0xaa)) { //接收到的数据是否符合HART数据报,符合则写入HART的tx,准备发送至HART设备 memcpy(scom1_hart.tx_buff, scom2_rs485.rx_buff, scom2_rs485.rx_len); scom1_hart.tx_len = scom2_rs485.rx_len; scom1_hart.tx_flag = TRUE; } //来自上位机的数据是否准备完毕 if (scom1_hart.tx_flag == TRUE) { scom1_hart.tx_flag = FALSE; HART_RTS(RTS_ON); wu_delay_us(10000); //将tx中的数据发送至HART设备 HAL_UART_Transmit_DMA(&huart1, scom1_hart.tx_buff, scom1_hart.tx_len); } //清空缓存区,等待新的数据 memset(scom2_rs485.rx_buff, 0, scom2_rs485.rx_len); scom2_rs485.rx_len = 0; } } void trans_ble2pc(void) { if( ble_init() == 0 ) return; if (scom6_ble.rx_flag == TRUE) { scom6_ble.rx_flag = FALSE; //将接收到的数据存入485的tx,准备发送至上位机 memcpy(scom2_rs485.tx_buff, scom6_ble.rx_buff, scom6_ble.rx_len); scom2_rs485.tx_len = scom6_ble.rx_len; scom2_rs485.tx_flag = TRUE; if(scom2_rs485.tx_flag == TRUE) { scom2_rs485.tx_flag = FALSE; //将数据发送至上位机 HAL_UART_Transmit_DMA(&huart2, scom2_rs485.tx_buff, scom2_rs485.tx_len); } //清空缓存区,等待新的数据 memset(scom6_ble.rx_buff, 0, scom6_ble.rx_len); scom6_ble.rx_len = 0; } } void trans_pc2ble(void) { if (scom2_rs485.rx_flag == TRUE) { scom2_rs485.rx_flag = FALSE; //将接收到的数据存入BLE的tx,准备发送至蓝牙设备 memcpy(scom6_ble.tx_buff, scom2_rs485.rx_buff, scom2_rs485.rx_len); scom6_ble.tx_len = scom2_rs485.rx_len; scom6_ble.tx_flag = TRUE; //来自上位机的数据是否准备完毕 if (scom6_ble.tx_flag == TRUE) { scom6_ble.tx_flag = FALSE; //将tx中的数据发送至蓝牙设备 HAL_UART_Transmit_DMA(&huart6, scom6_ble.tx_buff, scom6_ble.tx_len); } //清空缓存区,等待新的数据 memset(scom2_rs485.rx_buff, 0, scom2_rs485.rx_len); scom2_rs485.rx_len = 0; } } void trans_modbus_pc2sig(void) { if (scom2_rs485.rx_flag == TRUE) { scom2_rs485.rx_flag = FALSE; modbus_process_rtu(); if(scom2_rs485.tx_flag == TRUE) { scom2_rs485.tx_flag = FALSE; //将数据发送至上位机 HAL_UART_Transmit_DMA(&huart2, scom2_rs485.tx_buff, scom2_rs485.tx_len); } //清空缓存区,等待新的数据 memset(scom2_rs485.rx_buff, 0, scom2_rs485.rx_len); scom2_rs485.rx_len = 0; } } uint8_t sig2slave_step = 0; uint8_t sig2slave_data_length_total = 0; uint8_t buffer_size_temp = BUFFER_SIZE; void trans_modbus_sig2slave(void) { if (scom2_rs485.rx_flag == TRUE) { scom2_rs485.rx_flag = FALSE; switch (sig2slave_step) { case 0: { //进入此处说明已经接收完成一部分数据,重新开始超时计时,发送标志复位 mod_master.tx_flag = TX_NONE; sig2slave_current_tick = 0; //记录第一次接收到的数据长度 sig2slave_data_length_total = scom2_rs485.rx_len; //修改剩余buff长度,继续接收 buffer_size_temp -= scom2_rs485.rx_len; HAL_UART_Receive_DMA(&huart2, scom2_rs485.rx_buff + sig2slave_data_length_total, buffer_size_temp); sig2slave_step++; } break; case 1: { //超时时间内再次收到数据,重新开始超时计时 sig2slave_current_tick = 0; //本次收到的数据长度 uint8_t sig2slave_data_length_temp = buffer_size_temp - __HAL_DMA_GET_COUNTER(huart2.hdmarx); //累计收到的数据长度 sig2slave_data_length_total += sig2slave_data_length_temp; scom2_rs485.rx_len = sig2slave_data_length_total; if(scom2_rs485.rx_len < BUFFER_SIZE) { //继续接收 buffer_size_temp -= sig2slave_data_length_temp; HAL_UART_Receive_DMA(&huart2, scom2_rs485.rx_buff + sig2slave_data_length_total, buffer_size_temp); } } break; case 2: { if(mod_master.rx_error_message != RX_ERROR_TIMEOUT) { //进入此处说明收到了数据,并且超时计时期间内未收到新的数据 modbus_rtu_master_analysis(); } else { strcpy(mod_master.result_display, "ERROR: TIMEOUT"); } //在屏幕上显示 mod_master.result_display 字符串 lv_label_set_text(guider_ui.screen_modbus_trx_value_Rx, mod_master.result_display); //处理完成后复位相关参数 sig2slave_step = 0; sig_trans = TRANS_NONE; memset(scom2_rs485.rx_buff, 0, scom2_rs485.rx_len); scom2_rs485.rx_len = 0; sig2slave_data_length_total = 0; buffer_size_temp = BUFFER_SIZE; HAL_UART_Receive_DMA(&huart2, scom2_rs485.rx_buff, BUFFER_SIZE); } break; default: break; } } } void trans_start_capture(void) { uint8_t data_len1 = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx); uint8_t data_len2 = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart2.hdmarx); uint8_t data_len6 = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart6.hdmarx); if( (1 <= data_len1 )&&( data_len1 <= 3) ) { if(tabdata.hart_enable) { if (st_flag == TRANSPARENT_WAIT) { st_flag = TRANSPARENT_RECIEVE_START; tick_start = xTaskGetTickCountFromISR(); } } } if( (1 <= data_len2 )&&( data_len2 <= 3) ) { if(tabdata.bluetooth_enable) { if (st_flag == TRANSPARENT_WAIT) { st_flag = TRANSPARENT_RECIEVE_START; tick_start = xTaskGetTickCountFromISR(); } } } if( (1 <= data_len6 )&&( data_len6 <= 3) ) { if(tabdata.hart_enable||tabdata.bluetooth_enable||tabdata.modbus_enable) { if (st_flag == TRANSPARENT_WAIT) { st_flag = TRANSPARENT_RECIEVE_START; tick_start = xTaskGetTickCountFromISR(); } } } } uint8_t trans_enable_check(st_scom *scom) { uint8_t result = 0; if( scom == &scom1_hart ) { if(tabdata.hart_enable) { result = 1; sig_trans = TRANS_HART_TO_PC; } } if( scom == &scom6_ble ) { if(tabdata.bluetooth_enable) { result = 1; sig_trans = TRANS_BLE_TO_PC; } } if( scom == &scom2_rs485 ) { if(tabdata.hart_enable) { result = 1; sig_trans = TRANS_PC_TO_HART; } else if(tabdata.bluetooth_enable) { result = 1; sig_trans = TRANS_PC_TO_BLE; } else if(tabdata.modbus_enable) { result = 1; switch (tabdata.modbus_type) { case SIG_SLAVE: { sig_trans = TRANS_MODBUS_PC_TO_SIG; } break; case SIG_MASTER: { sig_trans = TRANS_MODBUS_SIG_TO_SLAVE; } break; default: break; } } } return result; } //处理modbus寄存器值的更新与写入 void modbus_registers_update(void) { //线圈寄存器 modbus_reg_update_coil(); //离散状态寄存器 modbus_reg_update_dis(); //保持寄存器 modbus_reg_update_hold(); //输入寄存器 modbus_reg_update_input(); } //线圈寄存器,读写 void modbus_reg_update_coil(void) { if( (get_coil_val(COIL_ADDR_ON_OFF) != menu_data.io_on2off)&&(get_coil_val(COIL_ADDR_ON_OFF) < 2) ) { //进入此处说明线圈寄存器的值被上位机修改 if( menu_data.scr_now == SCREEN_MAIN ) { //只有在主界面时,修改内容才生效 menu_data.io_on2off = get_coil_val(COIL_ADDR_ON_OFF); io_on2off_status(); } else { //拒绝修改内容 set_coil_val(COIL_ADDR_ON_OFF, menu_data.io_on2off); } } if( (get_coil_val(COIL_ADDR_LIGHT) != tabdata.item3_page0_lightflag)&&(get_coil_val(COIL_ADDR_LIGHT) < 2) ) { //进入此处说明线圈寄存器的值被上位机修改 tabdata.item3_page0_lightflag = get_coil_val(COIL_ADDR_LIGHT); if(tabdata.item3_page0_lightflag) { LIGHT_ON; } else { LIGHT_OFF; } } if( (get_coil_val(COIL_ADDR_CONFIG_SAVE) == 1)&&(tabdata.item3_page0_saveflag == 0) ) { if( (menu_data.scr_now == SCREEN_SETTING)&&(tabdata.item3_page0_resetflag != 1) ) { //当前处于设置界面,并且未处于重置过程中,执行保存 tabdata.item3_page0_saveflag = 1; } else { //拒绝修改 set_coil_val(COIL_ADDR_CONFIG_SAVE, 0); } } if( (get_coil_val(COIL_ADDR_CONFIG_RESET) == 1)&&(tabdata.item3_page0_resetflag == 0) ) { if( (menu_data.scr_now == SCREEN_SETTING)&&(tabdata.item3_page0_saveflag != 1) ) { //当前处于设置界面,并且未处于保存过程中,执行复位 tabdata.item3_page0_resetflag = 1; } else { //拒绝修改 set_coil_val(COIL_ADDR_CONFIG_RESET, 0); } } if( get_coil_val(COIL_ADDR_SCREEN_SWITCH) != ( (uint8_t)menu_data.scr_now - 1 ) ) { switch (menu_data.scr_now) { case SCREEN_INIT: { //拒绝修改,开机动画视作主界面 set_coil_val(COIL_ADDR_SCREEN_SWITCH, 0); } break; case SCREEN_MAIN: { //切换至设置界面; scr_setting_recover(); lv_scr_load(guider_ui.screen_setting); lv_obj_clear_flag(guider_ui.screen_setting, LV_OBJ_FLAG_HIDDEN); //隐藏主界面对象 lv_obj_add_flag(guider_ui.screen_main, LV_OBJ_FLAG_HIDDEN); menu_data.scr_now = SCREEN_SETTING; //当前界面为详细设置菜单 set_coil_val(COIL_ADDR_SCREEN_SWITCH, 1); } break; case SCREEN_SETTING: { //切换至主界面; //加载主界面 if(!scr_main_set_flag) { scr_main_set_flag = 1; setup_scr_screen_main(&guider_ui); delay_cnt(200); //不加延时有概率卡死 } scr_main_recover(); lv_scr_load(guider_ui.screen_main); lv_obj_clear_flag(guider_ui.screen_main, LV_OBJ_FLAG_HIDDEN); //隐藏设置界面对象 lv_obj_add_flag(guider_ui.screen_setting, LV_OBJ_FLAG_HIDDEN); menu_data.scr_now = SCREEN_MAIN; set_coil_val(COIL_ADDR_SCREEN_SWITCH, 0); } break; default: { //拒绝修改,其他界面视作设置界面 set_coil_val(COIL_ADDR_SCREEN_SWITCH, 1); } break; } } } //离散输入寄存器,上位机只读 void modbus_reg_update_dis(void) {} //保持寄存器,读写 uint16_t work_mode_pv = 0; void modbus_reg_update_hold(void) { work_mode_pv = 1 + (uint16_t)menu_data.input_mode_type + (menu_data.io_mode == IO_OUTPUT) * 15; if( HoldReg[HOLD_ADDR_SET_WORK_MODE] != work_mode_pv ) { if(menu_data.scr_now == SCREEN_MAIN) { } } } //输入寄存器,上位机只读 void modbus_reg_update_input(void) {} void set_coil_val(uint8_t addr, uint8_t bit_val) { if( (addr > COIL_ADD_MAX)||(bit_val > 1) ) return; addr -= COIL_ADD_MIN; if( addr > 200 ) return; uint8_t pcoil = addr / 8; //数组的第几个元素, 0-7 uint8_t pbit = addr % 8; //元素的第几位, 0-7 uint8_t fac = 0; //辅助计算的因子 switch (bit_val) { case 0: { fac = ~(1 << pbit); CoilState[pcoil] &= fac; } break; case 1: { fac = 1 << pbit; CoilState[pcoil] |= fac; } break; default: break; } } uint8_t get_coil_val(uint8_t addr) { if( addr > COIL_ADD_MAX ) return 99; addr -= COIL_ADD_MIN; if( addr > 200 ) return 99; uint8_t result = 0; uint8_t pcoil = addr / 8; //数组的第几个元素, 0-7 uint8_t pbit = addr % 8; //元素的第几位, 0-7 result = 0x01 & (CoilState[pcoil] >> pbit); return result; }