打印

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

[复制链接]
1421|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
冰冷的游客|  楼主 | 2014-7-2 15:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
电子缘科技| | 2014-7-2 15:13 | 只看该作者
判断数据,比如你的缓冲区有100位置,然后你就进行从0开始往上循环检测,只要检测到4个ff开头 83结尾的数据就开始放到另外一个缓冲区,这样就提取出来了,如果在这个过程中没有收到这个数据,你就不提取

使用特权

评论回复
板凳
冰冷的游客|  楼主 | 2014-7-2 15:48 | 只看该作者
电子缘科技 发表于 2014-7-2 15:13
判断数据,比如你的缓冲区有100位置,然后你就进行从0开始往上循环检测,只要检测到4个ff开头 83结尾的数据 ...

刚接触C不久,能给个具体的代码吗,或者用什么函数实现,谢谢

使用特权

评论回复
地板
电子缘科技| | 2014-7-2 15:53 | 只看该作者
你的缓冲区有多大?然后你要接受的数据有多长?这些都要知道才可以帮你想算法

使用特权

评论回复
5
冰冷的游客|  楼主 | 2014-7-2 15:59 | 只看该作者
电子缘科技 发表于 2014-7-2 15:53
你的缓冲区有多大?然后你要接受的数据有多长?这些都要知道才可以帮你想算法 ...

缓冲区80,数据长度13

使用特权

评论回复
6
dirtwillfly| | 2014-7-2 22:26 | 只看该作者
一个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[] = "\r\n立即重新启动系统!\r\n";
static code U8 CMD01[] = "\r\n2秒后重新启动系统!\r\n";
static code U8 CMD02[] = "\r\n编译时间:" __DATE__ " " __TIME__ "\r\n";
static code U8 CMDxx[] = "\r\n未定义命令\r\n";

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
//=============================================================================

使用特权

评论回复
7
冰冷的游客|  楼主 | 2014-7-3 08:52 | 只看该作者
冰冷的游客 发表于 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是校验位

使用特权

评论回复
8
冰冷的游客|  楼主 | 2014-7-3 08:53 | 只看该作者
dirtwillfly 发表于 2014-7-2 22:26
一个51检测串口字符串命令的代码,你参考下吧:
// 调试命令检测函数
U8 CmpCmd(U8 chr);

你这没有关于接收到数据的处理啊,这是我接收到的一串数据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是校验位

使用特权

评论回复
9
dirtwillfly| | 2014-7-3 09:14 | 只看该作者
冰冷的游客 发表于 2014-7-3 08:53
你这没有关于接收到数据的处理啊,这是我接收到的一串数据00 00 83 ff ff ff ff 02 81 00 00 83 ff 00 c0 ...

所以我说是参考啊

使用特权

评论回复
10
冰冷的游客|  楼主 | 2014-7-3 09:21 | 只看该作者
dirtwillfly 发表于 2014-7-3 09:14
所以我说是参考啊

谢谢

使用特权

评论回复
11
电子缘科技| | 2014-7-4 10:38 | 只看该作者

还没搞定呀?给你写一个吧,你试下

unsigned char Rdata[80];//接收缓冲区
unsigned char data[9];//需要数据缓冲----数了一下你的数据长度是9,具体多少你自己改下

unsigned char cnt,rcnt;//变量

for(cnt=0; cnt<80; cnt++)
{
        if((Rdata[cnt]==0xff) && (Rdata[cnt+1]==0xff) && (Rdata[cnt+2]==0xff) && (Rdata[cnt+3]==0xff) && (Rdata[cnt+8]==0x83))//符合协议条件,接收数据
        {
                for(rcnt=0; rcnt<9; rcnt++)
                {
                        data[rcnt] = Rdata[cnt];//从符合条件的cnt开始复制数据到data数组
                        cnt ++;                               
                }
                break;//接收完成退出
        }
}

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
冰冷的游客 + 1 很给力!
12
i1mcu| | 2014-7-4 14:45 | 只看该作者
读取帧头贞尾

使用特权

评论回复
13
i1mcu| | 2014-7-4 14:46 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

75

帖子

0

粉丝