问题描述:
作为一个职场新人上周技术老大交给一个任务,让去了解CAN总线,打算让做这方面的事,然后扔给一个IMX6的板子,让自己去测试上面已经移植好了的一个驱动。翻了翻之前买的书,发现在嵌入式这块,好像很多书籍上面都没有对CAN总线驱动有一个详细的描述,网上好像也就CSDN上有那么几篇文章介绍,然后就都是一些原理上的秒速,找起来很头疼,然后就这一周的学习情况做一个总结。
查看驱动信息:
第一步:
拿到板子之后,因为是才接触这个项目所以满满的都是陌生感啊...........................................................
到/dev下面去找can总线的设备节点:
cd /dev
ls
然后发现居然没有任何一个设备是和can设备相关的描述(瞬间懵逼.............),这是因为在linux2.6之后就把can归类到net目录下了,访问根据是socket CAN分配网络端口(INTERFACE)和索引接口(IFINDEX)来进行数据交互的。
第二步:
到/sys/class下面去找设备文件,找了老半天,发现原来是在/sys/class/net目录下
第三步:
查看驱动与上层应用的交互信息: cat uevent (该文件在/sys/class/net/can目录下)
得到:
INTERFACE = can0 端口
IFINDEX = 2 索引接口
ip工具+can盒子测试方式:
ip工具好像在linux中没有的话要自己安装,然后我拿到的是已经移植烧录好的板子,之前应该是将该工具也一并烧录到板子里面的了。can盒子使用的是广成科技的USBCANII双CAN口的,其提供了ECANTOLLS和相关驱动(我自己是用的ZLG(周立功)CAN盒子的驱动,但是遇到一个问题就是公司里另外一个不知道是哪家公司产的CAN盒子发现驱动装上ECANTOLLS正常安装并不能打开设备:提示USB设备打开失败...........而且相关的安装治疗说明文档都没有或者是不配套........所以就放弃了)。
测试步骤:
①板子CAN口接线到CAN盒子
②板子串口连上电脑串口终端
③CAN盒子USB线连接电脑,打开ECANTOLLS
串口上进行CAN设置:
①ip link set can0 down (注意can0是我在)
②ip link set can0 type can bitrate 50000 loopback off (设置can总线工作波特率)
③ip link set can0 up (can总线使能)
设置好之后可以查看can总线的状态:
ip -details link show can0
④发送数据
cansend can0 123#11
⑤接收数据
candump can0 (这时阻塞在接收处,等待ECANTOLLS发送信息过来)
结束发送ctrl +c
C程序测试方式:
前面介绍到,现行的很多linux版本不再以单纯的字符设备来描述can总线了,而是归类到net中,使用socket CAN来进行访问。
不多说直接上代码:
/*************************************************************************
*File Name: test_can.c
* Author: dsb
* Mail:
* Created Time: Thu 01 Mar 2018 07:00:17 PM PST
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
void helep_info(void)
{
printf("*function descraption:CAN send &receive*\n");
printf("********************helep info******************\n");
printf("s data***********is send data to bus;\n r ***************is receive data frome bus;\n q ***************is exit programe;\n h ***************is for helep info;\n note:data not more than 8byte;\n ********************helep info end**************\n");
return;
}
int main(void)
{
int s,nbytes;
helep_info();
char buf[11];
struct sockaddr_can addr; /*use to set net info*/
struct ifreq ifr; /*use to get interface name & interface index*/
struct can_frame frame; /*use to save send & receive data*/
// struct can_filter rfilter[1]; /*use to set can_id &can_mask*/
/*create socket*/
if( (s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) <0 )
{
perror("create socket failed");
exit(-1);
}
/*set up can interface*/
strcpy((char *)ifr.ifr_name,"can0");
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);
}
while(1)
{
printf("input cmd:");
fflush(stdout);
gets(buf);
if(!strncmp("r",buf,1))
{
printf("receive data begain\n");
/*we can set fileter for only receiving packet with special canid
* test_can is skip*/
nbytes = read(s, &frame, sizeof(frame));
if(nbytes>0 )
{
printf("%s ID=%#X DLC= %d\n",ifr.ifr_name, frame.can_id,\
frame.can_dlc);
int i=0;
for(i=0;i
printf("%#x",frame.data[i]);
}
printf("\n");
}
}
else if(!strncmp("s",buf,1))
{
printf("send data begain\n");
/*configure can_id and can data length*/
frame.can_id = 0x1f;
strcpy((char *)frame.data,(char *)(buf+2));
frame.can_dlc = strlen(frame.data);
printf("DLC=%d\n",frame.can_dlc);
printf("frame.data =%s\n",frame.data);
printf("send a CAN frame frome interface %s\n", ifr.ifr_name);
printf("ifindex= %d",ifr.ifr_ifindex);
nbytes = write(s,&frame, sizeof(frame));
if(nbytes <0)
{
perror("send fail");
}
}
else if(!strncmp("q",buf,1))
{
return 0;
}
else if(!strncmp("h",buf,1))
{
helep_info();
}
else
{
printf("cmd is not fund plese enter h to check\n");
}
memset(buf,0,sizeof(buf));
}
close(s);
return 0;
}