arduino can总线实验,开源调试软件的串口数据包协议。

24 篇文章 0 订阅
24 篇文章 1 订阅

看了

分享一个自己写的串口数据分析、图形显示软件 can debugger 串口调试助手 免费,功能强大!

http://blog.csdn.net/lanmanck/article/details/50787536

这个帖子,感觉can协议可视化串口调试很赞!前辈的软件开发肯定付出了很多辛勤的汗水。

于是就研究了下软件开源的串口数据包协议。

官网地址:

http://www.labisart.com/

下面代码移植到 arduino可以运行, 本着开源精神,需要可视化调试的同学可以拿走。

// demo: CAN-BUS Shield, receive data
#include <mcp_can.h>
#include <SPI.h>
MCP_CAN CAN0(10);                               // Set CS to pin 10

/* CAN message object structure */
typedef struct {
  uint32_t id; /* 29 bit identifier */
  //uint8_t id[4];
  uint8_t data[8]; /* Data field */
  uint8_t len; /* Length of data field in bytes */
  uint8_t ch; /* Object channel */
  uint8_t format; /* CAN_FORMAT,0 - STANDARD, 1- EXTENDED IDENTIFIER*/
  uint8_t type; /* CAN_FRAME,0 - DATA FRAME, 1 - REMOTE FRAME */
} CAN_msg ;
#define MSG_CH_CAN 0
#define MSG_CH_UART 0x35


/* Symbolic names for formats of CAN message */
typedef enum {STANDARD_FORMAT = 0, EXTENDED_FORMAT} CAN_FORMAT;
/* Symbolic names for type of CAN message */
typedef enum {DATA_FRAME = 0, REMOTE_FRAME} CAN_FRAME;
/* 把can数据包发送到uart
 * @bufsize:<=8
 */
int uart_send_canbuf(uint32_t id, void *buf, uint8_t bufsize)
{
  int i, idx = 2;
  uint8_t can_buf[32], temp, crc = 0, *pbuf = (uint8_t*)buf;
  /* head */
  can_buf[0] = 0xaa;
  can_buf[1] = 0xaa;
  /* ext id */
  id &= 0x3FFFFFFF;
  for (i = 0; i < 4; i++) {
    temp = (id >> (i * 8)) & 0xFF;
    if (temp == 0x55 || temp == 0xAA) {
      can_buf[idx++] = 0xa5;
    }
    can_buf[idx++] = temp;
    crc += temp;
  }
  /* crc in data[8] */
  for (i = 0; i < bufsize; i++) {
    if (pbuf[i] == 0x55 || pbuf[i] == 0xAA) {
      can_buf[idx++] = 0xa5;
    }
    can_buf[idx++] = pbuf[i];
    crc += pbuf[i];
  }
  for (; i < 8; i++) {
    can_buf[idx++] = 0;
  }
  /* len/formatpe */
  can_buf[idx++] = bufsize;
  can_buf[idx++] = MSG_CH_UART; /* ch=0 */
  can_buf[idx++] = EXTENDED_FORMAT; /*EXTENDED_FORMAT*/
  can_buf[idx++] = DATA_FRAME;

  /* crc more */
  for (i = 0; i < 4; i++) {
    crc += can_buf[idx - 4 + i];
  }
  can_buf[idx++] = crc;
  /* tail */
  can_buf[idx++] = 0x55;
  can_buf[idx++] = 0x55;
  /* to uart */
  i = 0;
  while (i < idx) {
    //while(UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
    //UART1_SendData8(can_buf[i++]);
    Serial.write(can_buf[i++]);
  }
  return 0;
}
#define CAN_PKT_SIZE 21
#define MAX_CAN_PARSE_BUF_LEN 32
static uint8_t g_can_frame[MAX_CAN_PARSE_BUF_LEN];
enum frame_sync_e {
  FS_FIND_AA1,
  FS_FIND_AA2,
  FS_FIND_DATA,
  FS_FIND_CRC, /* 未使用 */
  FS_FIND_551,
  FS_FIND_552
};
/* 从串口接收数据后调用本函数,并组包成can_msg */
CAN_msg *pmsg;
static uint8_t last_byte = 0, frame_idx = 0;
static enum frame_sync_e sync_state = FS_FIND_AA1;
//*
void uart_rec_canmsg(uint8_t data) {
  uint8_t cur_byte;
  //static uint8_t last_byte = 0, frame_idx = 0;
  //static enum frame_sync_e sync_state = FS_FIND_AA1;
  // 超时复位状态机操作,可根据实际情况删除
  //if (GET_DIFF_TICK(pudat->last_tick) > 250) {
  //  sync_state = FS_FIND_AA1;
  //  frame_idx = 0;
  //}
  cur_byte = data;

  if (sync_state == FS_FIND_AA1) {
    if (cur_byte == 0xAA) {
      sync_state = FS_FIND_AA2;
      frame_idx = 0;
      g_can_frame[frame_idx++] = cur_byte;
    }
  } else if (sync_state == FS_FIND_AA2) {
    if (cur_byte == 0xAA) {
      sync_state = FS_FIND_DATA;
      g_can_frame[frame_idx++] = cur_byte;
    } else {
      sync_state = FS_FIND_AA1;
    }
  }// 删除插入的A5数据//zzz A5什么数据??
  else if (sync_state == FS_FIND_DATA) {
    //0x55 0xaa解析问题!!!!!!!!!!
    //CAN_msg结构内出现 55 aa就会出错。
    /*if ( (cur_byte == 0x55 || cur_byte == 0xAA) && frame_idx != (CAN_PKT_SIZE - 3))
    {
      if (last_byte == 0xa5) {
        g_can_frame[frame_idx - 1] = cur_byte;
      }
      else {
        sync_state = FS_FIND_AA1;
        frame_idx = 0;
      }
    }
    else {
      g_can_frame[frame_idx++] = 0xff;//cur_byte;//zzz test
      if (frame_idx == (CAN_PKT_SIZE - 3)) {
        sync_state = FS_FIND_CRC;
      }
    }*/
    g_can_frame[frame_idx++] = cur_byte;
    if (frame_idx == (CAN_PKT_SIZE - 3)) {
        sync_state = FS_FIND_CRC;
    }
  }// CRC不加A5
  else if (sync_state == FS_FIND_CRC) {
    g_can_frame[frame_idx++] = cur_byte;
    // check crc
    sync_state = FS_FIND_551;
  }// 尾巴
  else if (sync_state == FS_FIND_551) {
    if (cur_byte == 0x55) {
      g_can_frame[frame_idx++] = cur_byte;
      sync_state = FS_FIND_552;
    } else
      sync_state = FS_FIND_AA1;
  } else if (sync_state == FS_FIND_552) {
    sync_state = FS_FIND_AA1;
    if (cur_byte == 0x55) {
      g_can_frame[frame_idx] = cur_byte;
      pmsg = (CAN_msg*)&g_can_frame[2];
      pmsg->ch = MSG_CH_UART; //视情况自己定义
      // 存入缓冲区待使用
      //memcpy(&g_uart_dat.msg_rcv, pmsg, sizeof(CAN_msg));
      // send data:  id = 0x00, standrad flame, data len = 8, stmp: data buf
      //CAN0.sendMsgBuf(0x00, 0, 8, stmp);
        CAN0.sendMsgBuf(pmsg->id, 0, 8, pmsg->data);
      //check test
        uart_send_canbuf(pmsg->id, pmsg->data, 8);
    }
  }
  last_byte = cur_byte;
  //pudat->last_tick = get_timer_tick();
};
//*/
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];




void setup()
{
  Serial.begin(115200);
  CAN0.begin(CAN_500KBPS);                       // init can bus : baudrate = 500k
  pinMode(2, INPUT);                            // Setting pin 2 for /INT input
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  if (!digitalRead(2))                        // If pin 2 is low, read receive buffer
  {
    CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)
    rxId = CAN0.getCanId();                    // Get message ID
    /* Serial.print("ID: ");
     Serial.print(rxId, HEX);
     Serial.print("  Data: ");
     for(int i = 0; i<len; i++)                // Print each byte of the data
     {
       if(rxBuf[i] < 0x10)                     // If data byte is less than 0x10, add a leading zero
       {
         Serial.print("0");
       }
       Serial.print(rxBuf[i], HEX);
       Serial.print(" ");
     }
     Serial.println();*/

    uart_send_canbuf(rxId, rxBuf, len);
  }
  while (Serial.available() > 0) {
    byte comchar = Serial.read();//读串口第一个字节
    uart_rec_canmsg(comchar);
  }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/






评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值