建立can的socket
int can_create_socket(char *name)
{
int fd;
struct sockaddr_can addr;
struct ifreq ifr;
socklen_t len = sizeof(addr);
/*
* RAW protocol sockets with can filters(SOCK_RAW)
* Broadcast Manager protocol sockets(SOCK_DGRAM)
*/
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
// fd = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
if(fd < 0) return -1;
strcpy(ifr.ifr_name, name );
ioctl(fd, SIOCGIFINDEX, &ifr);
/* 非阻塞 */
// int flags = fcntl(fd, F_GETFL, 0);
// fcntl(fd, F_SETFL, flags |O_NONBLOCK);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind(fd, (struct sockaddr *)&addr, len);
return fd;
}
设置can的波特率
void can1_baudrate_set(int bitrate)
{
system("ip link set can1 down");
if(bitrate == CAN_50K_BAUDRATE){
system("ip link set can1 type can bitrate 50000");
}else if(bitrate == CAN_20K_BAUDRATE){
system("ip link set can1 type can bitrate 20000");
}
system("ip link set can1 up");
}
接受函数如下:
int can1_receive(void)
{
int canFdMax, fd_act;
int can1_sock;
int rxlen;
fd_set recvFdSet;
struct timeval timeout;
struct can_frame rxBuf;
int can_frame_size = sizeof(struct can_frame);
can1_sock=can_create_socket("can1");
can1_baudrate_set(CAN_50K_BAUDRATE);//can1_baudrate_set(CAN_20K_BAUDRATE);
while(1)
{
canFdMax = -1;
FD_ZERO(&recvFdSet);
if (can1_sock > 0) {
FD_SET(can1_sock, &recvFdSet);
if(canFdMax < can1_sock) {canFdMax =can1_sock;}
}
if(canFdMax > 0){
timeout.tv_sec = 0;
timeout.tv_usec = 8*1000;
fd_act = 0;
fd_act = select(canFdMax+1, &recvFdSet, NULL, NULL, &timeout);
if (fd_act > 0) {
if (can1_sock > 0) {
if (FD_ISSET(can1_sock, &recvFdSet)) { /* can1 接收 */
rxLen = read(can1_sock, &rxBuf, can_frame_size);
if(rxLen > 0){
/*解析rxbuf*/
}
}
}
}
}
}
}
解析rxbuf过程,首先看can_frame结构体(我用的事扩展帧)
struct can_frame {
canid_t can_id;//CAN 标识符
__u8 can_dlc;//数据场的长度
__u8 data[8];//数据
};
截取rubuf的成员,可以建立一个自己的结构体,用来解析
typedef struct {
unsigned char eff_rtr_err;
unsigned char fun1;
unsigned char fun2;
unsigned char fun3;
unsigned char fun4;
}can_id_t;
can_id_t can_id_out;
假设 fun1为22-29(21-28)、fun2为15-21(14-20)、fun3为8-14(7-13)、fun1为1-7(0-6)
can_id_out.eff_rtr_err=(uchar)((rxbuf.can_id & 0xe0000000)>>29);
can_id_out.fun1 = (uchar)((rxbuf.can_id & 0x1fe00000)>>21);
can_id_out.fun2 = (uchar)((rxbuf.can_id & 0x001fc000)>>14);
can_id_out.fun3 = (uchar)((rxbuf.can_id & 0x00003f80)>>7);
can_id_out.fun4 = (uchar)(rxbuf.can_id & 0x0000007f);
rxbuf.can_dlc用来判断长度;
rxbuf.data为接受数据
发送数据类似