NXP

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

2019-07-12 12:47发布

问题描述:    作为一个职场新人上周技术老大交给一个任务,让去了解CAN总线,打算让做这方面的事,然后扔给一个IMX6的板子,让自己去测试上面已经移植好了的一个驱动。翻了翻之前买的书,发现在嵌入式这块,好像很多书籍上面都没有对CAN总线驱动有一个详细的描述,网上好像也就CSDN上有那么几篇文章介绍,然后就都是一些原理上的秒速,找起来很头疼,然后就这一周的学习情况做一个总结。
查看驱动信息:第一步:    拿到板子之后,因为是才接触这个项目所以满满的都是陌生感啊...........................................................
到/dev下面去找can总线的设备节点:cd   /devls然后发现居然没有任何一个设备是和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 +cC程序测试方式:    前面介绍到,现行的很多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* ");
printf("********************helep info****************** ");
printf("s data***********is send data to bus; r ***************is receive data frome bus; q ***************is exit programe; h ***************is for helep info; note:data not more than 8byte; ********************helep info end************** ");
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 ",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 ");
close(s);
exit(-2);
}
while(1)
{
printf("input cmd:");
fflush(stdout);
gets(buf);
if(!strncmp("r",buf,1))
{
printf("receive data begain ");


/*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 ",ifr.ifr_name, frame.can_id,
frame.can_dlc);
int i=0;
for(i=0;i {
printf("%#x",frame.data[i]);
}
printf(" ");
}

}
else if(!strncmp("s",buf,1))
{
printf("send data begain ");
/*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 ",frame.can_dlc);


printf("frame.data =%s ",frame.data);
printf("send a CAN frame frome interface %s ", 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 ");
}
memset(buf,0,sizeof(buf));
}
close(s);
return 0;
}