SDK分析

需要3个FIFO
TX
rt_ringbuffer_init(&sendRingBuffer, sendBuffer, sizeof(sendBuffer));---发送数据出去TCP
RX
rt_ringbuffer_init(&rxRingBuffer, rxBuffer, sizeof(rxBuffer));--串口收到数据
rt_ringbuffer_init(&messageRingBuffer, messageBuffer, sizeof(messageBuffer));--对上面的数据分析提炼以后拿到协议数据在分析的FIFO
 

 

其实FIFO已经很好理解 就是FREERTOS的消息队列 !!!一个发 一个收

比如TX的

在串口里面:

uint32_t tslTcpWrite(int fd, uint8_t *data, uint32_t size) {
    int32_t count = 0;
    
    if(NULL == data) {
        return 0;
    }
    
    count = rbWrite(&pRb,  data, size); 
    
    return count;
}

这样就放进去了

在任务或者TIMER里面周期

int8_t tslProtocolHandleSend(void) {
    int32_t tempLength = 0;
    uint8_t tempData[20];
    
    tempLength = rbRead(&pRb, (uint8_t *)&tempData, sizeof(tempData));
    if (tempLength >0)
        {
                printf("\r\n#\r\n");
                G_printHEX(tempData,tempLength);
                printf("\r\n#\r\n");
                //tcpWrite(tempData, tempLength);//模块发送出去 可以是BLE W5500等 
                return 0;
        }
     return 1;
}

这样就发出去!需要的细节是 每次我都是len>就发了!!所以!!你放入的时候 就规规矩矩 一个完整的包放去即可!!

后面RX为什么需要2个??

一个是基本的RX就是串口快速拿到数据

后面的那个是在上一层的 从里面提取一个完整的包!

从一个读出来  在完整的一包放到另外一个

 

其实这里 和之前我说的细节 也是一样 不要随便放!需要规规矩矩放!

我拿出来的依据不是len》0而是 if (tempLength == sizeof(ProtocolMessage_t)) 

所以你最好一次性放入一个包!

WHY 因为里面还有一个数组VALUE可能不会完全赋值满!

 

 

开始自己代码:

协议的文档转化为结构体!这个是真正的一个包

#define MAX_DATA_LEN        0x32
typedef struct {
    uint8_t         head;      
    uint8_t         num;  
    uint8_t         rnum;     
    uint16_t        alen;        
} ProtocolHead_t;
typedef struct {
    ProtocolHead_t   head;
    uint8_t          data[MAX_DATA_LEN];
    uint16_t         crc;
    int              fd;
} ProtocolCommon_t;

static ProtocolCommon_t dataProtocol;

分析数据的状态机

//分析状态机
typedef enum {
    Protocol_head,
    Protocol_num,
    Protocol_rnum,
    Protocol_alen,
    Protocol_body,
    Protocol_crc,
} ProtocolStatus_t;

typedef struct {
    ProtocolStatus_t status;
    uint8_t          alen;
    uint8_t          rlen;
    uint8_t          cmdCount;
    uint16_t         check;
} StatusData_t;

static StatusData_t     statusMachineData;

开始分析:

/*
 * 复位状态机 仅仅针对POS设置
 */
void resetStateMachine(void) {
    statusMachineData.status = Protocol_head;
}

/*
 * 复位状态机中间变量 其他成员清0
 */
void resetStateMachineData(void) {
    statusMachineData.alen = 0;
    statusMachineData.rlen = 0;
    statusMachineData.cmdCount = 0;
    statusMachineData.check = 0;
}
/*
* 协议分析
*/
int8_t protocolAnalyze(int fd, ProtocolCommon_t *protocol, uint8_t element) 
{
	uint16_t crc16 = 0;
	uint8_t finish = 0;
	switch(statusMachineData.status)
	{
		case Protocol_head:
		{
			if (element == 0XAA) 
			{
				statusMachineData.status = Protocol_num;
				protocol->head.head = 0XAA;
			}
			else 
			{
				resetStateMachine();
				resetStateMachineData();
			}
		} break;
		case Protocol_num:
		{
			protocol->head.num = element;
			statusMachineData.status = Protocol_rnum;
		}  break;
		case Protocol_rnum :
		{
			protocol->head.rnum = element;
			statusMachineData.status = Protocol_alen;
		}  break;
		case Protocol_alen:
		{
			if (statusMachineData.cmdCount == 0) 
			{
				protocol->head.alen = element << 8;
				statusMachineData.cmdCount = 1;
			} 
			else if (statusMachineData.cmdCount == 1) 
			{
				protocol->head.alen |= element;
				statusMachineData.cmdCount = 0;
				statusMachineData.alen = protocol->head.alen;
				statusMachineData.status = Protocol_body;
			}
		} break;
		case Protocol_body:
		{
			protocol->data[statusMachineData.rlen++] = element;
			if (statusMachineData.rlen >= statusMachineData.alen) 
			{
				statusMachineData.status = Protocol_crc;
			}
		}  break;
		case Protocol_crc:
		{
			if (statusMachineData.cmdCount == 0)
			{
				protocol->crc = element << 8;
				statusMachineData.cmdCount = 1;
			} 
			else if (statusMachineData.cmdCount == 1) 
			{
				protocol->crc |= element;
				statusMachineData.cmdCount = 0;
				finish =1;
			}
		} break;
		default :    NEVERSHOW  break;
	}
	if(finish)
		if (crc16 == protocol->crc) 
		{   
            show_ProtData(protocol);
			protocol->fd = fd;
			resetStateMachine();
			resetStateMachineData();
			return 0;
		}
    
	return -1;
}

可以测试 发AA 00 FF 00 01 AB 00 00

注意:是一个一个的发送 不是一下子全部发送!

就可以看到一个包被拿出来

每次其实是放入1个 然后每次读出来也就分析一次

注意:这样的状态机分析有一个超时问题 比如我发送AA 00 以后再也没有发送了 那么状态机就

一直POS死在那个位置 可以考虑用一个定期器去割韭菜复位状态机!

暂时没有这么做

 

完成测试一次:

初始化2个FIFO

    gizwitsInit();//L1级别
    FIFO_Init_L2();//L2级别

串口中:

    ProtocolMessage_t message;
    message.fd = 0;
    memcpy(message.data, (uint8_t *)udata.rxBuff,udata.len);
    message.len = 1;
    tslProtocolPutMessage(&message);

每次就是放置一个数据

main有timer 周期后台处理

void timerpaly(void)
{   

tslProtocolLoop();
tslProtocolHandle();
}

下面是L1到L2的传递 可以测试发送 AA 00 FF 00 01 01 00 00 00看到回调了一个注册函数

AA ---头

00 FF --num rnum

 


int8_t tslProtocolLoop(void) {
    int32_t tempLength = 0;
    ProtocolMessage_t message;
    int8_t ret = 0;
    
    tempLength = rbRead(&pRb, (uint8_t *)&message, sizeof(ProtocolMessage_t));
    if (tempLength == sizeof(ProtocolMessage_t)) {
        for (int i = 0; i < message.len; i++) {
            ret = protocolAnalyze(message.fd, &dataProtocol, message.data[i]);
            if (ret == 0)
            {
                if (reciveDataHandleHook) 
                    {
                        reciveDataHandleHook(dataProtocol.head.alen, dataProtocol.data);
                    }
               rbWrite(&pRbL2, (uint8_t *)&dataProtocol, sizeof(ProtocolCommon_t));
            }
        }
    }
    
    return 0;
}

/*
 * 处理用户注册的命令
 * 需要单独在一个线程中运行
这里的用法是在串口中接收数据 也即是放入到FIFO 然后在任务中读FIFO拿出来解析
 */
int8_t tslProtocolHandle(void) 
{
    int32_t tempLength = 0;
    ProtocolCommon_t dataProtocol;
    
    tempLength = rbRead(&pRbL2, (uint8_t *)&dataProtocol, sizeof(ProtocolCommon_t));
    if (tempLength == sizeof(ProtocolCommon_t)) 
        {
                printf("\r\n");
                G_printHEX(&dataProtocol,sizeof(ProtocolCommon_t));
                printf("\r\n");
                show_ProtData(&dataProtocol);
                node_command_type *node =  commer.Find(dataProtocol.data[0]<<8 |dataProtocol.data[1] );
                if(node !=NULL)
                    node->fun(0,0,0,NULL);
                return 0;
        } 
    else 
       {
            return -1;
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值