OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5283|回复: 13

如何在一串十六进制的数中取出帧头和帧尾之间的数据

[复制链接]

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
发表于 2017-8-9 15:54:34 | 显示全部楼层 |阅读模式
2金钱
只知道程序需要在中断里面写,但小白不知道怎么写,求大神们指点迷津,,,
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

29

主题

311

帖子

0

精华

高级会员

Rank: 4

积分
747
金钱
747
注册时间
2016-5-21
在线时间
199 小时
发表于 2017-8-9 18:23:41 | 显示全部楼层
第一步把冰箱门打开……。  
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-11 14:43:19 | 显示全部楼层
haysen 发表于 2017-8-9 18:23
第一步把冰箱门打开……。

BUF里面200个字节,如果帧头在200字节内,而帧尾在外,需要获取之间内容怎么编程???需要用到拼接,如何拼接??
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-11 14:44:47 | 显示全部楼层
haysen 发表于 2017-8-9 18:23
第一步把冰箱门打开……。

谢谢回复,麻烦在帮忙看下楼下的问题。。
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-11 14:45:20 | 显示全部楼层
yklstudent 发表于 2017-8-9 17:01
这个你定义好协议,按协议解析处理就可以了

谢谢回复,麻烦在帮忙看下楼下的问题。。
回复

使用道具 举报

32

主题

236

帖子

0

精华

高级会员

Rank: 4

积分
993
金钱
993
注册时间
2017-8-11
在线时间
137 小时
发表于 2017-8-11 15:05:22 | 显示全部楼层
你好,其实有大概有几种实行方案。
首先可以参考原子哥的串口中断函数。这个中断函数就是以0x0a,0x0d结束为标志进行判断的,
而接收的数据长度就是Rx1Len=USART_RX_STA&0x3fff;    //得到此次接收到的数据长度
用这个思路,你可以判断你的帧头和帧尾,然后得出数据长度,再写一个FOR循环,把第二位到Rx1Len-1的数据存起来,就是你要的
或者用添加标志位的办法,不过一般的协议都会有2个结束位的(一个校验,一个结束),连续连个字节才能更好判断一次发送结束
回复

使用道具 举报

16

主题

339

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2017-6-18
在线时间
164 小时
发表于 2017-8-11 15:28:36 来自手机 | 显示全部楼层
不能用原子的,大数据必须用串口中断流接收
回复

使用道具 举报

16

主题

339

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2017-6-18
在线时间
164 小时
发表于 2017-8-11 15:29:11 来自手机 | 显示全部楼层
简称串口流传输
回复

使用道具 举报

16

主题

339

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2017-6-18
在线时间
164 小时
发表于 2017-8-11 15:49:06 | 显示全部楼层
串口 流的 不同,与意义:;
串口流只在取发数据的一瞬间激活,不会影响系统的操作,取发数据的一瞬间只占几时钟周期, 可以认为其不存在
回复

使用道具 举报

16

主题

339

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2017-6-18
在线时间
164 小时
发表于 2017-8-11 15:49:30 | 显示全部楼层
/*
   serial.c - 低级功能用于通过串行端口发送和接收字节
   Grbl的一部分
*/
#include "avr/io.h"
#include <avr/interrupt.h>
#include "serial.h"
#include "config.h"
#include "motion_control.h"
#include "protocol.h"


uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t rx_buffer_head = 0;
uint8_t rx_buffer_tail = 0;

uint8_t tx_buffer[TX_BUFFER_SIZE];
uint8_t tx_buffer_head = 0;
volatile uint8_t tx_buffer_tail = 0;


/**************************************************************************************************/  
#ifdef ENABLE_XONXOFF                          //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
  volatile uint8_t flow_ctrl = XON_SENT;       //流控制状态变量
/*************************************************/
//***RX缓冲区 字节返回 函数***//
  
  static uint8_t get_rx_buffer_count(void)
      {
      if (rx_buffer_head == rx_buffer_tail) { return(0); }                               //头 = 尾, 返回  0;
      if (rx_buffer_head < rx_buffer_tail) { return(rx_buffer_tail-rx_buffer_head); }    //头 < 尾, 返回  尾 - 头
      return (RX_BUFFER_SIZE - (rx_buffer_head-rx_buffer_tail));                         //头 > 尾, 返回  头 - 尾
      }
#endif
/**************************************************************************************************/
//***串口 初始化***//  //默认为8位,无奇偶校验,1位停止位

void serial_init(void)
    {
    //设置波特率
    #if BAUD_RATE < 57600
    uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2;
    UCSR0A &= ~(1 << U2X0); // 波特率倍频器关 - 仅在Uno XXX上需要
    #else
    uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
    UCSR0A |= (1 << U2X0);  //波特率为高波特率,即115200
    #endif
    UBRR0H = UBRR0_value >> 8;UBRR0L = UBRR0_value;
   
    UCSR0B |= 1<<4;          //RXEN0 = 1; 接收使能
    UCSR0B |= 1<<3;          //TXEN0 = 1; 发送使能
   
    UCSR0B |= 1<<7;          //RXCIE0 = 1; 接收结束中断使能  
   
    UCSR0C |= 3<<1;          //UCSZ0 = 3(11); 8bit数据模式
    }
/**************************************************************************************************/
//***串口 发送***//

void serial_write(uint8_t data)
    {
    uint8_t next_head = tx_buffer_head + 1;             //把tx_buffer_head 加1后放入 next_head 临时头指针

    if (next_head == TX_BUFFER_SIZE){next_head = 0;}    //next_head 循环流结构

    while (next_head == tx_buffer_tail)             //由于 next_head = txbuffer_head +1; 所以只有 在缓冲区中的数未发完时, 才有可能等于tx_buffer_tail, 故等待缓冲区空了才能发;
        {
        if (sys.execute & EXEC_RESET) return;       //如果sys 变量中有 RESET 标志,直接跳出,响应复位;
        }
    tx_buffer[tx_buffer_head] = data;               //数据 放入 tx_buffer 缓冲流
    tx_buffer_head = next_head;                     //更新 tx_buffer_head 头指针位置

    UCSR0B |=  (1 << UDRIE0);                       //使能数据寄存器空中断, 让发送缓冲区 TX流 自动发送;
    }  
/**************************************************************************************************/
//***数据寄存器空 中断***//

#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega2560__)
ISR(USART0_UDRE_vect)
#else
ISR(USART_UDRE_vect)
#endif
    {
    uint8_t tail = tx_buffer_tail;       //TX流 临时尾指针
   
#ifdef ENABLE_XONXOFF                   //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
    if (flow_ctrl == SEND_XOFF)
        {
        UDR0 = XOFF_CHAR;
        flow_ctrl = XOFF_SENT;
        }
    else if (flow_ctrl == SEND_XON)
            {
            UDR0 = XON_CHAR;
            flow_ctrl = XON_SENT;
            }
        else
#endif
            {
            UDR0 = tx_buffer[tail];                           //从缓冲区发送一个字节
            
            tail++;                                           //更新尾部位置
            if (tail == TX_BUFFER_SIZE){tail = 0;}            //TX流尾指针循环流
            
            tx_buffer_tail = tail;                            //TX流尾指针写入tx_buffer_tail;
            }
               
    if (tail == tx_buffer_head){UCSR0B &= ~(1 << UDRIE0);}    //如果结束传输,关闭数据寄存器空中断停止tx流, 注: 此时tx_buffer_head = tx_buffer_tail;
    }
/*---------------------------------------------------------------------------------------------------------------------------------*/
//***串口 接收***//

uint8_t serial_read(void)
    {
//    if(seral_Enable_FLAG)
//        { return SERIAL_NO_DATA; }
//    else
//        {
    if (rx_buffer_head == rx_buffer_tail){return SERIAL_NO_DATA;}    //RX_头=尾; 跳出返回没有收到数据
    else
        {
        uint8_t data = rx_buffer[rx_buffer_tail];                   //从rx_buffer 缓冲区中获取数据
        
        rx_buffer_tail++;
        if (rx_buffer_tail == RX_BUFFER_SIZE) rx_buffer_tail = 0;   //rx_buffer_tail 尾指针循环流
        
#ifdef ENABLE_XONXOFF                  //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
        if ((get_rx_buffer_count() < RX_BUFFER_LOW) && flow_ctrl == XOFF_SENT)
            {
            flow_ctrl = SEND_XON;
            UCSR0B |=  (1 << UDRIE0); // Force TX
            }
#endif  
        return data;
        }
//        }
    }
/**************************************************************************************************/
//***串口 接收中断***//

#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega2560__)
ISR(USART0_RX_vect)
#else
ISR(USART_RX_vect)
#endif
    {
    uint8_t data = UDR0;             //从 串口0 数据寄存器 取出数据, 放入data;
    uint8_t next_head;

    switch (data)             //直接从串行流中取出运行时命令字符。 这些字符不会传入缓冲区,但是这些字符串用于运行时执行。
        {
        case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; //设为true
        case CMD_CYCLE_START:   sys.execute |= EXEC_CYCLE_START; break; //设为true
        case CMD_FEED_HOLD:     sys.execute |= EXEC_FEED_HOLD; break; //设为true
        case CMD_RESET:         mc_reset(); break; //调用运动控制复位程序。
        default: //将字符写入缓冲区
            {
            next_head = rx_buffer_head + 1;
            if (next_head == RX_BUFFER_SIZE){next_head = 0;}   //next_head 指针循环结构

            if (next_head != rx_buffer_tail)             //如果数据rx_buffer缓冲区满,将不写入缓冲区 //rx_buffer_head 头部指针也不会动
                {
                rx_buffer[rx_buffer_head] = data;
                rx_buffer_head = next_head;
               
#ifdef ENABLE_XONXOFF                    //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
                if ((get_rx_buffer_count() >= RX_BUFFER_FULL) && flow_ctrl == XON_SENT)
                    {
                    flow_ctrl = SEND_XOFF;
                    UCSR0B |=  (1 << UDRIE0); //强制TX
                    }
#endif
                }
            }
        }
    }
/**************************************************************************************************/
//***重置 读串口缓冲区指针***//

void serial_reset_read_buffer(void)
    {
    rx_buffer_tail = rx_buffer_head;         //尾 = 头的当前位置
   
#ifdef ENABLE_XONXOFF                    //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
    flow_ctrl = XON_SENT;
#endif
    }
/**************************************************************************************************/


回复

使用道具 举报

16

主题

339

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2017-6-18
在线时间
164 小时
发表于 2017-8-11 15:49:45 | 显示全部楼层
/*
   serial.c - 低级功能用于通过串行端口发送和接收字节
   Grbl的一部分
*/
#ifndef __serial_h_
#define __serial_h_

#include "nuts_bolts.h"


/*********************************************************************************************************************************/
#ifndef RX_BUFFER_SIZE
  #define RX_BUFFER_SIZE 128
#endif
#ifndef TX_BUFFER_SIZE
  #define TX_BUFFER_SIZE 64
#endif

#define SERIAL_NO_DATA 0xff
/*********************************************************************************************************************************/
#ifdef ENABLE_XONXOFF             //默认 ENABLE_XONXOFF = 0;      内部将不进行编译
  #define RX_BUFFER_FULL 96 // XOFF high watermark
  #define RX_BUFFER_LOW 64 // XON low watermark
  #define SEND_XOFF 1
  #define SEND_XON 2
  #define XOFF_SENT 3
  #define XON_SENT 4
  #define XOFF_CHAR 0x13
  #define XON_CHAR 0x11
#endif
/*********************************************************************************************************************************/
void                             serial_init                 (void);

void                             serial_write                (uint8_t data);

uint8_t                          serial_read                 (void);

void                             serial_reset_read_buffer    (void);               //读缓冲区 头 尾 指针复位,读数据区也随之清空; 用于e-stop和reset。
/*********************************************************************************************************************************/




#endif


回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-12 09:49:32 | 显示全部楼层
笨鸟想飞 发表于 2017-8-11 15:05
你好,其实有大概有几种实行方案。
首先可以参考原子哥的串口中断函数。这个中断函数就是以0x0a,0x0d结束 ...

你好 感谢回复,,不过还是不太明白一串数据大于200个字节的时候帧尾在外时如何判断,如何拼接,如何读取帧头帧尾之间的数。。。 。 在中断中已经解决在200字节数据内接收帧头帧尾的程序,,,
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-12 09:50:59 | 显示全部楼层
wlq19911021 发表于 2017-8-11 15:49
/*
   serial.c - 低级功能用于通过串行端口发送和接收字节
   Grbl的一部分

你好 感谢回复,,不过还是不太明白一串数据大于200个字节的时候帧尾在外时如何判断,如何拼接,如何读取帧头帧尾之间的数。。。 。 在中断中已经解决在200字节数据内接收帧头帧尾的程序,,,
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2017-7-28
在线时间
6 小时
 楼主| 发表于 2017-8-14 14:59:38 | 显示全部楼层
问题已解决,感谢各位
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-20 16:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表