#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; } }