injectorCTL/protocol.c
CSSC-WORK\murmur a71606de2e update function
2024-12-11 10:32:35 +08:00

509 lines
14 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 "protocol.h"
#include <string.h>
static DeviceStatus deviceStatus = {0};
// CRC16 查表法实现
static const uint16_t crcTable[] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
uint16_t CalculateCRC16(uint8_t *data, uint16_t length) {
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < length; i++) {
uint8_t index = (crc ^ data[i]) & 0xFF;
crc = (crc >> 8) ^ crcTable[index];
}
return crc;
}
// 更新下挂设备状态
void updateDeviceStatus(DeviceStatus_t status) {
deviceStatus.deviceStatus = status;
}
// 更新三通阀状态
void updateValveStatus(uint8_t index, ValveAngle_t angle) {
if (index == 1) {
deviceStatus.valves.angle1 = angle;
} else if (index == 2) {
deviceStatus.valves.angle2 = angle;
}
}
// 更新泵状态
void updatePumpStatus(uint8_t index, PumpStatus_t status) {
if (index == 1) {
deviceStatus.pumps.status1 = status;
} else if (index == 2) {
deviceStatus.pumps.status2 = status;
}
}
// 更新泵速度状态
void updatePumpSpeedStatus(uint8_t index, uint8_t speed) {
if (index == 1) {
deviceStatus.pumps.speed1 = speed;
} else if (index == 2) {
deviceStatus.pumps.speed2 = speed;
}
}
// 更新气泡传感器读数
void updateBubbleSensor(BubbleStatus_t value) {
deviceStatus.bubbleStatus = value;
}
// 更新急停状态
void updateEmergencyStop(EstopStatus_t status) {
deviceStatus.stopStatus = status;
}
// 更新错误码
void updateErrorCode(ErrorCode_t errorCode) {
deviceStatus.errorCode = errorCode;
}
// 更新初始化状态
void updateInitStatus(InitStatus_t status) {
deviceStatus.initStatus = status;
}
// 初始化设备状态
void InitDeviceStatus() {
// 更新设备状态
updateDeviceStatus(DEVICE_ONLINE);
updateValveStatus(1, 120);
updateValveStatus(2, 210);
updatePumpStatus(1, PUMP_CLOCKWISE);
updatePumpStatus(2, PUMP_ANTICLOCKWISE);
updatePumpSpeedStatus(1, 100);
updatePumpSpeedStatus(2, 100);
updateBubbleSensor(BUBBLE_DETECTED);
updateEmergencyStop(ESTOP_NORMAL);
updateInitStatus(INIT_SUCCESS);
}
//modBUS RTU 写命令
void writeCMD(uint8_t *txBuf, uint16_t *txLen) {
}
// 判断系统大端序还是小端序
static uint8_t IsBigEndian() {
uint32_t num = 0x12345678;
return ((*(uint8_t*)&num) == 0x12);
}
// 将数据按大端序填充
static void FillBigEndian32(uint8_t *data, uint32_t value) {
if(!IsBigEndian()) {
for(uint16_t i = 0; i < 4; i++) {
data[i] = (value >> ((4 - i - 1) * 8)) & 0xFF;
}
}
else {
for(uint16_t i = 0; i < 4; i++) {
data[i] = (value >> (i * 8)) & 0xFF;
}
}
}
static void FillBigEndian16(uint8_t *data, uint16_t value) {
if(!IsBigEndian()) {
for(uint16_t i = 0; i < 2; i++) {
data[i] = (value >> ((2 - i - 1) * 8)) & 0xFF;
}
}
else {
for(uint16_t i = 0; i < 2; i++) {
data[i] = (value >> (i * 8)) & 0xFF;
}
}
}
// 泵加速、减速处理
static uint8_t WritePumpAccDec(uint8_t index, uint8_t acc, uint8_t dec) {
// 实现泵加速、减速逻辑
RTU_Frame frame;
frame.data_cnt = 2;
uint8_t len = sizeof(RTU_Frame)+frame.data_cnt*sizeof(uint8_t);
frame.device_id = 1;
frame.func = RTU_PUMP_FUNC_WRITE_REG;
FillBigEndian16(&frame.reg_addr[0], RTU_PUMP_CMD_AC);
FillBigEndian16(&frame.reg_cnt[0], 2);
FillBigEndian32(&frame.data[0], acc);
FillBigEndian32(&frame.data[4], dec);
uint16_t crc = CalculateCRC16(&frame, len - sizeof(frame.crc));
// 大端序填充
FillBigEndian16(&frame.crc[0], crc);
writeCMD((uint8_t*)&frame, len);
}
// 泵速度设置处理
static uint8_t WritePumpSpeed(uint8_t index, uint8_t speed) {
// 实现泵速度设置逻辑
RTU_Frame frame;
frame.data_cnt = 2;
uint8_t len = sizeof(RTU_Frame)+frame.data_cnt*sizeof(uint8_t);
frame.device_id = 1;
frame.func = RTU_PUMP_FUNC_WRITE_REG;
FillBigEndian16(&frame.reg_addr[0], RTU_PUMP_CMD_VE);
FillBigEndian16(&frame.reg_cnt[0], 2);
FillBigEndian32(&frame.data[0], speed);
uint16_t crc = CalculateCRC16(&frame, len - sizeof(frame.crc));
// 大端序填充
FillBigEndian16(&frame.crc[0], crc);
writeCMD((uint8_t*)&frame, len);
}
// 泵步进设置处理
static uint8_t WritePumpStep(uint8_t index, int32_t step) {
// 实现泵步进设置逻辑
RTU_Frame frame;
frame.data_cnt = 2;
uint8_t len = sizeof(RTU_Frame)+frame.data_cnt*sizeof(uint8_t);
frame.device_id = 1;
frame.func = RTU_PUMP_FUNC_WRITE_REG;
FillBigEndian16(&frame.reg_addr[0], RTU_PUMP_CMD_DI);
FillBigEndian16(&frame.reg_cnt[0], 2);
// step为int32_t正负表示方向绝对值表示步数0表示停止
if(step != 0) {
FillBigEndian32(&frame.data[0], step);
}
else {
// 停止
}
uint16_t crc = CalculateCRC16(&frame, len - sizeof(frame.crc));
// 大端序填充
FillBigEndian16(&frame.crc[0], crc);
writeCMD((uint8_t*)&frame, len);
return 1;
}
// pump 读寄存器
uint16_t ReadPump1Reg(uint8_t index, uint16_t reg) {
// 读取保存寄存器不能直接使用RTU_Frame因为无数据位
uint8_t data[8] = {0};
data[0] = index;
data[1] = RTU_PUMP_FUNC_READ_REG;
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], 1);
uint16_t crc = CalculateCRC16(data, 6);
// 大端序填充
FillBigEndian16(&data[6], crc);
writeCMD(data, 8);
}
// 获取泵状态
void ReadPumpStatus(uint8_t index) {
ReadPump1Reg(index, RTU_PUMP_CMD_SC);
}
// 获取泵告警信息
void ReadPumpAlarm(uint8_t index) {
ReadPump1Reg(index, RTU_PUMP_CMD_AL);
}
// 解码告警信息
void DecodePumpAlarmMsg(uint16_t reg4001) {
static AlarmCode_t alarmCode = {0};
// 与上次告警信息相同,则不更新,仅打印一次
if (alarmCode.all == reg4001)
{
return 0;
}
alarmCode.all = reg4001;
if(alarmCode.all == 0) {
//暂时屏蔽,避免刷屏
// printf("\r\n%s无报警信息\r\n", pumpName[index]);
return 0;
}
// 打印表格头部
printf("\r\n+--------+------------------+\r\n");
printf("| 告警位 | 告警信息 |\r\n");
printf("+--------+------------------+\r\n");
for(uint16_t i = 0; i < 16; i++) {
if(alarmCode.all & (1 << i)) {
printf("| %6d | %-14s |\r\n", i, alarmInfo[i]);
printf("+--------+------------------+\r\n");
}
}
return 1;
}
// 解码状态信息
void DecodePumpStatusMsg(uint16_t reg4002) {
static StatusCode_t statusCode = {0};
// 与上次状态信息相同,则不更新,仅打印一次
if (statusCode.all == reg4002)
{
return 1;
}
statusCode.all = reg4002;
printf("\r\n+--------+------------------+\r\n");
printf("| 状态位 | 状态信息 |\r\n");
printf("+--------+------------------+\r\n");
for(uint16_t i = 0; i < 16; i++) {
if(statusCode.all & (1 << i)) {
printf("| %6d | %-14s |\r\n", i, statusInfo[i]);
printf("+--------+------------------+\r\n");
}
}
return 0;
}
// 定时1s更新设备状态
// 活度计通过网口获取
// 下挂设备通过485获取
void UpdatePumpStatus() {
// 更新设备状态
ReadPumpStatus(0);
ReadPumpStatus(1);
ReadPumpAlarm(0);
ReadPumpAlarm(1);
}
// 初始化处理
static uint8_t HandleInit(uint8_t *rxBuf, uint8_t *txBuf, uint16_t *txLen) {
// 实现初始化逻辑
InitDeviceStatus();
return 1;
}
// 状态查询处理
static uint8_t HandleStatusQuery(uint8_t *txBuf) {
// 填充并返回数据
memcpy(txBuf, &deviceStatus, sizeof(DeviceStatus));
return sizeof(DeviceStatus);
}
// 三通阀控制处理
static uint8_t HandleValveControl(uint8_t *Buff, uint8_t len) {
// 实现三通阀控制逻辑
if(len != 8) {
printf("三通阀控制错误\r\n");
return 0;
}
uint8_t index = Buff[0];
uint8_t direction = Buff[1];
uint16_t angle = (Buff[2]<<8) | Buff[3];
if(angle > 360) {
printf("三通阀控制错误\r\n");
return 1;
}
if (angle != VALVE_ANGLE_120 && angle != VALVE_ANGLE_210) {
printf("三通阀控制错误\r\n");
return 1;
}
// 具体实现
// 更新三通阀状态
updateValveStatus(index, angle);
return 0;
}
// 泵时长控制处理
static uint8_t HandlePumpTimeControl(uint8_t *Buff, uint8_t len) {
// 实现泵时长控制逻辑
// 暂未知控制方法,是直接设置泵运行时间,还是设置泵运行步数
return 1;
}
// 泵速度设置处理
static uint8_t HandlePumpSpeedControl(uint8_t *Buff, uint8_t len) {
// 实现泵速度设置逻辑
if(len != 4) {
printf("泵速度设置错误\r\n");
return 0;
}
uint8_t index = Buff[0];
uint8_t speed = Buff[1];
if (speed > 100) {
printf("泵速度设置错误\r\n");
return 0;
}
WritePumpSpeed(index, speed);
index = Buff[2];
speed = Buff[3];
if (speed > 100) {
printf("泵速度设置错误\r\n");
return 0;
}
WritePumpSpeed(index, speed);
return 1;
}
static uint8_t HandlePumpStepControl(uint8_t *Buff, uint8_t len) {
if(len != 10) {
printf("泵步进设置错误\r\n");
return 0;
}
uint8_t index = Buff[0];
int32_t step = (Buff[1]<<24) | (Buff[2]<<16) | (Buff[3]<<8) | Buff[4];
WritePumpStep(index, step);
index = Buff[5];
step = (Buff[6]<<24) | (Buff[7]<<16) | (Buff[8]<<8) | Buff[9];
WritePumpStep(index, step);
return 1;
}
// 软急停功能处理
static uint8_t HandleSoftStop(uint8_t *rxBuf, uint16_t rxLen) {
if(rxLen != 1) {
printf("软急停设置错误\r\n");
return 1;
}
// 实现软急停功能逻辑
if(rxBuf[0] == 0) {
// 正常状态
updateEmergencyStop(ESTOP_NORMAL);
}
else {
// 急停状态
updateEmergencyStop(ESTOP_PRESSED);
}
return 0;
}
CmdFrameError_t checkHostCmd(uint8_t *rxBuf, uint16_t rxLen) {
// 检查命令是否正确
if (memcmp(rxBuf, FRAME_HEADER, 4) != 0)
{
return CMD_FRAME_HEADER_ERROR;
}
if (memcmp(rxBuf + rxLen - 4, FRAME_TAIL, 4) != 0)
{
return CMD_FRAME_TAIL_ERROR;
}
uint16_t crc = CalculateCRC16(rxBuf+4, rxLen - 8);// 计算crc不包含帧头和帧尾
if (memcmp(rxBuf + rxLen - 4, &crc, 2) != 0)
{
return CMD_FRAME_CHECK_ERROR;
}
return CMD_FRAME_OK;
}
// 上位机命令处理函数采用的自定协议非modbus协议
// rxBuf: 接收到的数据
// rxLen: 接收到的数据长度
CmdFrameError_t ProcessHostCommand(uint8_t *rxBuf, uint16_t rxLen) {
CmdFrameError_t error = checkHostCmd(rxBuf, rxLen);
if (error != CMD_FRAME_OK)
{
return error;
}
uint16_t cmdCode = (rxBuf[sizeof(FRAME_HEADER)] << 8) | rxBuf[sizeof(FRAME_HEADER)+1];//提取命令码
uint8_t dataLen = rxBuf[sizeof(FRAME_HEADER)+2];//提取数据长度
uint8_t *data = &rxBuf[sizeof(FRAME_HEADER)+3];//提取数据
switch(cmdCode) {
case CMD_STATUS_QUERY:
error = HandleStatusQuery(data, dataLen);
break;
case CMD_VALVE_CTRL:
error = HandleValveControl(data, dataLen);
break;
case CMD_PUMP_RUN_TIME:
error = HandlePumpTimeControl(data, dataLen);
break;
case CMD_PUMP_RUN_SPEED:
error = HandlePumpSpeedControl(data, dataLen);
break;
case CMD_SOFT_STOP:
error = HandleSoftStop(data, dataLen);
break;
case CMD_PUMP_RUN_STEP:
error = HandlePumpStep(data, dataLen);
break;
case CMD_SYSTEM_INIT:
error = HandleInit(data, dataLen);
break;
default:
error = CMD_FRAME_CMD_ERROR;
break;
}
return error;
}