diff --git a/tcl.c b/tcl.c index 76fe0a5..73b9cae 100644 --- a/tcl.c +++ b/tcl.c @@ -20,7 +20,7 @@ #define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔 #define MAX_RETRY_CNT 3 #define RING_BUFFER_SIZE (1024 * 3) -#define FRAME_SIZE_MAX (200) +#define MAX_FRAME_LENGTH (200) /// @brief 主从模式,主机拥有更高优先级 typedef enum @@ -41,22 +41,23 @@ typedef enum typedef enum { ERR_OK = 0, + ERR_NOK, + ERR_TIMEOUT, ERR_HEADER, ERR_TAIL, ERR_CRC, - ERR_TIMEOUT, - ERR_UNKNOWN, - ERR_NOK + ERR_LENGTH, + ERR_NREADY } err_t; static devmode_t devMode = HOST_MODE; static devstatus_t curMode = R_MODE; static devstatus_t tarMode = R_MODE; -volatile int trySwt = 0; // 是否尝试切换到发送模式 +volatile int isOK2Swt = 1; // 是否尝试切换到发送模式 static devstatus_t tarDevMode = R_MODE; // 目标端工作模式 static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器 static int rxNewDataFlag = 0; -static uint8_t lstLineRxData[FRAME_SIZE_MAX]; // 透传缆最后一个接收到的数据 +static uint8_t lstLineRxData[MAX_FRAME_LENGTH]; // 透传缆最后一个接收到的数据 static uint8_t lstLineRxDataLen = 0; // 透传缆最后一个接收到的数据长度 static int isTimeOut = 0; static Node *userRxBuffList = NULL; // user端接收缓冲链表 @@ -168,10 +169,7 @@ uint64_t getPlatformTicks(void) // Callback functions for the timers void retryTimerCallback(MultiTimer *timer, void *userData) { - if (tarDevMode == R_MODE && curMode == R_MODE && tarMode == T_MODE) // 两端为收方可发起请求 - { - trySwt = 1; - } + isOK2Swt = 1; printf("Timer 1 fired at %lu ms\n", getPlatformTicks()); } @@ -200,11 +198,16 @@ uint8_t bccCRC(uint8_t *data, uint8_t len) /// @brief 检查数据有效性 /// @param data 待校验数据 /// @param len 数据长度 -/// @return 0->有效 1->帧头无效 2->帧尾无效 3->校验位无效 +/// @return 0->有效 err_t chkDataValid(uint8_t *data, uint8_t len) { // 按帧发送数据 // 判断帧的完整性及校验位 + if (len > MAX_FRAME_LENGTH) + { + return ERR_LENGTH; + } + if (data[0] != 0x5A || data[1] != 0xA5) // 帧头校验 { return ERR_HEADER; @@ -228,13 +231,23 @@ err_t chkDataValid(uint8_t *data, uint8_t len) /// @param len void userRecDataCallback(uint8_t *data, uint8_t len) { - if (chkDataValid(data, len)) + //等待时间内不能发送数据 + if (!isOK2Swt) { + userTransmitData(ERR_NREADY,1); + } + + err_t rst= chkDataValid(data, len); + if (rst == ERR_OK) + { + //校验通过则加入待发列表 appendNode(&userRxBuffList, data, len); + //由发送函数反馈发送结果 } else { - userTransmitData(CMD_ACK_NOK, 1); + //校验不通过立即反馈 + userTransmitData(rst, 1); } } @@ -260,7 +273,7 @@ err_t getACK(int timeOut) { if (isTimeOut) { - return ERR_NOK; + return ERR_TIMEOUT; } if (rxNewDataFlag) @@ -318,6 +331,10 @@ void handleTR() { lineTransmitData(CMD_ACK_OK, 1); userTransmitData(lstLineRxData, lstLineRxDataLen); + //每次建立通信后10s内收端不能发起通信 + isOK2Swt = 0; + multiTimerStop(&retryTimer); + multiTimerStart(&retryTimer, 10*1000, retryTimerCallback, NULL); // Start timer } else { @@ -327,14 +344,14 @@ void handleTR() } // 有数据需要发送 - if (getListSize(userRxBuffList) > 0) + if (isOK2Swt && getListSize(userRxBuffList) > 0) { // 发送数据 uint8_t reTryCnt = 0; err_t lstState = ERR_OK; while (userRxBuffList != NULL) // 遍历链表 { - if (lstState != ERR_OK) + if (lstState == ERR_NOK) { if (!isTimeOut) { @@ -350,12 +367,21 @@ void handleTR() lineTransmitData(userRxBuffList->data, userRxBuffList->size); if (USING_ACK == 1) // 使用ACK { - if (getACK(userRxBuffList->size * 10) == ERR_OK) // ACK正常 + err_t rst = getACK(userRxBuffList->size * 10); + if (rst == ERR_TIMEOUT) + { + lstState = ERR_TIMEOUT; + userTransmitData(ERR_TIMEOUT, 1); + // 超时错误大概率是透传缆损坏,不主动重试,终止发送 + break; + } + else if (rst == ERR_OK) // ACK正常 { lstState = ERR_OK; userRxBuffList = userRxBuffList->next; // 正常则移动指针 deleteFirstNode(&userRxBuffList); - userTransmitData(CMD_ACK_OK, 1); + // userTransmitData(CMD_ACK_OK, 1); + userTransmitData(ERR_OK, 1); } else { @@ -365,11 +391,13 @@ void handleTR() { reTryCnt = 0; lstState = ERR_OK; - userRxBuffList = userRxBuffList->next; // 正常则移动指针 + userRxBuffList = userRxBuffList->next; // 次数超出阈值则移动指针 deleteFirstNode(&userRxBuffList); - userTransmitData(CMD_ACK_NOK, 1); + // userTransmitData(CMD_ACK_NOK, 1); + userTransmitData(ERR_NOK,1); break; } + //失败的原因可能是数据碰撞,需要根据优先级等待不同的时间后进行重试 multiTimerStop(&timeoutTimer); multiTimerStart(&timeoutTimer, time2Retry, timeOutTimerCallback, NULL); // Start timer }