461 lines
8.8 KiB
C
461 lines
8.8 KiB
C
|
||
#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;
|
||
}
|
||
}
|
||
|
||
|