改用链表保存待发数据
完成基本逻辑
This commit is contained in:
parent
b02e5c4e74
commit
92a02c11c4
99
linkedlist.c
Normal file
99
linkedlist.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// linkedlist.c
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
|
// 创建新节点并为其分配不定长数组
|
||||||
|
Node* createNode(int* arr, int size) {
|
||||||
|
Node* newNode = (Node*)malloc(sizeof(Node));
|
||||||
|
if (!newNode) {
|
||||||
|
printf("内存分配失败\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode->data = (int*)malloc(size * sizeof(int)); // 分配数组内存
|
||||||
|
if (!newNode->data) {
|
||||||
|
printf("数组内存分配失败\n");
|
||||||
|
free(newNode); // 释放节点内存
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
newNode->data[i] = arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode->size = size;
|
||||||
|
newNode->next = NULL;
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向链表末尾添加节点
|
||||||
|
void appendNode(Node** head, int* arr, int size) {
|
||||||
|
Node* newNode = createNode(arr, size);
|
||||||
|
|
||||||
|
if (*head == NULL) {
|
||||||
|
*head = newNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* temp = *head;
|
||||||
|
while (temp->next != NULL) {
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp->next = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除链表的第一个节点
|
||||||
|
void deleteFirstNode(Node** head) {
|
||||||
|
if (*head == NULL) {
|
||||||
|
printf("链表为空,无法删除第一个节点。\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* temp = *head;
|
||||||
|
*head = (*head)->next;
|
||||||
|
|
||||||
|
free(temp->data); // 释放数组
|
||||||
|
free(temp); // 释放节点
|
||||||
|
|
||||||
|
printf("第一个节点已删除。\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印链表
|
||||||
|
void printList(Node* head) {
|
||||||
|
Node* temp = head;
|
||||||
|
while (temp != NULL) {
|
||||||
|
printf("节点数组: ");
|
||||||
|
for (int i = 0; i < temp->size; i++) {
|
||||||
|
printf("%d ", temp->data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放链表占用的内存
|
||||||
|
void freeList(Node* head) {
|
||||||
|
Node* temp;
|
||||||
|
while (head != NULL) {
|
||||||
|
temp = head;
|
||||||
|
head = head->next;
|
||||||
|
free(temp->data); // 释放节点中的数组
|
||||||
|
free(temp); // 释放节点本身
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取链表中节点的数量
|
||||||
|
int getListSize(Node* head) {
|
||||||
|
int count = 0;
|
||||||
|
Node* temp = head;
|
||||||
|
|
||||||
|
while (temp != NULL) {
|
||||||
|
count++;
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
20
linkedlist.h
Normal file
20
linkedlist.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// linkedlist.h
|
||||||
|
|
||||||
|
#ifndef LINKEDLIST_H
|
||||||
|
#define LINKEDLIST_H
|
||||||
|
|
||||||
|
// 定义链表节点的结构体,并使用 typedef 进行简化
|
||||||
|
typedef struct Node {
|
||||||
|
int* data; // 指向不定长数组的指针
|
||||||
|
int size; // 数组的大小
|
||||||
|
struct Node* next; // 指向下一个节点的指针
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
// 函数声明
|
||||||
|
Node* createNode(int* arr, int size); // 创建新节点
|
||||||
|
void appendNode(Node** head, int* arr, int size); // 添加节点到链表末尾
|
||||||
|
void deleteFirstNode(Node** head); // 删除链表的第一个节点
|
||||||
|
void printList(Node* head); // 打印链表
|
||||||
|
void freeList(Node* head); // 释放链表内存
|
||||||
|
int getListSize(Node* head); // 获取链表中的节点数量
|
||||||
|
#endif // LINKEDLIST_H
|
243
tcl.c
243
tcl.c
@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "MultiTimer.h"
|
#include "MultiTimer.h"
|
||||||
#include "lwrb/lwrb.h"
|
#include "lwrb/lwrb.h"
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
#define CMD_TRA_MODE 0xA1
|
#define CMD_TRA_MODE 0xA1
|
||||||
#define CMD_REC_MODE 0xA2
|
#define CMD_REC_MODE 0xA2
|
||||||
@ -12,10 +13,12 @@
|
|||||||
#define CMD_ACK_OK 0xAB
|
#define CMD_ACK_OK 0xAB
|
||||||
#define CMD_ACK_NOK 0xAF
|
#define CMD_ACK_NOK 0xAF
|
||||||
|
|
||||||
|
#define USING_ACK 1
|
||||||
|
|
||||||
#define MIN_TR_PERIOD_MS (1000 * 5) // 单字节最小传输时间
|
#define MIN_TR_PERIOD_MS (1000 * 5) // 单字节最小传输时间
|
||||||
#define HOST_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000) // 主机重试时间间隔
|
#define HOST_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000) // 主机重试时间间隔
|
||||||
#define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔
|
#define CLIENT_RETRY_PERIOD_MS (MIN_TR_PERIOD_MS + 1000 * 10) // 客户端重试时间间隔
|
||||||
|
#define MAX_RETRY_CNT 3
|
||||||
#define RING_BUFFER_SIZE (1024 * 3)
|
#define RING_BUFFER_SIZE (1024 * 3)
|
||||||
#define FRAME_SIZE_MAX (200)
|
#define FRAME_SIZE_MAX (200)
|
||||||
|
|
||||||
@ -40,7 +43,10 @@ typedef enum
|
|||||||
ERR_OK = 0,
|
ERR_OK = 0,
|
||||||
ERR_HEADER,
|
ERR_HEADER,
|
||||||
ERR_TAIL,
|
ERR_TAIL,
|
||||||
ERR_CRC
|
ERR_CRC,
|
||||||
|
ERR_TIMEOUT,
|
||||||
|
ERR_UNKNOWN,
|
||||||
|
ERR_NOK
|
||||||
} err_t;
|
} err_t;
|
||||||
|
|
||||||
static devmode_t devMode = HOST_MODE;
|
static devmode_t devMode = HOST_MODE;
|
||||||
@ -49,11 +55,12 @@ static devstatus_t tarMode = R_MODE;
|
|||||||
volatile int trySwt = 0; // 是否尝试切换到发送模式
|
volatile int trySwt = 0; // 是否尝试切换到发送模式
|
||||||
static devstatus_t tarDevMode = R_MODE; // 目标端工作模式
|
static devstatus_t tarDevMode = R_MODE; // 目标端工作模式
|
||||||
static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器
|
static MultiTimer retryTimer, timeoutTimer; // 重试定时器、超时定时器
|
||||||
lwrb_t traBuff,frameLenBuff;// 环形缓冲区
|
static int rxNewDataFlag = 0;
|
||||||
uint8_t ringBuffer[RING_BUFFER_SIZE];
|
static uint8_t lstLineRxData[FRAME_SIZE_MAX]; // 透传缆最后一个接收到的数据
|
||||||
uint8_t buffer[FRAME_SIZE_MAX];// 单次待发数据缓冲区
|
static uint8_t lstLineRxDataLen = 0; // 透传缆最后一个接收到的数据长度
|
||||||
uint8_t frameLen[15];//缓存区数据帧对应长度
|
static int isTimeOut = 0;
|
||||||
|
static Node *userRxBuffList = NULL; // user端接收缓冲链表
|
||||||
|
// static err_t lstState = ERR_OK;
|
||||||
|
|
||||||
// 设置GPIO电平
|
// 设置GPIO电平
|
||||||
void setGpioLevel(int gpio, int level)
|
void setGpioLevel(int gpio, int level)
|
||||||
@ -94,16 +101,17 @@ void lineTransmitData(uint8_t *data, uint8_t len)
|
|||||||
// 发送数据
|
// 发送数据
|
||||||
|
|
||||||
// 发送完毕后需恢复为接收模式
|
// 发送完毕后需恢复为接收模式
|
||||||
|
msdelay(len * 10);
|
||||||
initWorkStatus(R_MODE);
|
initWorkStatus(R_MODE);
|
||||||
}
|
}
|
||||||
// 透传缆发送逻辑
|
// 透传缆发送逻辑
|
||||||
// 0. 用户串口接收待发送数据,放入缓存队列。帧长度对应保存。
|
// 0. 用户串口接收待发送数据,放入缓存链表队列。
|
||||||
// 1. 通过透传缆串口发送数据
|
// 1. 通过透传缆串口发送数据
|
||||||
// 2. 发送完成后切换为接收模式
|
// 2. 发送完成后切换为接收模式
|
||||||
// 3. 通过透传缆串口接收回复的ACK
|
// 3. 通过透传缆串口接收回复的ACK
|
||||||
// 4. ACK正常则发送成功,否则发送失败
|
// 4. ACK正常则发送成功,否则发送失败
|
||||||
// 5. 发送成功则准备发送缓存队列中下一帧数据
|
// 5. 发送成功则准备发送缓存队列中下一帧数据
|
||||||
// 6. 发送失败则重发当前帧
|
// 6. 发送失败则等待指定时间t后重发当前帧
|
||||||
|
|
||||||
/// @brief 通过用户串口发送数据
|
/// @brief 通过用户串口发送数据
|
||||||
/// @param data 待发送数据
|
/// @param data 待发送数据
|
||||||
@ -168,6 +176,13 @@ void retryTimerCallback(MultiTimer *timer, void *userData)
|
|||||||
printf("Timer 1 fired at %lu ms\n", getPlatformTicks());
|
printf("Timer 1 fired at %lu ms\n", getPlatformTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void timeOutTimerCallback(MultiTimer *timer, void *userData)
|
||||||
|
{
|
||||||
|
isTimeOut = 1;
|
||||||
|
|
||||||
|
printf("Timer 1 fired at %lu ms\n", getPlatformTicks());
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief 计算异或XOR校验
|
/// @brief 计算异或XOR校验
|
||||||
/// @param data 待校验数据
|
/// @param data 待校验数据
|
||||||
/// @param len 数据长度
|
/// @param len 数据长度
|
||||||
@ -208,56 +223,18 @@ err_t chkDataValid(uint8_t *data, uint8_t len)
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建长度为3k的队列
|
|
||||||
|
|
||||||
// 更新缓存队列
|
|
||||||
void updateDataQueue(uint8_t *data, uint8_t len)
|
|
||||||
{
|
|
||||||
lwrb_write(&traBuff, data, len);
|
|
||||||
lwrb_write(&frameLenBuff, len, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief 用户接口接收数据回调
|
/// @brief 用户接口接收数据回调
|
||||||
/// @param data
|
/// @param data
|
||||||
/// @param len
|
/// @param len
|
||||||
void userRecDataCallback(uint8_t *data, uint8_t len)
|
void userRecDataCallback(uint8_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
if (len == 1)
|
if (chkDataValid(data, len))
|
||||||
{
|
{
|
||||||
switch (data[0])
|
appendNode(&userRxBuffList, data, len);
|
||||||
{
|
|
||||||
case CMD_REC_MODE:
|
|
||||||
switchToRecMode();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_TRA_MODE:
|
|
||||||
if (curMode == R_MODE && tarDevMode == R_MODE)
|
|
||||||
{
|
|
||||||
switchToTraMode();
|
|
||||||
// ok
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_SLP_MODE:
|
|
||||||
initWorkMode(SLEEP_MODE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_WKP_MODE:
|
|
||||||
initWorkMode(WORK_MODE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 需要透传的数据
|
userTransmitData(CMD_ACK_NOK, 1);
|
||||||
updateDataQueue(data, len);
|
|
||||||
// if (chkDataValid(data, len))
|
|
||||||
// {
|
|
||||||
// lineTransmitData(data, len);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,61 +243,42 @@ void userRecDataCallback(uint8_t *data, uint8_t len)
|
|||||||
/// @param len
|
/// @param len
|
||||||
void lineRecCallback(uint8_t *data, uint8_t len)
|
void lineRecCallback(uint8_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
if (len == 1)
|
rxNewDataFlag = 1;
|
||||||
{
|
memcpy(lstLineRxData, data, len);
|
||||||
switch (data[0])
|
lstLineRxDataLen = len;
|
||||||
{
|
}
|
||||||
case CMD_REC_MODE:
|
|
||||||
lineTransmitData(CMD_ACK_OK, 1);
|
|
||||||
tarDevMode = R_MODE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_TRA_MODE: // 对端请求切换为发送模式
|
/// @brief 阻塞方式接收ACK数据
|
||||||
if (curMode == R_MODE)
|
/// @param timeOut 指定超时时间,单位ms
|
||||||
|
/// @return 返回ACK状态
|
||||||
|
err_t getACK(int timeOut)
|
||||||
{
|
{
|
||||||
lineTransmitData(CMD_ACK_OK, 1);
|
rxNewDataFlag = 0;
|
||||||
tarDevMode = T_MODE;
|
multiTimerStop(&timeoutTimer);
|
||||||
|
multiTimerStart(&timeoutTimer, timeOut, timeOutTimerCallback, NULL); // Start timer
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (isTimeOut)
|
||||||
|
{
|
||||||
|
return ERR_NOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rxNewDataFlag)
|
||||||
|
{
|
||||||
|
rxNewDataFlag = 0;
|
||||||
|
if (lstLineRxDataLen == 1 && lstLineRxData[0] == CMD_ACK_OK)
|
||||||
|
{
|
||||||
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lineTransmitData(CMD_ACK_NOK, 1);
|
return ERR_NOK;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
lineTransmitData(CMD_ACK_NOK, 1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (chkDataValid(data, len) == ERR_OK)
|
continue;
|
||||||
{
|
|
||||||
lineTransmitData(CMD_ACK_OK, 1);
|
|
||||||
userTransmitData(data, len);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTransmitData(CMD_ACK_NOK, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void transmitDataCallback(lwrb_t *buff, lwrb_evt_type_t type, size_t len)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case LWRB_EVT_RESET:
|
|
||||||
printf("[EVT] Buffer reset event!\r\n");
|
|
||||||
break;
|
|
||||||
case LWRB_EVT_READ:
|
|
||||||
printf("[EVT] Buffer read event: %d byte(s)!\r\n", (int)len);
|
|
||||||
break;
|
|
||||||
case LWRB_EVT_WRITE:
|
|
||||||
printf("[EVT] Buffer write event: %d byte(s)!\r\n", (int)len);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,42 +287,101 @@ void handleTR()
|
|||||||
{
|
{
|
||||||
// 初始化外设
|
// 初始化外设
|
||||||
|
|
||||||
uint8_t retryTime = 100;
|
uint16_t time2Retry = 0;
|
||||||
if (devMode == HOST_MODE)
|
if (devMode == HOST_MODE)
|
||||||
{
|
{
|
||||||
// 间隔0.1s
|
// 间隔1s
|
||||||
retryTime = 100;
|
time2Retry = 1000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retryTime = 1000;
|
time2Retry = 1000 * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化MultiTimer
|
// 初始化MultiTimer
|
||||||
multiTimerInstall(getPlatformTicks);
|
multiTimerInstall(getPlatformTicks);
|
||||||
// 定时器始终开启
|
|
||||||
multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // Start timer
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
lwrb_init(&traBuff, ringBuffer, RING_BUFFER_SIZE);
|
|
||||||
lwrb_init(&frameLenBuff,frameLen,sizeof(frameLen));
|
|
||||||
lwrb_set_evt_fn(&traBuff, transmitDataCallback);
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
multiTimerYield();
|
multiTimerYield();
|
||||||
if (trySwt)
|
|
||||||
|
// 收到新数据
|
||||||
|
if (rxNewDataFlag)
|
||||||
{
|
{
|
||||||
trySwt = 0; // clear flag
|
if (lstLineRxDataLen == 1)
|
||||||
switchToTraMode();
|
|
||||||
multiTimerStart(&retryTimer, retryTime, retryTimerCallback, NULL); // always restart timer
|
|
||||||
}
|
|
||||||
if (lwrb)
|
|
||||||
{
|
{
|
||||||
/* code */
|
/* code */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (chkDataValid(lstLineRxData, lstLineRxDataLen) == ERR_OK)
|
||||||
|
{
|
||||||
|
lineTransmitData(CMD_ACK_OK, 1);
|
||||||
|
userTransmitData(lstLineRxData, lstLineRxDataLen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineTransmitData(CMD_ACK_NOK, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有数据需要发送
|
||||||
|
if (getListSize(userRxBuffList) > 0)
|
||||||
|
{
|
||||||
|
// 发送数据
|
||||||
|
uint8_t reTryCnt = 0;
|
||||||
|
err_t lstState = ERR_OK;
|
||||||
|
while (userRxBuffList != NULL) // 遍历链表
|
||||||
|
{
|
||||||
|
if (lstState != ERR_OK)
|
||||||
|
{
|
||||||
|
if (!isTimeOut)
|
||||||
|
{
|
||||||
|
// 跳过后续代码进入下次循环
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isTimeOut = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineTransmitData(userRxBuffList->data, userRxBuffList->size);
|
||||||
|
if (USING_ACK == 1) // 使用ACK
|
||||||
|
{
|
||||||
|
if (getACK(userRxBuffList->size * 10) == ERR_OK) // ACK正常
|
||||||
|
{
|
||||||
|
lstState = ERR_OK;
|
||||||
|
userRxBuffList = userRxBuffList->next; // 正常则移动指针
|
||||||
|
deleteFirstNode(&userRxBuffList);
|
||||||
|
userTransmitData(CMD_ACK_OK, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lstState = ERR_NOK;
|
||||||
|
reTryCnt++;
|
||||||
|
if (reTryCnt > MAX_RETRY_CNT)
|
||||||
|
{
|
||||||
|
reTryCnt = 0;
|
||||||
|
lstState = ERR_OK;
|
||||||
|
userRxBuffList = userRxBuffList->next; // 正常则移动指针
|
||||||
|
deleteFirstNode(&userRxBuffList);
|
||||||
|
userTransmitData(CMD_ACK_NOK, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
multiTimerStop(&timeoutTimer);
|
||||||
|
multiTimerStart(&timeoutTimer, time2Retry, timeOutTimerCallback, NULL); // Start timer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // 无ACK
|
||||||
|
{
|
||||||
|
lstState = ERR_OK;
|
||||||
|
userRxBuffList = userRxBuffList->next; // 移动指针
|
||||||
|
deleteFirstNode(&userRxBuffList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user