文章目录
- Linux Shell操作
- 查询CAN信息
- 开启/关闭CAN
- 发送/接收CAN数据
- 设置CAN参数
- 虚拟VCAN
- Linux CAN编程
- 主要头文件
- CAN重要数据结构
- struct ifreq
- struct sockaddr_can
- struct can_filter
- struct can_frame
- CAN的协议域
- socket()函数对应的参数
- Socket的协议域
- Socket的网络类型
- Socket协议
- Socket的IOCTL
- CAN编码流程
- 示例代码
Linux Shell操作
查询CAN信息
- ip -details link show can0
查询CAN的详细信息,包括波特率、标志设置等信息
- ip -details -statistics link show can0
查询CAN的工作状态
- ifconfig -a
查询CAN的收发数据包情况,以及中断号
- dmesg | grep “can”
查询CAN的详细物理信息,包括电压、寄存器、中断等
开启/关闭CAN
- ifconfig can0 down
关闭CAN
- ifconfig can0 up
打开CAN
- ip link set can0 up type can
打开CAN网络
- ip link set can0 down
关闭CAN 网络
发送/接收CAN数据
- cansend can0 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
发送默认ID为0x1的can标准帧,数据为0x11 22 33 44 55 66 77 88每次最大8个byte
- cansend can0 -i 0x800 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 -e
-e 表示扩展帧,CAN_ID最大29bit,标准帧CAN_ID最大11bit -i表示CAN_ID
- cansend can0 -i 0x02 0x11 0x12 --loop=20
–loop 表示发送20个包
- candump can0
接收数据
- cansend can0 123#1122334455667788
设置CAN参数
- ip link set can0 type can --help
can参数设置详解
- ip link set can0 up type can bitrate 800000
设置can0的波特率为800kbps,CAN网络波特率最大值为1Mbps
- ip link set can0 up type can bitrate 800000 loopback on
设置回环模式,自发自收,用于测试是硬件是否正常,loopback不一定支持
- List item
虚拟VCAN
- sudo modprobe vcan
加载虚拟can模块
- sudo ip link add dev vcan0 type vcan
添加vcan0网卡
Linux CAN编程
主要头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
CAN重要数据结构
struct ifreq irq;
struct sockaddr_can canAddr;
struct can_filter canFilter;
struct can_frame canFrame;
struct ifreq
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct if_settings {
unsigned int type;
unsigned int size;
union {
raw_hdlc_proto __user *raw_hdlc;
cisco_proto __user *cisco;
fr_proto __user *fr;
fr_proto_pvc __user *fr_pvc;
fr_proto_pvc_info __user *fr_pvc_info;
sync_serial_settings __user *sync;
te1_settings __user *te1;
} ifs_ifsu;
};
struct ifreq {
#define IFHWADDRLEN 6
union
{
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
void __user * ifru_data;
struct if_settings ifru_settings;
} ifr_ifru;
};
struct sockaddr_can
struct sockaddr_can {
__kernel_sa_family_t can_family;
int can_ifindex;
union {
struct { canid_t rx_id, tx_id; } tp;
} can_addr;
};
struct can_filter
struct can_filter {
canid_t can_id;
canid_t can_mask;
};
struct can_frame
struct can_frame {
canid_t can_id;
__u8 can_dlc;
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
CAN的协议域
#ifndef AF_CAN
#define AF_CAN 29
#define PF_CAN AF_CAN
#endif
#define CAN_RAW 1
#define CAN_BCM 2
#define CAN_TP16 3
#define CAN_TP20 4
#define CAN_MCNET 5
#define CAN_ISOTP 6
#define CAN_NPROTO 7
socket()函数对应的参数
Socket的协议域
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_LOCAL 1
#define AF_INET 2
#define AF_AX25 3
#define AF_IPX 4
#define AF_APPLETALK 5
#define AF_NETROM 6
#define AF_BRIDGE 7
#define AF_ATMPVC 8
#define AF_X25 9
#define AF_INET6 10
#define AF_ROSE 11
#define AF_DECnet 12
#define AF_NETBEUI 13
#define AF_SECURITY 14
#define AF_KEY 15
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK
#define AF_PACKET 17
#define AF_ASH 18
#define AF_ECONET 19
#define AF_ATMSVC 20
#define AF_RDS 21
#define AF_SNA 22
#define AF_IRDA 23
#define AF_PPPOX 24
#define AF_WANPIPE 25
#define AF_LLC 26
#define AF_IB 27
#define AF_MPLS 28
#define AF_CAN 29
#define AF_TIPC 30
#define AF_BLUETOOTH 31
#define AF_IUCV 32
#define AF_RXRPC 33
#define AF_ISDN 34
#define AF_PHONET 35
#define AF_IEEE802154 36
#define AF_CAIF 37
#define AF_ALG 38
#define AF_NFC 39
#define AF_VSOCK 40
#define AF_KCM 41
#define AF_QIPCRTR 42
#define AF_SMC 43
#define AF_XDP 44
#define AF_MAX 45
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_LOCAL AF_LOCAL
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
#define PF_APPLETALK AF_APPLETALK
#define PF_NETROM AF_NETROM
#define PF_BRIDGE AF_BRIDGE
#define PF_ATMPVC AF_ATMPVC
#define PF_X25 AF_X25
#define PF_INET6 AF_INET6
#define PF_ROSE AF_ROSE
#define PF_DECnet AF_DECnet
#define PF_NETBEUI AF_NETBEUI
#define PF_SECURITY AF_SECURITY
#define PF_KEY AF_KEY
#define PF_NETLINK AF_NETLINK
#define PF_ROUTE AF_ROUTE
#define PF_PACKET AF_PACKET
#define PF_ASH AF_ASH
#define PF_ECONET AF_ECONET
#define PF_ATMSVC AF_ATMSVC
#define PF_RDS AF_RDS
#define PF_SNA AF_SNA
#define PF_IRDA AF_IRDA
#define PF_PPPOX AF_PPPOX
#define PF_WANPIPE AF_WANPIPE
#define PF_LLC AF_LLC
#define PF_IB AF_IB
#define PF_MPLS AF_MPLS
#define PF_CAN AF_CAN
#define PF_TIPC AF_TIPC
#define PF_BLUETOOTH AF_BLUETOOTH
#define PF_IUCV AF_IUCV
#define PF_RXRPC AF_RXRPC
#define PF_ISDN AF_ISDN
#define PF_PHONET AF_PHONET
#define PF_IEEE802154 AF_IEEE802154
#define PF_CAIF AF_CAIF
#define PF_ALG AF_ALG
#define PF_NFC AF_NFC
#define PF_VSOCK AF_VSOCK
#define PF_KCM AF_KCM
#define PF_QIPCRTR AF_QIPCRTR
#define PF_SMC AF_SMC
#define PF_XDP AF_XDP
#define PF_MAX AF_MAX
Socket的网络类型
enum sock_type {
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
SOCK_DCCP = 6,
SOCK_PACKET = 10,
};在这里插入代码片
Socket协议
enum {
IPPROTO_IP = 0,
#define IPPROTO_IP IPPROTO_IP
IPPROTO_ICMP = 1,
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2,
#define IPPROTO_IGMP IPPROTO_IGMP
IPPROTO_IPIP = 4,
#define IPPROTO_IPIP IPPROTO_IPIP
IPPROTO_TCP = 6,
#define IPPROTO_TCP IPPROTO_TCP
IPPROTO_EGP = 8,
#define IPPROTO_EGP IPPROTO_EGP
IPPROTO_PUP = 12,
#define IPPROTO_PUP IPPROTO_PUP
IPPROTO_UDP = 17,
#define IPPROTO_UDP IPPROTO_UDP
IPPROTO_IDP = 22,
#define IPPROTO_IDP IPPROTO_IDP
IPPROTO_TP = 29,
#define IPPROTO_TP IPPROTO_TP
IPPROTO_DCCP = 33,
#define IPPROTO_DCCP IPPROTO_DCCP
IPPROTO_IPV6 = 41,
#define IPPROTO_IPV6 IPPROTO_IPV6
IPPROTO_RSVP = 46,
#define IPPROTO_RSVP IPPROTO_RSVP
IPPROTO_GRE = 47,
#define IPPROTO_GRE IPPROTO_GRE
IPPROTO_ESP = 50,
#define IPPROTO_ESP IPPROTO_ESP
IPPROTO_AH = 51,
#define IPPROTO_AH IPPROTO_AH
IPPROTO_MTP = 92,
#define IPPROTO_MTP IPPROTO_MTP
IPPROTO_BEETPH = 94,
#define IPPROTO_BEETPH IPPROTO_BEETPH
IPPROTO_ENCAP = 98,
#define IPPROTO_ENCAP IPPROTO_ENCAP
IPPROTO_PIM = 103,
#define IPPROTO_PIM IPPROTO_PIM
IPPROTO_COMP = 108,
#define IPPROTO_COMP IPPROTO_COMP
IPPROTO_SCTP = 132,
#define IPPROTO_SCTP IPPROTO_SCTP
IPPROTO_UDPLITE = 136,
#define IPPROTO_UDPLITE IPPROTO_UDPLITE
IPPROTO_MPLS = 137,
#define IPPROTO_MPLS IPPROTO_MPLS
IPPROTO_RAW = 255,
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MAX
};
Socket的IOCTL
#define SIOCINQ FIONREAD
#define SIOCOUTQ TIOCOUTQ
#define SOCK_IOC_TYPE 0x89
#define SIOCADDRT 0x890B
#define SIOCDELRT 0x890C
#define SIOCRTMSG 0x890D
#define SIOCGIFNAME 0x8910
#define SIOCSIFLINK 0x8911
#define SIOCGIFCONF 0x8912
#define SIOCGIFFLAGS 0x8913
#define SIOCSIFFLAGS 0x8914
#define SIOCGIFADDR 0x8915
#define SIOCSIFADDR 0x8916
#define SIOCGIFDSTADDR 0x8917
#define SIOCSIFDSTADDR 0x8918
#define SIOCGIFBRDADDR 0x8919
#define SIOCSIFBRDADDR 0x891a
#define SIOCGIFNETMASK 0x891b
#define SIOCSIFNETMASK 0x891c
#define SIOCGIFMETRIC 0x891d
#define SIOCSIFMETRIC 0x891e
#define SIOCGIFMEM 0x891f
#define SIOCSIFMEM 0x8920
#define SIOCGIFMTU 0x8921
#define SIOCSIFMTU 0x8922
#define SIOCSIFNAME 0x8923
#define SIOCSIFHWADDR 0x8924
#define SIOCGIFENCAP 0x8925
#define SIOCSIFENCAP 0x8926
#define SIOCGIFHWADDR 0x8927
#define SIOCGIFSLAVE 0x8929
#define SIOCSIFSLAVE 0x8930
#define SIOCADDMULTI 0x8931
#define SIOCDELMULTI 0x8932
#define SIOCGIFINDEX 0x8933
#define SIOGIFINDEX SIOCGIFINDEX
#define SIOCSIFPFLAGS 0x8934
#define SIOCGIFPFLAGS 0x8935
#define SIOCDIFADDR 0x8936
#define SIOCSIFHWBROADCAST 0x8937
#define SIOCGIFCOUNT 0x8938
#define SIOCGIFBR 0x8940
#define SIOCSIFBR 0x8941
#define SIOCGIFTXQLEN 0x8942
#define SIOCSIFTXQLEN 0x8943
#define SIOCETHTOOL 0x8946
#define SIOCGMIIPHY 0x8947
#define SIOCGMIIREG 0x8948
#define SIOCSMIIREG 0x8949
#define SIOCWANDEV 0x894A
#define SIOCOUTQNSD 0x894B
#define SIOCGSKNS 0x894C
#define SIOCDARP 0x8953
#define SIOCGARP 0x8954
#define SIOCSARP 0x8955
#define SIOCDRARP 0x8960
#define SIOCGRARP 0x8961
#define SIOCSRARP 0x8962
#define SIOCGIFMAP 0x8970
#define SIOCSIFMAP 0x8971
#define SIOCADDDLCI 0x8980
#define SIOCDELDLCI 0x8981
#define SIOCGIFVLAN 0x8982
#define SIOCSIFVLAN 0x8983
#define SIOCBONDENSLAVE 0x8990
#define SIOCBONDRELEASE 0x8991
#define SIOCBONDSETHWADDR 0x8992
#define SIOCBONDSLAVEINFOQUERY 0x8993
#define SIOCBONDINFOQUERY 0x8994
#define SIOCBONDCHANGEACTIVE 0x8995
#define SIOCBRADDBR 0x89a0
#define SIOCBRDELBR 0x89a1
#define SIOCBRADDIF 0x89a2
#define SIOCBRDELIF 0x89a3
#define SIOCSHWTSTAMP 0x89b0
#define SIOCGHWTSTAMP 0x89b1
#define SIOCDEVPRIVATE 0x89F0
#define SIOCPROTOPRIVATE 0x89E0
CAN编码流程
示例代码
int canSocket;
bool can_init()
{
int nRet;
int nFlags;
struct ifreq ifr;
struct sockaddr_can canAddr;
struct can_filter canFilter;
canSocket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (canSocket < 0) {
perror("create can socket failed");
return false;
}
nFlags = fcntl(canSocket, F_GETFL, 0);
fcntl(canSocket, F_SETFL, nFlags | O_NONBLOCK);
strcpy(ifr.ifr_name, (const char *)"can0");
nRet = ioctl(canSocket, SIOCGIFINDEX, &ifr);
if (nRet < 0) {
perror("ioctl can failed");
close(tcanSocket);
canSocket = 0;
return false;
}
canAddr.can_family = AF_CAN;
canAddr.can_ifindex = ifr.ifr_ifindex;
nRet = bind(canSocket, (struct sockaddr *)&canAddr, sizeof(canAddr));
if (nRet < 0) {
perror("bind can socket failed");
close(canSocket);
this->u8Socket = 0;
return false;
}
canFilter.can_id = filterID;
canFilter.can_mask = CAN_SFF_MASK;
nRet = setsockopt(canSocket, SOL_CAN_RAW, CAN_RAW_FILTER, &canFilter, sizeof(struct can_filter));
if (nRet < 0) {
perror("setsockopt failed");
return false;
}
return true;
}
ssize_t can_send(int ID, char *pData, char len)
{
ssize_t nBytes;
struct can_frame canSendFrame = {0};
if (u8Len > CAN_MAX_DLEN){
return -1;
}
canSendFrame.can_id = ID;
canSendFrame.can_dlc = 8;
memcpy(canSendFrame.data, pData, len);
nBytes = write(canSocket, &canSendFrame, sizeof(canSendFrame));
if (nBytes <= (sizeof(can_frame) - CAN_MAX_DLEN)) {
perror("can socket write failed");
return -1;
}
return (nBytes - (sizeof(can_frame) - CAN_MAX_DLEN));
}
ssize_t can_recv(char *pData)
{
ssize_t nBytes;
struct can_frame canRecvFrame = {0};
if (NULL == pData){
return -1;
}
nBytes = read(canSocket, &canRecvFrame, sizeof(can_frame));
if (nBytes < (sizeof(can_frame) - CAN_MAX_DLEN)) {
perror("can socket read failed");
return -1;
}
memcpy(pData, canRecvFrame.data, (nBytes - (sizeof(can_frame) - CAN_MAX_DLEN)));
return (nBytes - (sizeof(can_frame) - CAN_MAX_DLEN));
}
void can_exit()
{
close(canSocket);
}