RK3588 can 编程

以前也做过Can编程,时间久了,就忘记了,因项目的需要,再次做Can编程的时候,竟然发现很多东西都忘记了,于是把怎么进行can编程记录下来,用来备忘。

一、Can总线的一些基本特性。

1、多主控制。在总线空闲时,所有的单元都可以发送消息。最先访问总线的单元,可获得发送权。多个单元同时发送时,根据消息的ID来确定谁具有发送权。

2、没有地址的概念。与总线相连的单元没有地址的概念,因此在总线上增加单元时,连接在总线上的其他单元及应用层都不需要改变。

3、can的电气特性。Can使用二根线来连接各个单元,CAN_H, CAN_L.Can总线通过二根线的电位差来得到总线电平。显性电平表示逻辑0,一般CAN_H 为3.5V,CAN_L 为1.5V,电位差为2V.隐性电平表示逻辑1,一般CAN_H 和CAN_L为2.5V。

4、每个节点单元的组成。一个MCU(微型控制器),一个CAN控制器和一个CAN收发器。

5、帧的种类。CAN定义了5种类型的帧,分别是数据帧,遥控帧,错误帧,过载帧,间隔帧。其中数据帧和遥控帧有标准格式和扩展格式二种。标准格式有11位标识符(ID),扩展格式有29位标识符(ID)

6、一次传输的数据大小。原来的一般是 0-8个字节,现在也有0-64个字节的。很多情况下,一帧数据是不能完整的传输我们的信息,需要分帧。

二、rk3588 can应用编程。

1、can通信测试工具

canutils是常用的CAN通信测试工具包,内含5个独立的程序:

canconfig:用于配置CAN总线接口的参数,主要是波特率和模式。

candump:从CAN总线接口接收数据并以十六进制形式打印到标准输出,也可以输出到指定文件。

candump can0   开启打印,等待接收

canecho:把从CAN总线接口接收到的所有数据重新发送到CAN总线接口。

cansend:往指定的CAN总线接口发送指定的数据。

cansend can0 345#testsend 发送(标准帧,数据帧,ID:345, date:testsend)

cansend can0 00000345#testsend 发送(扩展帧,数据帧,ID:00000345, date:testsend)

cansequence:往指定的CAN总线接口自动重复递增数字,也可以指定接收模式并校验检查接收的递增数字。

2、can 常用命令接口

1、查询当前网络设备:

ifconfig -a

2、关闭CAN

ip link set can0 down

3、设置比特率500KHZ

ip link set can0 type can bitrate 500000

4、打印CAN0信息

ip -details link show can0

5、启动CAN

ip link set can0 up

三、编程实例

struct ifreq ifr;
struct sockaddr_can addr;
int can_fd;
can_fd = socket(PF_CAN,SOCK_RAW,CAN_RAW);//创建套接字
if(can_fd < 0)
    printf("socket can error\n");

strcpy(ifr.ifr_name,"can0");
if(ioctl(can_fd,SIOCGIFINDEX,&ifr)) //指定设备为can0
    printf("ioctl can0 error\n");

addr.can_family = PF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(can_fd,(struct sockaddr *)&addr,sizeof(addr))<0)
    printf("can0 bind error \n");

//过滤规则 接收到的数据帧的 can_id  & mask == can_id & mask
struct can_filter rfilter[1];
rfilter[0].can_id = 0x0800000;
rfilter[0].can_mask = 0xff00000;
setsockopt(can_fd,SOL_CAN_RAW,CAN_RAW_FILTER,&rfilter,sizeof(rfilter));
//发送数据
struct can_frame frame; //发送数据需要填充这个结构体
struct can_frame {
    canid_t can_id;//CAN 标识符
    __u8 can_dlc;//数据场的长度
    __u8 data[8];//数据
};
write(can_fd,&frame,sizeof(frame));
//接收数据
read(can_fd,&frame,sizeof(frame));

猜你喜欢

转载自blog.csdn.net/dreamliweiming/article/details/132232069