optical/NxFuncs/comm/mtcomm.c
2025-09-04 09:45:08 +08:00

461 lines
8.8 KiB
C
Raw Permalink 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.

#define _IN_MTCOMM_C
#include "mtcomm.h"
#include "crc8.h"
#include "trigger.h"
//------------------------------------------------------
//------------------------------------------------------
typedef struct
{
MtCommExFuncs commExFuncs; // 交换函数
MtCommPacket sendPacket; // 发送的数据包
MtCommPacket resvPacket; // 接收的数据包
// 传输过程控制
int transEnable; // 传输允许, 0, 不允许; 1, 发送允许; 2 接收允许
int transId; // 当前传输ID
int sendStatus; // 发送状态, 0, 空闲; 1, 发送中; 2接收回包中; 3, 完成。
int sendResult; // 发送结果, 0 正常空闲; 1发送成功 2 发送失败; 3等待回包成功4 等待回包超时
int sendSteps; // 发送控制步骤
int hasBack; // 是否有回包(会自动等待回包)
int resvStatus; // 接收状态, 0 空闲; 1, 等待接收中; 2, 收到数据包; 3. 接收停止
u32 ustimer;
}MtCommCtrl;
MtCommCtrl g_mtCommCtrl;
//------------------------------------------------------
// 初始化
// 注册收发函数和485开关函数
void InitMtComm(MtCommExFuncs * pExFuncs)
{
memset(&g_mtCommCtrl, 0, sizeof(MtCommCtrl));
if (pExFuncs != NULL)
{
memcpy(&(g_mtCommCtrl.commExFuncs), pExFuncs, sizeof(MtCommExFuncs));
}
}
// 异步收发过程,完成数据的收发过程。
// 需要在控制流程中不停调用
void MtCommAsyncTask(void)
{
if (g_mtCommCtrl.transEnable == 1) // 发送允许
{
switch (g_mtCommCtrl.sendSteps)
{
case 0:
g_mtCommCtrl.sendStatus = 1; // 传输中
g_mtCommCtrl.sendResult = 0;
g_mtCommCtrl.sendSteps++;
break;
case 1: // 打开发送允许
{
if (g_mtCommCtrl.commExFuncs.Set485TxEnOn != NULL)
{
g_mtCommCtrl.commExFuncs.Set485TxEnOn(); // 发送允许打开
}
g_mtCommCtrl.ustimer = GetUsSoftTimer();
g_mtCommCtrl.sendSteps++;
break;
}
case 2: // 等待发送允许生效, 开始发送数据包
{
u32 thisus;
thisus = GetUsSoftTimer();
if (thisus - g_mtCommCtrl.ustimer > 200)
{
if (g_mtCommCtrl.commExFuncs.SendMtCommData != NULL)
{
g_mtCommCtrl.commExFuncs.SendMtCommData((u8*)&g_mtCommCtrl.sendPacket, LEN_MTCOMM_PKT); // 发送数据
}
g_mtCommCtrl.sendSteps++;
}
break;
}
case 3: // 等待发送完成
{
int freelen = 0;
if (g_mtCommCtrl.commExFuncs.GetTrsFreeLen != NULL)
{
freelen = g_mtCommCtrl.commExFuncs.GetTrsFreeLen();
}
if (freelen <= 0)
{
g_mtCommCtrl.ustimer = GetUsSoftTimer();
g_mtCommCtrl.sendSteps++;
}
break;
}
case 4: // 等待最后一个发送完成, 关闭发送允许
{
u32 thisus;
thisus = GetUsSoftTimer();
if (thisus - g_mtCommCtrl.ustimer > 200)
{
if (g_mtCommCtrl.commExFuncs.Set485TxEnOff != NULL)
{
g_mtCommCtrl.commExFuncs.Set485TxEnOff(); // 发送允许关闭
}
g_mtCommCtrl.sendSteps++;
}
break;
}
case 5:
{
if (g_mtCommCtrl.hasBack != 0) // 如果有回包
{
g_mtCommCtrl.sendStatus = 2; // 等待回包状态
g_mtCommCtrl.ustimer = GetUsSoftTimer(); // 记录时间点
g_mtCommCtrl.resvStatus = 0;
g_mtCommCtrl.transEnable = 2; // 启动接收
}
else
{
g_mtCommCtrl.sendStatus = 3; // 传输完成
g_mtCommCtrl.sendResult = 1; // 发送成功
g_mtCommCtrl.transEnable = 0; // 不允许传输
}
break;
}
default:
{
g_mtCommCtrl.sendStatus = 3; // 传输完成
g_mtCommCtrl.sendResult = 2; // 发送失败
g_mtCommCtrl.transEnable = 0; // 不允许传输
break;
}
}
}
else if (g_mtCommCtrl.transEnable == 2) // 接收允许
{
int rsvlen = 0;
g_mtCommCtrl.resvStatus = 1; // 接收数据中
if (g_mtCommCtrl.commExFuncs.Set485TxEnOff != NULL) // 关闭发送允许
{
g_mtCommCtrl.commExFuncs.Set485TxEnOff(); // 发送允许关闭
}
if (g_mtCommCtrl.commExFuncs.GetMtRsvLen != NULL)
{
rsvlen = g_mtCommCtrl.commExFuncs.GetMtRsvLen(); // 得到已接收数据长度
}
if (rsvlen >= LEN_MTCOMM_PKT) // 数据长度够
{
if (g_mtCommCtrl.commExFuncs.GetMtCommData != NULL)
{
g_mtCommCtrl.commExFuncs.GetMtCommData((u8*)&g_mtCommCtrl.resvPacket, LEN_MTCOMM_PKT); // 接收数据
}
if (g_mtCommCtrl.hasBack != 0) // 如果有回包
{
g_mtCommCtrl.hasBack = 0;
g_mtCommCtrl.sendStatus = 3; // 传输完成
g_mtCommCtrl.sendResult = 3; // 结果正确
}
g_mtCommCtrl.resvStatus = 2; // 收到数据包
g_mtCommCtrl.ustimer = GetUsSoftTimer(); // 记录时间点
g_mtCommCtrl.transEnable = 0; // 关闭传输
}
else
{
if (g_mtCommCtrl.hasBack != 0) // 如果有回包
{
u32 thisus;
thisus = GetUsSoftTimer();
if (thisus - g_mtCommCtrl.ustimer > 10000) // 10ms 超时
{
g_mtCommCtrl.resvStatus = 3; // 接收停止
g_mtCommCtrl.hasBack = 0;
g_mtCommCtrl.sendStatus = 3; // 传输完成
g_mtCommCtrl.sendResult = 4; // 结果超时
g_mtCommCtrl.transEnable = 0; // 关闭传输
}
}
else
{
// 继续等待
}
}
}
else // 其他情况, 什么也不做
{
}
}
// 打包一个数据包
// 添加同步字生成CRC
int PacketAMtComm(MtCommPacket * pPacket)
{
if (pPacket == NULL)
{
return -1;
}
memcpy(pPacket->sync, MTCOMM_SYNC, MT_SYNC_LEN);
pPacket->crc8 = CalcCrc8((u8*)pPacket, MT_CHECK_LEN);
return 0;
}
// 校验一个数据包
// 验证同步字和CRC
// 返回0正常
int CheckAMtPacket(MtCommPacket * pPacket)
{
int rslt;
if (pPacket == NULL)
{
return -1;
}
rslt = memcmp(pPacket->sync, MTCOMM_SYNC, MT_SYNC_LEN);
if (rslt == 0)
{
u8 crc;
crc = CalcCrc8((u8*)pPacket, MT_CHECK_LEN);
if (pPacket->crc8 != crc)
{
rslt = -2;
}
}
return rslt;
}
// 读空接收buff
void ReadMtCommBuffEmpty(void)
{
int rslt, len;
u8 temp;
len = 0;
if (g_mtCommCtrl.commExFuncs.GetMtRsvLen != NULL)
{
len = g_mtCommCtrl.commExFuncs.GetMtRsvLen();
}
while (len > 0)
{
if (g_mtCommCtrl.commExFuncs.GetMtCommData != NULL)
{
rslt = g_mtCommCtrl.commExFuncs.GetMtCommData(&temp, 1);
}
else
{
break;
}
if (rslt != 1)
{
rslt = 0;
break;
}
len--;
}
}
// 启动一次发送任务
// 返回传输ID
int SendAMtPacket(MtCommPacket * pPacket, int hasback)
{
if (pPacket == NULL)
{
return -1;
}
if (g_mtCommCtrl.sendStatus != 0 || g_mtCommCtrl.sendStatus != 3)
{
return -2;
}
g_mtCommCtrl.transEnable = 0;
g_mtCommCtrl.sendStatus = 0;
g_mtCommCtrl.sendResult = 0;
g_mtCommCtrl.sendSteps = 0;
// 是否等待回包
g_mtCommCtrl.hasBack = hasback;
g_mtCommCtrl.transId++; // 传输 ID 自增
if (g_mtCommCtrl.transId < 10 || g_mtCommCtrl.transId > 10000000)
{
g_mtCommCtrl.transId = 10;
}
memcpy(&g_mtCommCtrl.sendPacket, pPacket, LEN_MTCOMM_PKT);
g_mtCommCtrl.transEnable = 1; // 启动接收
return g_mtCommCtrl.transId; // 返回当前传输的ID方便后续查询使用
}
// 获取发送状态
int GetSendStatus(int id)
{
int sta;
if (g_mtCommCtrl.transId != id)
{
return -1;
}
sta = g_mtCommCtrl.sendStatus;
if (sta == 3)
{
g_mtCommCtrl.sendStatus = 0; // 自动清零
}
return sta;
}
// 获取发送结果
int GetSendResult(int id)
{
if (g_mtCommCtrl.transId != id)
{
return -1;
}
return g_mtCommCtrl.sendResult;
}
// 读取一个数据包
// 如果接收到, 回包数据在pPacket中
int GetAMtPacket(MtCommPacket * pPacket)
{
if (g_mtCommCtrl.transEnable != 2) // 非接收状态
{
g_mtCommCtrl.transEnable = 0;
g_mtCommCtrl.resvStatus = 0;
ReadMtCommBuffEmpty();
g_mtCommCtrl.transEnable = 2; // 启动接收
}
#define MAX_MTCOMM_SCAN 128 // 单次最大扫描个数
if (1)
{
int rslt, len;
int i;
int phase;
u8 temp;
u8 rdBuf[LEN_MTCOMM_PKT];
MtCommPacket * pDat;
if (pPacket == NULL ||
g_mtCommCtrl.commExFuncs.GetMtRsvLen == NULL ||
g_mtCommCtrl.commExFuncs.GetMtCommData == NULL ||
0 )
{
return -1;
}
i = 0; // 扫描字节计数器
pDat = (MtCommPacket *)rdBuf;
do
{
len = g_mtCommCtrl.commExFuncs.GetMtRsvLen();
if (len < LEN_MTCOMM_PKT)
{
rslt = -3;
break; // 没有足够数据
}
phase = 0;
rslt = 0;
// 从接收缓冲区中找数据包
while(((len + phase) >= LEN_MTCOMM_PKT) && (phase < LEN_MTCOMM_PKT))
{
if (phase == 0 && i > MAX_MTCOMM_SCAN)
{
rslt = -4;
break; // 查找同步序列超出最大单次扫描字节数
}
rslt = g_mtCommCtrl.commExFuncs.GetMtCommData(&temp, 1); // 读取一个字节
if (rslt != 1)
{
printf("error at GetMtCommData rslt\r\n");
rslt = -8;
break;
}
rslt = 0;
i++; // 扫描字数增加
len--; // 剩余长度减小
if (phase < MT_SYNC_LEN) // 识别同步序列
{
if (temp != MTCOMM_SYNC[phase])
{
phase = 0;
rslt = 0;
break;
}
}
rdBuf[phase] = temp; // 保存
phase++;
}
if (rslt != 0)
{
break;
}
if (phase >= LEN_MTCOMM_PKT) // 得到数据包
{
u8 crc8;
crc8 = CalcCrc8(rdBuf, MT_CHECK_LEN);
if (crc8 == pDat->crc8)
{
// 得到正确数据包
memcpy(pPacket, pDat, LEN_MTCOMM_PKT);
// printf("GetAMtCommPacket ok\r\n");
rslt = LEN_MTCOMM_PKT;
break;
}
else
{
// CRC 不正确
printf("1. crc error in GetAMtCommPacket\r\n");
// 拷贝需要再判断的数据
// continue;
}
}
else
{
// 没有找到同步序列的情况
// continue;
}
}while(1);
return rslt;
}
}