中文參考 http://blog.csdn.net/yuanlulu/article/details/7220060
控制器區域網路 (Controller Area Network, 簡稱 CAN 或 CANbus)
一種通訊協定,主要應用在汽車、工控領域。
目前版本CAN 2.0A與CAN 2.0B ,B是A的擴充。2.0B 的ID長度占29bit, 2.0A 的ID長度占11bit
節點架構
CAN Controller 通常內建於MCU內(也有獨立的ex: SJA1000),會在外接Transceiver(ex:ISO1050)轉成類比訊號。
CAN封包格式
寫基本的CAN,只需要注意仲裁欄位、控制欄位、資料欄位
Field name | Length (bits) | Purpose |
---|---|---|
Start-of-frame | 1 | Denotes the start of frame transmission |
Identifier (green) | 11 | A (unique) identifier which also represents the message priority |
Remote transmission request (RTR) | 1 | Must be dominant (0) for data frames and recessive (1) for remote request frames (see Remote Frame, below) |
Identifier extension bit (IDE) | 1 | Must be dominant (0) for base frame format with 11-bit identifiers |
Reserved bit (r0) | 1 | Reserved bit. Must be dominant (0), but accepted as either dominant or recessive. |
Data length code (DLC) (yellow) | 4 | Number of bytes of data (0–8 bytes)[a] |
Data field (red) | 0–64 (0-8 bytes) | Data to be transmitted (length in bytes dictated by DLC field) |
CRC | 15 | Cyclic redundancy check |
CRC delimiter | 1 | Must be recessive (1) |
ACK slot | 1 | Transmitter sends recessive (1) and any receiver can assert a dominant (0) |
ACK delimiter | 1 | Must be recessive (1) |
End-of-frame (EOF) | 7 | Must be recessive (1) |
CAN BUS的操作可以如同使用SOCKET。
參考Linux下範例 candsend.c candump.c
看完除了會can 的發送與接收,也可以學到命令列參數使用方法 (function: getopt_long)
以下簡單範例:
Setting :
struct can_frame frame; struct ifreq ifr; struct sockaddr_can addr; char *interface = "can0"; int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW; s = socket(family, type, proto) strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFINDEX, &ifr)) { perror("CAN ioctl"); return 1; } addr.can_family = family; addr.can_ifindex = ifr.ifr_ifindex; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("CAN bind"); return 1; }Send :
//sendcanbus(); frame.can_id = 0x0321; frame.can_dlc = 4; frame.data[0] = 0; frame.data[1] = 1; frame.data[2] = 2; frame.data[3] = 3; ret = send(s,&frame,sizeof(frame),0);Read :
//dropt the timeout packets while(nbytes = recvfrom(s,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,&len)>=0) { printf("\r\nrecvfrom nbytes %d",nbytes); memcpy(b,&frame,sizeof(frame)); for (i=0 ; i < sizeof(struct can_frame) ; i++) { printf(" 0x%x ",b[i]); } usleep(10000);// }