signed

QiShunwang

“诚信为本、客户至上”

嵌入式Linux下CAN接口socket发送调试

2020/8/20 15:34:50   来源:

1、简介

最近在做嵌入式linux can通讯的调试,需要用到扩展帧,参照示例代码和linux库改为扩展帧格式发送。
参考链接 链接: https://blog.csdn.net/toradexsh/article/details/72639660 .

2、扩展帧与数据帧的不同

// linux/can.h
/*

  • Controller Area Network Identifier structure
  • bit 0-28 : CAN identifier (11/29 bit)
  • bit 29 : error message frame flag (0 = data frame, 1 = error message)
  • bit 30 : remote transmission request flag (1 = rtr frame)
  • bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
    */
    typedef __u32 canid_t;

#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29

标准帧的ID长度为11位,扩展帧的ID长度为29位,对于复杂的多点应用可以更灵活的设计优先级设置滤波器,帧ID是32位数据结构,想要发送扩展帧,可以根据以上的定义,对帧ID的bit31置1即可发送标准帧,置零则是标准帧,远程帧和错误帧同理,

3、附上测试代码

// can发送代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int main(int argc, char *argv[])
{
	int s, nbytes;
	struct sockaddr_can addr;
	struct ifreq ifr;
	struct can_frame frame;
	struct can_filter rfilter[1];

	/* handle (optional) flags first */
	if (argc != 2)
	{
		fprintf(stderr, "Usage:   <can interface name> for sending\n");
		exit(1);
	}
	/* create socket */
	if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
	{
		perror("Create socket failed");
		exit(-1);
	}

	/* set up can interface */
	strcpy(ifr.ifr_name, argv[1]);
	printf("can port is %s\n", ifr.ifr_name);
	/* assign can device */
	ioctl(s, SIOCGIFINDEX, &ifr);
	addr.can_family = AF_CAN;
	addr.can_ifindex = ifr.ifr_ifindex;
	/* bind can device */
	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		perror("Bind can device failed\n");
		close(s);
		exit(-2);
	}

	/* configure sending */

	/* configure can_id and can data length */
	//frame.can_id = 0x1F;			 //标准帧
	frame.can_id = 0x1F | (1 << 31); //扩展帧
	frame.can_dlc = 8;
	printf("%s ID=%#x data length=%d\n", ifr.ifr_name, frame.can_id, frame.can_dlc);
	/* prepare data for sending: 0x11,0x22...0x88 */
	for (int i = 0; i < 8; i++)
	{
		frame.data[i] = ((i + 1) << 4) | (i + 1);
		printf("%#x ", frame.data[i]);
	}
	printf("Sent out\n");
	/* Sending data */
	if (write(s, &frame, sizeof(frame)) < 0)
	{
		perror("Send failed");
		close(s);
		exit(-4);
	}

	close(s);
	return 0;
}