You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
11 KiB
280 lines
11 KiB
#include "modbus_processer.hpp"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
/***********************485rx**************************/
|
|
// 接收到了多少数据
|
|
// volatile uint16_t s_modbus_uart_rx_off = 0;
|
|
// 当前是否正在处理接收到的数据
|
|
// volatile bool s_modbus_uart_rx_buf_is_processing = false;
|
|
/***********************485tx**************************/
|
|
static modbus_processer_t* g_processer;
|
|
|
|
#define GET_UINT16(uint8) (uint16_t)(((uint16_t)((uint8)[0]) << 8) + (uint8)[1])
|
|
void modbus_processer_process_data(uint8_t* rx, uint16_t len);
|
|
void modbus_processer_init(modbus_processer_t* processer) { g_processer = processer; }
|
|
|
|
void ModbusProcessRxData(uint8_t* rxraw, uint8_t length, ModbusMasterData_t* rxparsed) {
|
|
rxparsed->functionCode = (ModbusFunctionCode)rxraw[1];
|
|
if (rxraw[1] == ModbusOrder01 || rxraw[1] == ModbusOrder02 || rxraw[1] == ModbusOrder03 || rxraw[1] == ModbusOrder04) {
|
|
/**
|
|
* @brief
|
|
* 由于是共用体,所以均给001赋值即可
|
|
*/
|
|
rxparsed->d.O01.startbit = rxraw[2] * 256 + rxraw[3];
|
|
rxparsed->d.O01.numbit = rxraw[4] * 256 + rxraw[5];
|
|
} else if (rxraw[1] == ModbusOrder0F || rxraw[1] == ModbusOrder10) {
|
|
/**
|
|
* @brief
|
|
* 由于是共用体,所以均给0F赋值即可
|
|
*/
|
|
rxparsed->d.O0F.startbit = rxraw[2] * 256 + rxraw[3];
|
|
rxparsed->d.O0F.numbit = rxraw[4] * 256 + rxraw[5];
|
|
rxparsed->d.O0F.bytenum = rxraw[6];
|
|
rxparsed->d.O0F.bit = &rxraw[7];
|
|
} else {
|
|
/**
|
|
* @brief Not support now
|
|
*/
|
|
}
|
|
}
|
|
|
|
#define UINT16ToUINT8(u16d, u8addbegin) \
|
|
{ \
|
|
(u8addbegin)[0] = u16d >> 8; \
|
|
(u8addbegin)[1] = (uint8_t)u16d; \
|
|
}
|
|
|
|
void ModbusCreateTx_setReg(uint8_t* txbuffer, uint8_t length, uint16_t off, uint16_t regdata) {
|
|
if (3 + off * 2 > length - 2) {
|
|
return;
|
|
}
|
|
txbuffer[3 + off * 2] = regdata >> 8;
|
|
txbuffer[3 + off * 2 + 1] = (uint8_t)regdata;
|
|
}
|
|
|
|
void ModbusCreateTxData(uint8_t* txbuffer, uint8_t length, uint16_t* sendlength, ModbusSlaveData_t* txdata) {
|
|
/**
|
|
* @brief TODO:添加txbuffer长度计算
|
|
*/
|
|
if (length < 4) return;
|
|
txbuffer[0] = txdata->deviceId;
|
|
txbuffer[1] = (uint8_t)txdata->functionCode;
|
|
*sendlength = 0;
|
|
volatile uint16_t _sendlength = 0;
|
|
volatile uint16_t i = 0;
|
|
|
|
if (txdata->functionCode == ModbusOrder01 || txdata->functionCode == ModbusOrder02 || txdata->functionCode == ModbusOrder03 || txdata->functionCode == ModbusOrder04) {
|
|
/**
|
|
* @brief 01,02 指令操作bit
|
|
*/
|
|
|
|
// 读取多个输出状态
|
|
// sendLen =
|
|
// add(1byte)+functionCode(1byte)+addNum(1)+crc(2) = 5+numbyte
|
|
volatile uint16_t numbyte = txdata->d.O01.bytenum;
|
|
_sendlength = 5 + numbyte;
|
|
if (length < _sendlength) return;
|
|
txbuffer[2] = txdata->d.O01.bytenum;
|
|
if (txdata->d.O01.byte_table != nullptr) {
|
|
for (i = 0; i < numbyte; i++) {
|
|
txbuffer[3 + i] = txdata->d.O01.byte_table[i];
|
|
}
|
|
}
|
|
} else if (txdata->functionCode == ModbusOrder0F || txdata->functionCode == ModbusOrder10) {
|
|
// 写入多个输出
|
|
// sendLen = add(1byte)+functionCode(1byte)+startAdd(2)+addNum(2)+crc(2) = 8
|
|
_sendlength = 8;
|
|
if (length < _sendlength) return;
|
|
|
|
UINT16ToUINT8(txdata->d.O0F.startbit, &txbuffer[2]);
|
|
UINT16ToUINT8(txdata->d.O0F.bitnum, &txbuffer[4]);
|
|
} else {
|
|
/**
|
|
* @brief Not support now
|
|
*/
|
|
}
|
|
// calculate crc
|
|
if (_sendlength > 2) {
|
|
modbus_pack_crc_to_packet(txbuffer, _sendlength);
|
|
}
|
|
*sendlength = _sendlength;
|
|
}
|
|
|
|
void ModbusCreateExceptionData(uint8_t* txbuffer, uint8_t length, uint16_t* sendlength, uint8_t deviceid, uint8_t functioncode, ModbusStatus status) {
|
|
/**
|
|
* @brief TODO:添加txbuffer长度计算
|
|
*/
|
|
volatile uint16_t _sendlength = 0;
|
|
volatile uint16_t i = 0;
|
|
|
|
if (length < 4) return;
|
|
txbuffer[0] = deviceid;
|
|
txbuffer[1] = functioncode | 0x80;
|
|
txbuffer[2] = (uint8_t)status;
|
|
*sendlength = 0;
|
|
// sendLen = add(1byte)+functionCode(1byte)+exception(1)+crc(2) = 4
|
|
_sendlength = 4;
|
|
modbus_pack_crc_to_packet(txbuffer, _sendlength);
|
|
*sendlength = _sendlength;
|
|
return;
|
|
}
|
|
#if 0
|
|
void modbus_processer_try_process_data(void) {
|
|
/**
|
|
* @brief
|
|
* 根据modbus协议,当超过3.5个字符时间后依然没有收到数据
|
|
*/
|
|
// bool receive_one_packet = false; // 因为keil报警告才注释
|
|
if (s_modbus_uart_rx_off != 0) {
|
|
uint16_t modbus_uart_rx_off_before = s_modbus_uart_rx_off;
|
|
|
|
g_processer->port_delay_us(g_processer->modbus_baundrate_one_packet_delay_us);
|
|
|
|
g_processer->port_enter_critical();
|
|
if (s_modbus_uart_rx_off == modbus_uart_rx_off_before) {
|
|
s_modbus_uart_rx_buf_is_processing = true;
|
|
}
|
|
g_processer->port_exit_critical();
|
|
|
|
if (s_modbus_uart_rx_buf_is_processing) {
|
|
modbus_processer_process_data(g_processer->modbus_processer_rx_buf, s_modbus_uart_rx_off);
|
|
g_processer->port_enter_critical();
|
|
s_modbus_uart_rx_off = 0;
|
|
s_modbus_uart_rx_buf_is_processing = false;
|
|
g_processer->port_exit_critical();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************************************************************
|
|
* ==================================================modbus消息处理=================================================== *
|
|
***********************************************************************************************************************/
|
|
void modbus_processer_process_data(uint8_t* rx, uint16_t rxlen) {
|
|
/**
|
|
* @brief modbus接收完成以后在这里进行处理数据
|
|
*
|
|
*/
|
|
// 如果不是广播信息或者不是当前设备的信息,丢弃
|
|
if (rx[0] != 0 && rx[0] != g_processer->modbus_device_id) {
|
|
return;
|
|
}
|
|
// CRC校验失败
|
|
if (!modbus_checkcrc16(rx, rxlen)) {
|
|
return;
|
|
}
|
|
// if(functioncode)
|
|
static ModbusMasterData_t rxorder;
|
|
static ModbusSlaveData_t txorder;
|
|
// 将接受到的数据进行组包
|
|
ModbusProcessRxData(rx, rxlen, &rxorder);
|
|
// static uint16_t txsendlen = 0; // 因为keil报警告才注释
|
|
txorder.deviceId = g_processer->modbus_device_id;
|
|
// 功能码
|
|
txorder.functionCode = rxorder.functionCode;
|
|
|
|
modbus_processer_context_t context = {0};
|
|
context.tx = &txorder;
|
|
context.rx = &rxorder;
|
|
g_processer->process_rx(&context);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* ======================================================Extern======================================================= *
|
|
***********************************************************************************************************************/
|
|
|
|
ModbusFunctionCode modbus_get_function_code(modbus_processer_context_t* context) { //
|
|
return context->tx->functionCode;
|
|
}
|
|
void modbus_set_tx_reg_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regdata) {
|
|
uint16_t off = regoff - context->rx->d.O03.startreg;
|
|
ModbusCreateTx_setReg(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, off, //
|
|
regdata);
|
|
}
|
|
void modbus_set_tx_regs_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t* regdata, int reglen) {
|
|
for (int i = 0; i < reglen; i++) {
|
|
modbus_set_tx_reg_03(context, regoff + i, regdata[i]);
|
|
}
|
|
}
|
|
|
|
uint16_t modbus_get_reg_10(modbus_processer_context_t* context, uint16_t regoff) {
|
|
uint16_t off = regoff - context->rx->d.O10.startreg;
|
|
uint8_t* data = context->rx->d.O10.reg;
|
|
if ((off + 1) * 2 <= context->rx->d.O10.bytenum) {
|
|
uint16_t u16 = GET_UINT16(&data[off * 2]);
|
|
return u16;
|
|
} else {
|
|
uint16_t u16 = data[off * 2];
|
|
return u16;
|
|
}
|
|
}
|
|
uint8_t* modbus_get_buf_10(modbus_processer_context_t* context, uint16_t regoff) {
|
|
uint16_t off = regoff - context->rx->d.O10.startreg;
|
|
uint8_t* data = context->rx->d.O10.reg;
|
|
return &data[off * 2];
|
|
}
|
|
bool modbus_if_register_exists_03(modbus_processer_context_t* context, uint16_t regoff) {
|
|
uint16_t startreg = context->rx->d.O03.startreg;
|
|
uint16_t endreg = context->rx->d.O03.startreg + context->rx->d.O03.numreg;
|
|
return regoff >= startreg && regoff < endreg;
|
|
}
|
|
bool modbus_if_registers_exists_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regnum) { return (modbus_if_register_exists_03(context, regoff) && modbus_if_register_exists_03(context, regoff + regnum - 1)); }
|
|
|
|
bool modbus_if_register_exists_10(modbus_processer_context_t* context, uint16_t regoff) {
|
|
uint16_t startreg = context->rx->d.O10.startreg;
|
|
uint16_t endreg = context->rx->d.O10.startreg + context->rx->d.O10.numreg;
|
|
return regoff >= startreg && regoff < endreg;
|
|
}
|
|
void modbus_send_03(modbus_processer_context_t* context, ModbusStatus modbus_status) {
|
|
uint16_t sendlegth = 0;
|
|
if (modbus_status == Modbus_OK) {
|
|
/**
|
|
* @brief 正常
|
|
*/
|
|
context->tx->functionCode = context->rx->functionCode;
|
|
context->tx->deviceId = g_processer->modbus_device_id;
|
|
context->tx->d.O03.bytenum = context->rx->d.O03.numreg * 2;
|
|
context->tx->d.O03.reg = nullptr;
|
|
// 组成响应包
|
|
ModbusCreateTxData(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, &sendlegth, context->tx);
|
|
// 包组成以后发送给服务端
|
|
g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth);
|
|
} else {
|
|
// LOGD("error");
|
|
/**
|
|
* @brief 异常
|
|
*/
|
|
// 处理异常情况
|
|
ModbusCreateExceptionData(g_processer->modbus_processer_tx_buf, //
|
|
g_processer->modbus_processer_tx_buf_size, //
|
|
&sendlegth, //
|
|
g_processer->modbus_device_id, //
|
|
context->rx->functionCode, //
|
|
modbus_status);
|
|
// 组包完成发送应答
|
|
g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth);
|
|
}
|
|
}
|
|
void modbus_send_10(modbus_processer_context_t* context, ModbusStatus modbus_status) {
|
|
uint16_t sendlegth = 0;
|
|
if (modbus_status == Modbus_OK) {
|
|
context->tx->functionCode = context->rx->functionCode;
|
|
context->tx->deviceId = g_processer->modbus_device_id;
|
|
context->tx->d.O10.regnum = context->rx->d.O10.numreg;
|
|
context->tx->d.O10.startreg = context->rx->d.O10.startreg;
|
|
// 构造回执,并发送
|
|
ModbusCreateTxData(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, &sendlegth, context->tx);
|
|
g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth);
|
|
} else {
|
|
// 构造异常包并发送
|
|
ModbusCreateExceptionData(g_processer->modbus_processer_tx_buf, //
|
|
g_processer->modbus_processer_tx_buf_size, //
|
|
&sendlegth, //
|
|
g_processer->modbus_device_id, //
|
|
context->rx->functionCode, //
|
|
modbus_status);
|
|
g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth);
|
|
}
|
|
}
|