单片机/MCU论坛
直播中

xiaopeng

11年用户 224经验值
擅长:嵌入式技术,处理器/DSP
私信 关注
[文章]

【HD-G2UL-EVM开发板体验】CAN数据收发

说明

开发板引出了一路CAN接口,可以用它来做CAN通讯相关的应用程序。

Linux 系统中CAN 接口配置

在 Linux 系统中, CAN 总线接口设备作为网络设备被系统进行统一管理。在控制台下, CAN 总线的配置和以太网的配置使用相同的命令。

在控制台输入ifconfig -a可以查看CAN接口

图片.png

显示有一路CAN接口can0可用。

另外,可以用相关命令对其进行操作:

线的位速率:
ip link set can0 type cantq 125 prop-seg 6phase-seg1 7 phase-seg2 2 sjw 1
也可以使用 ip 命令直接设定位速率:
ip link set can0 type can bitrate 125000
当设置完成后,可以通过下面的命令查询 can0 设备的参数设置:
ip -details link show can0
当设置完成后,可以使用下面的命令使能 can0 设备:
ifconfig can0 up
使用下面的命令取消 can0 设备使能:
ifconfig can0 down
在设备工作中,可以使用下面的命令来查询工作状态:
ip -details -statistics link show can0

Linux 系统中CAN 接口应用程序开发

由于系统将 CAN 设备作为网络设备进行管理,因此在 CAN 总线应用开发方面, Linux 提供了SocketCAN 接口,使得 CAN 总线通信近似于和以太网的通信,应用程序开发接口 更加通用, 也更加灵活。

关于Linux的CAN接口编程详细技术文档可以参考如下文章:

https://blog.csdn.net/panfei263031/article/details/122977734

CAN接口确定

根据开发板用户手册和原理图可以确定CAN接口(TX,RX)的位置:

图片.png

图片.png

应用编程

在正式开始之前,需要设置设置一下系统启动脚本,否则使用过程中会存在一些问题。
参考用户手册的CAN章节,需要修改/etc/rc.local文件,添加对CAN的配置:

图片.png

本次应用程序将实现如下功能:

1、循环发送CAN数据帧,ID:0x12,DLC:4,data:01 02 03 04 ,每秒一次

2、以非阻塞的方式周期性读取CAN数据,若接收到数据则把数据打印出来

源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <fcntl.h>


int main(void)
{
	struct ifreq ifr = {0};
	struct sockaddr_can can_addr = {0};
	struct can_frame frame = {0};
	
	struct can_filter rfilter;
	
	int loopback = 0;//1-开启回环模式,0-关闭回环模式
	int sockfd = -1;
	int ret;
	
	/*  打开套接字 */
	sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
	if (sockfd < 0)
	{
		printf("socket error\r\n");
		exit(EXIT_FAILURE);
	}
	
	/*  指定can0设备 */
	strcpy(ifr.ifr_name, "can0");
	ioctl(sockfd, SIOCGIFINDEX, &ifr);
	can_addr.can_family = AF_CAN;
	can_addr.can_ifindex = ifr.ifr_ifindex;
	
	/*  将can0与套接字绑定 */
	ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
	if (ret < 0)
	{
		printf("bind error\r\n");
		close(sockfd);
		exit(EXIT_FAILURE);
	}	
	
	/* 设置read函数的非阻塞 */
	fcntl(sockfd, F_SETFL, FNDELAY);
	
	/*  设置过滤规则 */
	rfilter.can_id = 0x12;
	rfilter.can_mask = 0x7FF;
	//设置过滤器
	//setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
	
	/*  设置回环模式 */
	setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));
	
	int ro = 0;
	//设置接收自己的消息
	//setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &ro, sizeof(ro));
	
	/*  发送数据 */
	frame.data[0] = 0x01;
	frame.data[1] = 0x02;
	frame.data[2] = 0x03;
	frame.data[3] = 0x04;	
	
	frame.can_dlc = 4;
	frame.can_id = 0x12;
	
	while(1)
	{
		printf("CAN data write\r\n");	
		ret = write(sockfd, &frame, sizeof(frame));//发送数据
		if(ret != sizeof(frame))
		{
			printf("write error,ret = %d\r\n",ret);
			break;
		}
		sleep(1);
		printf("CAN data read\r\n");
		struct can_frame rec_frame;
		if(read(sockfd, &rec_frame, sizeof(struct can_frame)) > 0)//读取数据
		{
			char temp[50];
			for(int i = 0; i < rec_frame.can_dlc; i++)
			{
				sprintf(&temp[i * 3], "%02x ", rec_frame.data[i]);
			}
			printf("recv message :ID:0x%x, DLC:%d,  data:%s\r\n", rec_frame.can_id, rec_frame.can_dlc, temp);
		}
			
	}
	
	close(sockfd);
	exit(EXIT_SUCCESS);
}

编译

图片.png

运行并测试

开发板运行can_test程序,并使用USB转CAN工具连接开发板,使用PC工具进行can数据的接收和发送。

PC端接收开发板发送的数据:

图片.png

开发板接收PC端发送的数据:

图片.png

总结

根据实验结果说明开发板的CAN数据收发是成功的,达到了预期的效果。
由此可见,Linux下的CAN编程与网络编程非常相似,极大的简化了CAN的应用程序编程。

更多回帖

发帖
×
20
完善资料,
赚取积分