tpgf 发表于 2025-2-6 13:34

环形缓冲区的使用


uint8_t parse_uart_cmd(uint8_t lastcmdCnt)
{
       

        uint8_t buf = {0} ,*p;
        uint8_t j=0, datalen = 0,yu=0;
        uint8_t cmdtype = 0,cmdCnt = lastcmdCnt; //0 此处应当是实际的数据
        int out=0;

#if UART_RX_MODE == 1
        uint8_t start_index = cmd_start;
        uint8_t end_index = cmd_end;       
        memcpy(buf, cmdbuf, end_index);
        cmd_start = 0;
        cmd_end = 0;
        datalen = end_index;
        for(j=0; j<=datalen-7; ){
                cmdtype = parse_single_cmd(&buf, cmdCnt);
                if(cmdtype){
                        cmdlist = cmdtype;
                        cmdCnt++;
                        j+=8;
                }
                else{
                        j++;
                }
        }
#elif UART_RX_MODE ==2
    //DMA_UART_MODE
        uint8_t start_index = cmd_start;
        uint8_t end_index = RxBufLen - DMA1_Channel5->CNDTR; //待传输的数据-->等待传输的数据 处理的次数增多而减少
       
    //-->no more new data
        if(end_index == start_index)                              //just a line
                return cmdCnt;                                          // 0
        //conclulate the lenth of buffer recived
        else if(end_index > start_index){                           //normal consituation
                datalen = end_index - start_index;
                memcpy(buf, &sRxBuffer, datalen);                  //copy theRX to buffer
//                yu = datalen % 8;
//                end_index -= yu;
        }
        //the wrong consituation that the buffer is outoff
        //先将 start_index 到缓冲区末尾的数据复制到 buf 中,然后将从缓冲区开头到 end_index 的数据复制到 buf 的剩余部分。最后计算 datalen。
        else{//end_index = RxBufLen - DMA1_Channel5->CNDTR;
                memcpy(buf, &sRxBuffer, RxBufLen-start_index);//exceed a line and return loop
                memcpy(&buf, sRxBuffer, end_index); //复制剩下的全部
                datalen = (RxBufLen - start_index) + end_index ;
//                yu = datalen % 8;
//                if(end_index>=yu)
//                        end_index -= yu;
//                else
//                        end_index = RxBufLen + end_index-yu;
        }
        #if 1
        if(datalen>COMMAND_LEN){//判断出datalen的长度,再根据该长度进行下一步操作
                //ljz add
       #if UART_DEBUG==1
                p=buf;
                printf("LJZ RX buf: ");
                while(*p!=NULL)
                {
                        printf("%02X ",*p);
                        p++;
                }
                printf("\r\n");
                #endif

                cmd_start = (end_index>(COMMAND_LEN-1)) ? (end_index-COMMAND_LEN):(RxBufLen + end_index)-COMMAND_LEN ;//判断下一个指令的长度
               
                for(j=0; j<datalen-COMMAND_LEN; ){
                        cmdtype = parse_single_cmd(&buf, cmdCnt);//检查是否是功能选择指令
                        if(cmdtype){
                                cmdlist = cmdtype;
                                cmdCnt++;
                                #if UART_DEBUG ==1
                                printf("LJZ Command item: %d\r\n",cmdCnt);
                                #endif
                                j+=(COMMAND_LEN+1);    //处理下一串指令
                        }
                        else{
                                j++;    //处理下一个指令
                        }
       
                }
        }
    #endif       
        #if 0
        if(datalen>7){
          #if UART_DEBUG==1
                p=buf;
                printf("LJZ RX buf: ");
                while(*p!=NULL)
                {
                        printf("%02X ",*p);
                        p++;
                }
                printf("\r\n");
                #endif
                ///
                cmd_start = (end_index>6) ? (end_index-7):(RxBufLen + end_index)-7 ;        // 计算 cmd_start: 根据 end_index 和 RxBufLen 计算出一个 cmd_start 值。这个值取决于 end_index 是否大于6,如果是,则从当前位置往前数7个字节作为起始位置;如果不是,则跨越缓冲区边界(即加上 RxBufLen 再减去7)
                for(j=0; j<datalen-7; ){                                                //有循环的功能
                        cmdtype = parse_single_cmd(&buf, cmdCnt); //the singel command alanysis
                        if(cmdtype){
                                cmdlist = cmdtype;
                                cmdCnt++;
                                #if UART_DEBUG ==1
                                printf("LJZ Command item: %d\r\n",cmdCnt);
                                #endif
                                j+=8;
                        }
                        else{
                                j++;
                        }
                }
        }               
    #endif       
       
       
#endif       
        return cmdCnt;            
}


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_43519774/article/details/144298531

chenjun89 发表于 2025-2-9 09:22

网上有封装好的标准库

在水一方00 发表于 2025-2-27 16:06

在DMA模式下,它能够处理环形缓冲区并且逐一解析命令。
页: [1]
查看完整版本: 环形缓冲区的使用