看了
分享一个自己写的串口数据分析、图形显示软件 can debugger 串口调试助手 免费,功能强大!
http://blog.csdn.net/lanmanck/article/details/50787536
这个帖子,感觉can协议可视化串口调试很赞!前辈的软件开发肯定付出了很多辛勤的汗水。
于是就研究了下软件开源的串口数据包协议。
官网地址:
下面代码移植到 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
*********************************************************************************************************/