怎么样接收一帧完整的数据

2019-08-01 15:16发布

接收缓冲区接收到一串数据,但是只有其中的一帧4个ff开头 83结尾的数据才能用,我怎么才能把它截取出来
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
电子缘科技
1楼-- · 2019-08-01 18:37
判断数据,比如你的缓冲区有100位置,然后你就进行从0开始往上循环检测,只要检测到4个ff开头 83结尾的数据就开始放到另外一个缓冲区,这样就提取出来了,如果在这个过程中没有收到这个数据,你就不提取
冰冷的游客
2楼-- · 2019-08-01 20:08
电子缘科技 发表于 2014-7-2 15:13
判断数据,比如你的缓冲区有100位置,然后你就进行从0开始往上循环检测,只要检测到4个ff开头 83结尾的数据 ...

刚接触C不久,能给个具体的代码吗,或者用什么函数实现,谢谢
电子缘科技
3楼-- · 2019-08-02 01:06
你的缓冲区有多大?然后你要接受的数据有多长?这些都要知道才可以帮你想算法
冰冷的游客
4楼-- · 2019-08-02 03:44
 精彩回答 2  元偷偷看……
dirtwillfly
5楼-- · 2019-08-02 08:32
一个51检测串口字符串命令的代码,你参考下吧:
// 调试命令检测函数
U8 CmpCmd(U8 chr);
// 屏蔽51编译器未调用函数警告
void NoCall_Uart(void);

//=============================================================================
// 发送接收队列部分
//=============================================================================
#define URBMax      20              // 接收缓存大小

U8  UartRecvBuf[URBMax];            // 接收缓存
U8  URWP  = 0;                      // 存入指针
U8  URRP  = 0;                      // 读取指针
U8  URNum = 0;                      // 数据数量



#define USBMax      20              // 发送缓存大小

U8  UartSendBuf[URBMax];            // 发送缓存
U8  USWP  = 0;                      // 存入指针
U8  USRP  = 0;                      // 读取指针
U8  USNum = 0;                      // 数据数量

U8  SendFlag = 0;

// 接收数据入队
U8  URQWrite(U8 Data)
{
//    P00 =~P00;
    if(URNum >= URBMax)return FALSE;// 失败
    UartRecvBuf[URWP] = Data;       // 数据入队
    URWP++;                         // 移动指针
    if(URWP >= URBMax)
    {
        URWP = 0;  
    }
    URNum++;
    return TRUE;                    // 成功
}

// 接收数据出队
U8  URQRead(U8 *Data)
{
    if(URNum == 0)return FALSE;     // 失败
    ES     =   0;                   // 关闭串口中断
//    P01 = ~P01;
    *Data = UartRecvBuf[URRP];      // 数据出队
    URRP++;                         // 移动指针
    if(URRP >= URBMax)
    {
        URRP = 0;  
    }
    URNum--;                        
    ES     =   1;                   // 允许串口中断
    return TRUE;                    // 成功
}




// 发送数据入队
U8  USQWrite(U8 Data)
{
    if(USNum >= USBMax)return FALSE;// 失败
    ES     =   0;                   // 关闭串口中断
    UartSendBuf[USWP] = Data;       // 数据入队
    USWP++;                         // 移动指针
    if(USWP >= USBMax)
    {
        USWP = 0;  
    }
    USNum++;
    if(SendFlag == 0)               // 如果不在发送状态
    {
        TI = 1;                     // 则启动发送
    }
    ES     =   1;                   // 允许串口中断
    return TRUE;                    // 成功
}

// 发送数据出队
U8  USQRead(U8 *Data)
{
    if(USNum == 0)return FALSE;     // 失败
    *Data = UartSendBuf[USRP];      // 数据出队
    USRP++;                         // 移动指针
    if(USRP >= USBMax)
    {
        USRP = 0;  
    }
    USNum--;                        
    return TRUE;                    // 成功
}
//=============================================================================
// KEIL printf 接口部分
//=============================================================================
char putchar (char chr)  
{
    // 如果发送缓冲区满 则直到发送成功才退出
    while(USQWrite(chr) == FALSE);
    return (chr);
}

char _getkey ()  
{
    char Data;
    // 如果接收缓冲区空 直到接收成功才退出
    while(URQRead((U8*)&Data) == FALSE);
    return Data;
}


//=============================================================================
// 用户界面部分
//=============================================================================

// 串口发送字符
void UART_SendChar(U8 chr)
{
    // 如果发送缓冲区满 则直到发送成功才退出
    while(USQWrite(chr) == FALSE);
}
// 串口发送字符串
void UART_SendString(U8 *str)
{
    while(*str)
    {
        UART_SendChar(*str++);
    }
}

// 从串口接收字符 阻塞
U8  UART_RecvChar(void)
{
    U8 Data;
    // 如果接收缓冲区空 直到接收成功才退出
   
    if(URQRead(&Data) == FALSE);
    return Data;
}

// 从串口接收字符 非阻塞
U8  UART_RecvChar_N(U8 *Data)
{
    return URQRead(Data);
}

// 串口初始化
void UartInit(void)               
{
        PCON &= 0x7f;       // 波特率不倍速
        SCON  = 0x50;       // 8位数据,可变波特率
        BRT   = 0xFA;       // 设定独立波特率发生器重装值  //115200bps@22.1184MHz
        AUXR |= 0x04;       // 独立波特率发生器时钟为Fosc,即1T
        AUXR |= 0x01;       // 串口1选择独立波特率发生器为波特率发生器
        AUXR |= 0x10;       // 启动独立波特率发生器

    TI = 0;             // 清零串口发送完成中断请求标志
    ES = 1;             // 允许串口中断
    EA = 1;             // 开总中断
    NoCall_Uart();      // 屏蔽51编译器未调用函数警告
}

//=============================================================================
// 串口中断部分
//=============================================================================
// 串口中断
void UART_Interrupt_Receive(void) interrupt 4
{
    U8 Data;
    if(RI==1)
    {
        RI = 0;                     
        Data = SBUF;                // 接收串口数据
        URQWrite(Data);             // 接收到的数据如队列
#if USER_CMD_EN != 0
        CmpCmd(Data);               // 解析用户调试命令
#endif
    }
    if(TI == 1)
    {
        TI = 0;
        if(USQRead(&Data) == TRUE)  // 如果获取数据成功
        {
            SBUF = Data;            // 发送数据
                SendFlag = 1;           // 置发送状态
        }else{
            SendFlag = 0;           // 不在发送状态
        }
    }
}

//=============================================================================



//=============================================================================
// 本函数是为了屏蔽51编译器未调用函数警告
// 帮助51编译器做覆盖分析 从而节约RAM 及 ROM
// 实际不起任何作用 也没有任何函数被调用
//=============================================================================
void NoCall_Uart(void)
{
    U8 i;
    i=0;
    if(i)
    {
        // Uart.c
        // KEIL printf 接口部分
        putchar(0);  
        _getkey ();
        // 串口发送字符
        UART_SendChar(0);
        // 串口发送字符串
        UART_SendString((U8 *)0);
        // 从串口接收字符 阻塞
        UART_RecvChar();
        // 从串口接收字符 非阻塞
        UART_RecvChar_N((U8 *)0);
    }
}
//=============================================================================


//=============================================================================
// 调试命令解析部分
//=============================================================================
// 本调试命令在确认命令前不影响正常的串口数据的收发,
// 串口助手发送数据选用16进制发送, 命令长度为5个字节
// 用户调试命令发送格式: 55 AA 5A A5 00
//                       其中前4字节为命令识别码,
//                       最后1字节为命令码
//=============================================================================
#if USER_CMD_EN != 0

static code U8 CmdCheck[4] = {0x55,0xaa,0x5a,0xa5};

static code U8 CMD00[] = " 立即重新启动系统! ";
static code U8 CMD01[] = " 2秒后重新启动系统! ";
static code U8 CMD02[] = " 编译时间:" __DATE__ " " __TIME__ " ";
static code U8 CMDxx[] = " 未定义命令 ";

static void DlyMs(U16 t)        //@22.1184MHz
{
    U8 i, j;
   
    if(t == 0)return;
    do{
        i = 22;
        j = 128;
        do{
            while (--j);
        } while (--i);
    }while(--t);
}

// 调试命令检测函数
U8 CmpCmd(U8 chr)
{
    static U8 cnt=0;
    U8 *p;
    if(cnt >= 4)    //
    {
        switch(chr)
        {
        case 0:     // 复位系统
            p = CMD00;
            while(*p)       // 发送提示信息
            {
                if(SendFlag == 1)while(TI == 0);
                SBUF = *p++;
                while(TI == 0);
                TI = 0;
            }
            IAP_CONTR = 0x60;   // 复位系统
            break;
        case 1:     // 复位系统
            p = CMD01;
            while(*p)       // 发送提示信息
            {
                if(SendFlag == 1)while(TI == 0);
                SBUF = *p++;
                while(TI == 0);
                TI = 0;
            }
            DlyMs(2000);
            IAP_CONTR = 0x60;   // 复位系统
            break;
        case 2:     // 发送编译时间
            p = CMD02;
            while(*p)      // 发送提示信息
            {
                if(SendFlag == 1)while(TI == 0);
                SBUF = *p++;
                while(TI == 0);
                TI = 0;
            }
            break;
        //case 3:     // 用户可以添加自己的命令
        //    break;
        default:           // 未定义命令
            p = CMDxx;
            while(*p)      // 发送提示信息
            {
                if(SendFlag == 1)while(TI == 0);
                SBUF = *p++;
                while(TI == 0);
                TI = 0;
            }
            break;
        }
        cnt=0;
    }

    if(chr == CmdCheck[cnt])
    {
        cnt++;
    }else{
        cnt=0;
    }
    return 0;
}
#endif      // end of USER_CMD_EN
//=============================================================================
冰冷的游客
6楼-- · 2019-08-02 11:13
冰冷的游客 发表于 2014-7-2 15:59
缓冲区80,数据长度13

你这没有关于接收到数据的处理啊,这是我接收到的一串数据00 00 83 ff ff ff ff 02 81 00 00 83 ff 00 c0 00 ff ff 20 81 但是我就要ff ff ff ff 02 81 00 00 83这段,我的协议是四个ff开头,83是校验位

一周热门 更多>