ZNY_Pakistan/Anjiehui7_ZNY/User/modbus_slave.c

382 lines
9.5 KiB
C
Raw Permalink Normal View History

2025-04-03 15:24:54 +08:00
#include "includes.h"
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void Modbus_Task(uint8_t c);
// modbusͨѶ<CDA8><D1B6><EFBFBD><EFBFBD>
#pragma pack(push, 1)
typedef struct
{
uint8_t id; // ͨ<>ŵ<EFBFBD>ַ
uint8_t cmd; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint16_t reg; // <20>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ
union
{
uint16_t cnt; // <20><>ȡ<EFBFBD><C8A1><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint16_t data; // д<><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
uint16_t crc;
} modbus_request_t;
#pragma pack(pop)
// modbus rtu <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
#define MODBUS_1ST_REG (30001) // <20><>1<EFBFBD><31><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ַ
#define MODBUS_LAST_REG (30016) // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ַ
#define MODBUS_ADR_REG (40001) // ͨ<>ŵ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ַ
// modbus rtu<74><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define MODBUS_ERR_ILF (0x01) // <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define MODBUS_ERR_ILA (0x02) // <20><>ЧͨѶ<CDA8><D1B6>ַ
#define MODBUS_ERR_ILD (0x03) // <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>ֵ
#define MODBUS_ERR_FID (0x04) // ִ<><D6B4>ʧ<EFBFBD><CAA7>
#define MODBUS_ERR_ACK (0x05) // ACK<43><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽ<EFBFBD><D1BD>ܲ<EFBFBD><DCB2>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>У<EFBFBD>
#define MODBUS_ERR_BUSY (0x06) // <20>豸æ<E8B1B8><C3A6><EFBFBD>ܾ<EFBFBD>
#define MODBUS_ERR_NAK (0x07) // NAK<41><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ִ<EFBFBD>У<EFBFBD>
// modbus rtu <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
uint8_t MODBUS_RTU_Buf[(MODBUS_LAST_REG - MODBUS_1ST_REG + 1) * 2];
void Slave_IRQHandler(USART_Handle *huart)
{
uint8_t u8DTU = (uint8_t) huart->Instance->RDR;
/* Handle received data */
Modbus_Task(u8DTU);
}
void Slave_Init()
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
PA15 ------> USART3_DE
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_10|LL_GPIO_PIN_11;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/*---------------------------------------------------------------------------------------------------------*/
/* RS485 Transmit Control (Address Byte: Parity Bit =1 , Data Byte:Parity Bit =0) */
/*---------------------------------------------------------------------------------------------------------*/
static void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
{
/* Set UART parity as SPACE and skip baud rate setting */
// UART_SetLine_Config(UART1, 0, UART_WORD_LEN_8, UART_PARITY_SPACE, UART_STOP_BIT_1);
/* Send data */
UART_Transmit_IT(&huart3, pu8TxBuf, u32WriteBytes);
}
void Slave_Open()
{
LL_USART_InitTypeDef USART_InitStruct = {0};
huart3.RxISR = Slave_IRQHandler;
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);
/* USART3 interrupt Init */
NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
USART_InitStruct.BaudRate = 9600;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
LL_USART_Init(USART3, &USART_InitStruct);
LL_USART_EnableDEMode(USART3);
LL_USART_SetDESignalPolarity(USART3, LL_USART_DE_POLARITY_HIGH);
LL_USART_SetDEAssertionTime(USART3, 0);
LL_USART_SetDEDeassertionTime(USART3, 0);
LL_USART_ConfigAsyncMode(USART3);
SET_BIT(USART3->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
LL_USART_Enable(USART3);
}
uint32_t Fill_MODBUS_RTU_Buf()
{
uint8_t len = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
uint16_t val = 0;
uint32_t val32 = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD>
if(dcBuff.sampleData.volumeTotal == 0)
return 0;
// <20><><EFBFBD><EFBFBD>״̬
if(dcBuff.sampleData.staPress.notConnect)
val |= (1 << 0);
if(dcBuff.sampleData.staExtTempr[0].notConnect)
val |= (1 << 2);
if(dcBuff.sampleData.staDPress.notConnect)
val |= (1 << 4);
// Һλ<D2BA><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)
val |= (1 << 6);
// <20><><EFBFBD><EFBFBD>ֵ״̬
if(dcBuff.sampleData.staPress.underFlow)
val |= (1 << 8);
else if(dcBuff.sampleData.staPress.overFlow)
val |= (2 << 8);
if(dcBuff.sampleData.staExtTempr[0].underFlow)
val |= (1 << 10);
else if(dcBuff.sampleData.staExtTempr[0].overFlow)
val |= (2 << 10);
if(dcBuff.sampleData.staDPress.underFlow)
val |= (1 << 12);
else if(dcBuff.sampleData.staDPress.overFlow)
val |= (2 << 12);
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><>ѹ
val = (uint16_t) dcBuff.sampleData.diff;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20>ݻ<EFBFBD><DDBB>ٷֱ<D9B7>
val = (uint16_t) dcBuff.sampleData.volumePct;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><><EFBFBD><EFBFBD>
val32 = dcBuff.sampleData.volume;
val32 = htonl(val32);
memmove(MODBUS_RTU_Buf + len, &val32, 4);
len += 4;
// <20><><EFBFBD><EFBFBD>
val32 = dcBuff.sampleData.weight;
val32 = htonl(val32);
memmove(MODBUS_RTU_Buf + len, &val32, 4);
len += 4;
// <20>߶ȣ<DFB6>mmWC <20><> mm
if(!dcBuff.configDisplay.op_USE_CAPACITY_SENSOR && !dcBuff.configDisplay.op_USE_HEIGHT_LEVEL && !dcBuff.configDisplay.op_USE_PCT_LEVEL)
val = (uint16_t) KPa2mmH2O(dcBuff.sampleData.diff);
else
val = (uint16_t) dcBuff.sampleData.height;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// ѹ<><D1B9>
val = (uint16_t) dcBuff.sampleData.pressure;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><EFBFBD>: <20>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD>
memmove(&val, &dcBuff.sampleData.extTempr[0], 2);
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><><EFBFBD><EFBFBD>
val = (uint16_t) dcBuff.configBottle.source;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><><EFBFBD><EFBFBD>Ч<EFBFBD>ݻ<EFBFBD>
val32 = dcBuff.sampleData.volumeTotal;
val32 = htonl(val32);
memmove(MODBUS_RTU_Buf + len, &val32, 4);
len += 4;
// <20><><EFBFBD>ռ<EFBFBD>״̬
val = 0;
if(dcBuff.sampleData.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT)
val |= 1;
else
{
if(dcBuff.sampleData.vacuum[0].staVacuum == VACUUM_STATUS_FAULT)
val |= (3 << 2);
else if(dcBuff.sampleData.vacuum[0].vacuum > 99.99999999)
val |= (2 << 2);
else if(dcBuff.sampleData.vacuum[0].vacuum <= 0.00999999)
val |= (1 << 2);
}
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><><EFBFBD>ն<EFBFBD>
val = dcBuff.sampleData.vacuum[0].vacuum * 100;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
// <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>
val = (int16_t) dcBuff.sampleData.vacuum[0].tempr;
val = htons(val);
memmove(MODBUS_RTU_Buf + len, &val, 2);
len += 2;
return 1;
}
// <20><><EFBFBD><EFBFBD>modbus rtu<74><75><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD>CRC<52>İ<EFBFBD><C4B0><EFBFBD>
void MODBUS_RTU_CMD(modbus_request_t *req)
{
static uint8_t BUFF[(MODBUS_LAST_REG - MODBUS_1ST_REG + 1) * 2 + 6]; // <20><>Ӧ<EFBFBD><D3A6>
uint8_t err = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint8_t len = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
uint16_t id; // ͨ<>ŵ<EFBFBD>ַ
uint16_t reg; // <20><><EFBFBD>ݵ<EFBFBD>ַ
uint16_t cnt; // <20><><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD>
uint16_t crc;
// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD>ŵ<EFBFBD>ַ
if(req->id != dcBuff.configBottle.addr && req->id != 0)
return;
// <20><><EFBFBD>շ<EFBFBD><D5B7><EFBFBD>֡
memset(BUFF, 0, sizeof(BUFF));
BUFF[len++] = dcBuff.configBottle.addr; // <20>ӻ<EFBFBD><D3BB><EFBFBD>ַ
BUFF[len++] = req->cmd; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
reg = ntohs(req->reg); // <20><><EFBFBD>ݼĴ<DDBC><C4B4><EFBFBD>
if(req->cmd == 0x03 || req->cmd == 0x06)
reg += 40001;
else if(req->cmd == 0x04)
reg += 30001;
else
err = MODBUS_ERR_ILF; // <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(err == 0)
{
if(req->cmd == 0x03) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
cnt = ntohs(req->cnt); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(reg != MODBUS_ADR_REG || cnt != 1)
err = MODBUS_ERR_NAK; // <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ִ<EFBFBD><D6B4>
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>ͨѶ<CDA8><D1B6>ַˢ<D6B7>»<EFBFBD><C2BB><EFBFBD>
id = htons(dcBuff.configBottle.addr);
BUFF[len++] = 2; // <20><><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
memmove(BUFF + len, (uint8_t *) &id, 2);
len += 2;
}
}
else if(req->cmd == 0x06) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if(reg != MODBUS_ADR_REG)
err = MODBUS_ERR_NAK; // <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ִ<EFBFBD><D6B4>
else
{
id = ntohs(req->data);
if(id < 1 || id > 247)
err = MODBUS_ERR_ILD; // <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>ֵ
else
{
// <20><><EFBFBD>õ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
dcBuff.configBottle.addr = id;
Config_SaveConfig();
BUFF[0] = id; // <20>µ<EFBFBD>ַ
memmove(BUFF + len, &req->reg, 4); // <20><><EFBFBD>ݵ<EFBFBD>ַ<EFBFBD><D6B7>ͨѶ<CDA8><D1B6>ַ
len += 4;
}
}
}
else if(req->cmd == 0x04) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
cnt = ntohs(req->cnt); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(reg < MODBUS_1ST_REG || reg > MODBUS_LAST_REG || cnt < 1 || reg + (cnt - 1) > MODBUS_LAST_REG)
err = MODBUS_ERR_NAK; // <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ִ<EFBFBD><D6B4>
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD>µIJɼ<C4B2><C9BC><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD>»<EFBFBD><C2BB><EFBFBD>
if(!Fill_MODBUS_RTU_Buf())
return;
BUFF[len++] = cnt * 2; // <20><><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
memmove(BUFF + len, MODBUS_RTU_Buf + (reg - MODBUS_1ST_REG) * 2, cnt * 2);
len += cnt * 2;
}
}
}
if(err != 0)
{
BUFF[1] |= 0x80; // <20><><EFBFBD><EFBFBD>ָʾ
BUFF[len++] = err; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD>CRC
crc = MODBUS_RTU_CRC16(BUFF, len);
crc = htons(crc);
memmove(BUFF + len, &crc, 2);
len += 2;
if(req->id != 0)
{
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>
RS485_SendDataByte(BUFF, len);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void Modbus_Task(uint8_t c)
{
static uint8_t BUFF[sizeof(modbus_request_t)] = {0};
static uint8_t len = 0;
// ȡ<><C8A1><EFBFBD><EFBFBD>
BUFF[len++] = c;
// <20><>֤<EFBFBD><D6A4><EFBFBD>Ⱥ<EFBFBD>CRCֵ
if(len == sizeof(modbus_request_t))
{
if(MODBUS_RTU_CRC16(BUFF, sizeof(modbus_request_t)) == 0)
{
MODBUS_RTU_CMD((modbus_request_t *) BUFF);
len = 0;
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>
memmove(BUFF, BUFF + 1, --len);
}
}
}