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

2019-08-01 15:16发布

接收缓冲区接收到一串数据,但是只有其中的一帧4个ff开头 83结尾的数据才能用,我怎么才能把它截取出来
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
12条回答
dirtwillfly
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
//=============================================================================

一周热门 更多>