sggt/App/MODBUS/Src/modbus_rtu_master.c

222 lines
7.5 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_rtu_master.h"
MODBUS_MASTER mod_master;
void modbus_rtu_master_init(void)
{
mod_master.target_id = 0x00;
mod_master.command_code = 0x00;
mod_master.start_address = 0x0000;
mod_master.register_num = 0x0000;
mod_master.crc16 = 0x0000;
mod_master.byte_num = 0;
memset(mod_master.data_tx_value8, 0, TX_DATA_MAX);
memset(mod_master.data_tx_value16, 0, TX_DATA_MAX);
memset(mod_master.data_tx, 0, TX_BUFF_MAX);
memset(mod_master.data_rx, 0, RX_BUFF_MAX);
mod_master.data_tx_len = 0;
mod_master.data_rx_len = 0;
mod_master.rx_error_message = RX_ERROR_NONE;
mod_master.tx_error_message = TX_ERROR_NONE;
mod_master.timeout = 1000;
mod_master.rx_flag = RX_NONE;
mod_master.tx_flag = TX_NONE;
}
void modbus_rtu_master_load(void)
{
mod_master.data_tx[0] = mod_master.target_id;
mod_master.data_tx[1] = mod_master.command_code;
memset(mod_master.data_rx, 0, sizeof(mod_master.data_rx));
switch (mod_master.data_tx[1])
{
//读四种寄存器的格式一致
case ReadCoilState:
{
//注释break直接向下穿透
}
//break;
case ReadDisInputState:
{
//注释break直接向下穿透
}
//break;
case ReadHoldReg:
{
//注释break直接向下穿透
}
//break;
case ReadInputReg:
{
mod_master.data_tx[2] = (uint8_t)(mod_master.start_address >> 8);
mod_master.data_tx[3] = (uint8_t)(mod_master.start_address & 0x00FF);
mod_master.data_tx[4] = (uint8_t)(mod_master.register_num >> 8);
mod_master.data_tx[5] = (uint8_t)(mod_master.register_num & 0x00FF);
mod_master.crc16 = ModbusCRC16(mod_master.data_tx, 6);
mod_master.data_tx[6] = (uint8_t)(mod_master.crc16 & 0x00FF);
mod_master.data_tx[7] = (uint8_t)(mod_master.crc16 >> 8);
mod_master.data_tx_len = 8;
}
break;
case WriteSingleCoil:
{
mod_master.data_tx[2] = (uint8_t)(mod_master.start_address >> 8);
mod_master.data_tx[3] = (uint8_t)(mod_master.start_address & 0x00FF);
mod_master.data_tx[4] = (uint8_t)(mod_master.data_tx_value8[0] >> 8);
mod_master.data_tx[5] = (uint8_t)(mod_master.data_tx_value8[0] & 0x00FF);
mod_master.crc16 = ModbusCRC16(mod_master.data_tx, 6);
mod_master.data_tx[6] = (uint8_t)(mod_master.crc16 & 0x00FF);
mod_master.data_tx[7] = (uint8_t)(mod_master.crc16 >> 8);
mod_master.data_tx_len = 8;
}
break;
case WriteSingleReg:
{
mod_master.data_tx[2] = (uint8_t)(mod_master.start_address >> 8);
mod_master.data_tx[3] = (uint8_t)(mod_master.start_address & 0x00FF);
mod_master.data_tx[4] = (uint8_t)(mod_master.data_tx_value16[0] >> 8);
mod_master.data_tx[5] = (uint8_t)(mod_master.data_tx_value16[0] & 0x00FF);
mod_master.crc16 = ModbusCRC16(mod_master.data_tx, 6);
mod_master.data_tx[6] = (uint8_t)(mod_master.crc16 & 0x00FF);
mod_master.data_tx[7] = (uint8_t)(mod_master.crc16 >> 8);
mod_master.data_tx_len = 8;
}
break;
case WriteMultiCoil:
{
if( mod_master.register_num % 8 )
{
//线圈数量不为8的倍数时字节数 == (线圈数量/8 + 1
if( (mod_master.register_num/8 + 1) != mod_master.byte_num )
{
mod_master.tx_error_message = TX_ERROR_COIL_NUM;
return;
}
}
else
{
//线圈数量为8的倍数时字节数 == 线圈数量/8
if( (mod_master.register_num/8) != mod_master.byte_num )
{
mod_master.tx_error_message = TX_ERROR_COIL_NUM;
return;
}
}
mod_master.data_tx[2] = (uint8_t)(mod_master.start_address >> 8);
mod_master.data_tx[3] = (uint8_t)(mod_master.start_address & 0x00FF);
mod_master.data_tx[4] = (uint8_t)(mod_master.register_num >> 8);
mod_master.data_tx[5] = (uint8_t)(mod_master.register_num & 0x00FF);
mod_master.data_tx[6] = mod_master.byte_num;
for(uint8_t i = 1; i <= mod_master.byte_num; i++ )
{
mod_master.data_tx[6 + i] = mod_master.data_tx_value8[i - 1];
}
mod_master.crc16 = ModbusCRC16(mod_master.data_tx, 7 + mod_master.byte_num);
mod_master.data_tx[7 + mod_master.byte_num] = (uint8_t)(mod_master.crc16 & 0x00FF);
mod_master.data_tx[8 + mod_master.byte_num] = (uint8_t)(mod_master.crc16 >> 8);
mod_master.data_tx_len = 8 + mod_master.byte_num + 1;
}
break;
case WriteMultiReg:
{
if( (mod_master.register_num * 2) != mod_master.byte_num )
{
//字节数 == (寄存器数量*2
mod_master.tx_error_message = TX_ERROR_HOLDREG_NUM;
return;
}
mod_master.data_tx[2] = (uint8_t)(mod_master.start_address >> 8);
mod_master.data_tx[3] = (uint8_t)(mod_master.start_address & 0x00FF);
mod_master.data_tx[4] = (uint8_t)(mod_master.register_num >> 8);
mod_master.data_tx[5] = (uint8_t)(mod_master.register_num & 0x00FF);
mod_master.data_tx[6] = mod_master.byte_num;
for(uint8_t i = 1; i <= mod_master.byte_num; i++ )
{
mod_master.data_tx[6 + i] = mod_master.data_tx_value16[ (i - 1)/2 ] >> ( 8*(i%2) );
}
mod_master.crc16 = ModbusCRC16(mod_master.data_tx, 7 + mod_master.byte_num);
mod_master.data_tx[7 + mod_master.byte_num] = (uint8_t)(mod_master.crc16 & 0x00FF);
mod_master.data_tx[8 + mod_master.byte_num] = (uint8_t)(mod_master.crc16 >> 8);
mod_master.data_tx_len = 8 + mod_master.byte_num + 1;
}
break;
default:
{
mod_master.tx_error_message = TX_ERROR_WRONG_CMD;
}
break;
}
}
void modbus_rtu_master_send(void)
{
if(mod_master.tx_error_message == TX_ERROR_NONE)
{
mod_master.rx_flag = TX_WAITING;
//将准备好的数据发送至从设备
memcpy(scom2_rs485.tx_buff, mod_master.data_tx, mod_master.data_tx_len);
scom2_rs485.tx_len = mod_master.data_tx_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);
}
//在发送回调中判断发送是否完成
sig_trans = TRANS_MODBUS_SIG_TO_SLAVE;
}
}
void modbus_rtu_master_analysis(void)
{
if(scom2_rs485.rx_len > RX_BUFF_MAX)
{
mod_master.rx_error_message = RX_ERROR_OVERFLOW;
return;
}
mod_master.data_rx_len = scom2_rs485.rx_len;
memcpy(mod_master.data_rx, scom2_rs485.rx_buff, mod_master.data_rx_len);
if(mod_master.data_rx[0] != mod_master.target_id)
{
mod_master.rx_error_message = RX_ERROR_WRONG_ID;
return;
}
if(mod_master.data_rx[1] <= 0x80)
{
//收到的是正常响应
}
else
{
//收到的是异常响应
ex_message = (eMBException)mod_master.data_rx[2];
}
mod_master.rx_flag = RX_OK;
}