sggt/App/MODBUS/Src/modbus_485.c

506 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 )
{
//进入此处说明线圈寄存器的值被上位机修改
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 )
{
//进入此处说明线圈寄存器的值被上位机修改
tabdata.item3_page0_lightflag = get_coil_val(COIL_ADDR_LIGHT);
if(tabdata.item3_page0_lightflag)
{
LIGHT_ON;
}
else
{
LIGHT_OFF;
}
}
}
//离散输入寄存器,上位机只读
void modbus_reg_update_dis(void)
{}
//保持寄存器,读写
void modbus_reg_update_hold(void)
{}
//输入寄存器,上位机只读
void modbus_reg_update_input(void)
{}
void set_coil_val(uint8_t addr, uint8_t bit_val)
{
if( (addr < COIL_ADD_MIN)||(addr > COIL_ADD_MAX)||(bit_val > 1) ) return;
addr -= COIL_ADD_MIN;
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)
{
uint8_t result = 0;
if( (addr < COIL_ADD_MIN)||(addr > COIL_ADD_MAX) ) return;
addr -= COIL_ADD_MIN;
uint8_t pcoil = addr / 8; //数组的第几个元素, 0-7
uint8_t pbit = addr % 8; //元素的第几位, 0-7
result = 0x01 & (CoilState[pcoil] >> pbit);
return result;
}