Browse Source

modbus协议初始化

master
zwsd 3 years ago
parent
commit
cc9da3c879
  1. 102
      modbus_processer.c
  2. 44
      modbus_processer.h
  3. 75
      zmodbus_common.c
  4. 122
      zmodbus_common.h
  5. 84
      zmodbus_slave.c
  6. 13
      zmodbus_slave.h

102
modbus_processer.c

@ -0,0 +1,102 @@
#include "modbus_processer.h"
#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_init(modbus_processer_t* processer) { g_processer = processer; }
void modbus_processer_push_data(uint8_t rxdata) {
if (!s_modbus_uart_rx_buf_is_processing) {
if (s_modbus_uart_rx_off < g_processer->modbus_processer_rx_buf_size) {
g_processer->modbus_processer_rx_buf[s_modbus_uart_rx_off] = rxdata;
s_modbus_uart_rx_off++;
}
}
}
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);
}
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;
}
}
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_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) {
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);
}
}
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);
}
}

44
modbus_processer.h

@ -0,0 +1,44 @@
#pragma once
#include <stdint.h>
#include "zmodbus_common.h"
#include "zmodbus_slave.h"
#include "zport.h"
typedef struct {
ModbusMasterData_t* rx;
ModbusSlaveData_t* tx;
} modbus_processer_context_t;
typedef struct modbus_processer {
uint8_t modbus_device_id; // default 0x01;
uint8_t* modbus_processer_rx_buf;
uint8_t modbus_processer_rx_buf_size; //
uint8_t* modbus_processer_tx_buf;
uint8_t modbus_processer_tx_buf_size; //
/*************************************/
int modbus_baundrate_one_packet_delay_us;
void (*port_enter_critical)();
void (*port_exit_critical)();
void (*port_delay_us)(uint32_t us);
void (*tx)(uint8_t* rx, uint16_t len);
//
void (*process_rx)(modbus_processer_context_t* context);
} modbus_processer_t;
void modbus_processer_init(modbus_processer_t* processer);
void modbus_processer_push_data(uint8_t rxdata);
ModbusFunctionCode modbus_get_function_code(modbus_processer_context_t* context);
void modbus_set_tx_reg_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regdata);
uint16_t modbus_get_reg_10(modbus_processer_context_t* context, uint16_t regoff);
bool modbus_if_register_exists_03(modbus_processer_context_t* context, uint16_t regoff);
bool modbus_if_register_exists_10(modbus_processer_context_t* context, uint16_t regoff);
void modbus_send_03(modbus_processer_context_t* context, ModbusStatus modbus_status);
void modbus_send_10(modbus_processer_context_t* context, ModbusStatus modbus_status);

75
zmodbus_common.c

@ -0,0 +1,75 @@
#include "zmodbus_common.h"
static const uint8_t auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40};
// CRC低位字节值表
static const uint8_t auchCRCLo[] = { // CRC_16低8位数据区
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40};
/*函数功能:CRC校验码生成
puchMsgg是要进行CRC校验的消息usDataLen是消息中字节数
CRC校验码
GenerateCRC16CheckCode查表计算函数*/
uint16_t ZGenerateCRC16CheckCode(uint8_t *puckMsg, uint8_t usDataLen) {
volatile uint8_t uchCRCHi = 0xFF; //CRC字节初始化
volatile uint8_t uchCRCLo = 0xFF; //CRC
volatile uint32_t uIndex; // CRC循环中的索引
//
while (usDataLen--) {
//CRC
uIndex = uchCRCLo ^ *puckMsg++;
uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex];
uchCRCHi = auchCRCLo[uIndex];
}
//
return (uchCRCLo << 8 | uchCRCHi);
}
void ZGenerateCRC16CheckCodeToPacket(uint8_t *puckMsg, uint8_t packetlen) {
uint16_t crc = ZGenerateCRC16CheckCode(puckMsg, packetlen - 2);
puckMsg[packetlen - 2] = crc >> 8;
puckMsg[packetlen - 1] = crc;
}

122
zmodbus_common.h

@ -0,0 +1,122 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/*定义Modbus的操作功能码,支持01、02、03、04、05、06、15、16功能码*/
typedef enum {
// ReadCoilStatus 线
ModbusOrder01 = 0x01,
// ReadInputStatus
ModbusOrder02 = 0x02,
// ReadHoldingRegister
ModbusOrder03 = 0x03,
// ReadInputRegister
ModbusOrder04 = 0x04,
// WriteSingleCoil 线
ModbusOrder05 = 0x05,
// WriteSingleRegister
ModbusOrder06 = 0x06,
// WriteMultipleCoil 线
ModbusOrder0F = 0x0F,
// WriteMultipleRegister
ModbusOrder10 = 0x10,
// ReadFileRecord
ModbusOrder14 = 0x14,
// WriteFileRecord
ModbusOrder15 = 0x15,
// MaskWriteRegister
ModbusOrder16 = 0x16,
// ReadWriteMultiRegister
ModbusOrder17 = 0x17,
// ReadDeviceID读设备识别码
ModbusOrder2B = 0x2B,
} ModbusFunctionCode;
/*定义接收到指令检测错误时的错误码*/
typedef enum {
Modbus_OK = 0x00,
InvalidFunctionCode = 0x01, //
IllegalDataAddress = 0x02, //
IllegalDataValues = 0x03, //
SlaveFailure = 0x04, //
Acknowledgement = 0x05, //
SlaveDeviceBusy = 0x06, //
MemoryParityError = 0x08, //
GatewayDisabled = 0x0A, //
GatewayResponseFailed = 0x0B //
} ModbusStatus;
typedef struct {
uint8_t deviceid;
ModbusFunctionCode functionCode;
union {
/**********read************/
struct {
uint16_t startbit; // bit
uint16_t numbit; // bit
} O01; // ReadCoilStatus
struct {
uint16_t startbit; // bit
uint16_t numbit; // bit
} O02; // ReadInputStatus
struct {
uint16_t startreg; // byte
uint16_t numreg; // reg(reg==16bit)
} O03; // ReadInputStatus
struct {
uint16_t startreg; // byte
uint16_t numreg; // reg(reg==16bit)
} O04; // ReadInputStatus
/**********write************/
struct {
uint16_t startbit; // bit
uint16_t numbit; // bit
uint8_t bytenum;
uint8_t *bit;
} O0F; // WriteMultipleCoil
struct {
uint16_t startreg; // byte
uint16_t numreg; // byte
uint8_t bytenum; // numreg*2
uint8_t *reg;
} O10; // WriteMultipleCoil
} d;
} ModbusMasterData_t;
typedef struct {
ModbusFunctionCode functionCode;
uint8_t deviceId;
union {
/**********read_receipt************/
struct {
uint8_t bytenum; // bit
uint8_t *byte_table;
} O01; // ReadCoilStatus
struct {
uint8_t bytenum; // byte_table
uint8_t *byte_table;
} O02; // ReadInputStatus
struct {
uint8_t bytenum; // byte
uint8_t *reg;
} O03; // ReadInputStatus
struct {
uint8_t bytenum; // byte
uint8_t *reg;
} O04; // ReadInputStatus
/**********write_receipt************/
struct {
uint16_t startbit;
uint16_t bitnum; // bit
} O0F; // WriteMultipleCoil-->01
struct {
uint16_t startreg;
uint16_t regnum; // byte
} O10; // --->03
} d;
} ModbusSlaveData_t;
void ZGenerateCRC16CheckCodeToPacket(uint8_t *puckMsg, uint8_t packetlen);
uint16_t ZGenerateCRC16CheckCode(uint8_t *puckMsg, uint8_t usDataLen);

84
zmodbus_slave.c

@ -0,0 +1,84 @@
#include "zmodbus_slave.h"
#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 != NULL) {
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) {
ZGenerateCRC16CheckCodeToPacket(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;
ZGenerateCRC16CheckCodeToPacket(txbuffer, _sendlength);
*sendlength = _sendlength;
return;
}

13
zmodbus_slave.h

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "zmodbus_common.h"
void ModbusCreateTx_setReg(uint8_t *txbuffer, uint8_t length, uint16_t off, uint16_t regdata);
void ModbusCreateTxData(uint8_t *txbuffer, uint8_t length, uint16_t *sendlength, ModbusSlaveData_t *txdata);
void ModbusCreateExceptionData(uint8_t *txbuffer, uint8_t length, uint16_t *sendlength, uint8_t deviceid, uint8_t functioncode, ModbusStatus status);
#ifdef __cplusplus
}
#endif
Loading…
Cancel
Save