从零理解CAN总线(FlexCAN驱动测试篇)

问题描述:

    作为一个职场新人上周技术老大交给一个任务,让去了解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<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>


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<frame.can_dlc;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;
}



猜你喜欢

转载自blog.csdn.net/ass_dsb/article/details/79425153
今日推荐