2018-11-13 13:29:23 vonchn 阅读数 246

ARM40-­A5应用程序——CAN总线的发送和接收

版权声明:本文为博主原创文章,允许转载。
  
  ARM40-A5系列板卡共有2路隔离CAN总线,CAN总线的引脚定义见《ARM40-­A5指南——CAN总线接口与测试》。

一、shell中CAN总线的接收与发送

1.1、硬件接线与配置

  将CAN0的TX与CAN1的TX通过100R电阻连接,CAN0的RX和CAN1的RX通过100R电阻连接(直接相连亦可),然后:

ifconfig can0 down
ip link set can0 type can bitrate 250000        //配置can0的波特率为250kbps
ifconfig can0 up

ifconfig can1 down
ip link set can1 type can bitrate 250000        //配置can0的波特率为250Kbps
ifconfig can1 up

2.2、shell中接收与发送

root@ARM40:~# candump can1 &			                        //将CAN1设置为接收
root@ARM40:~# cansend can0 5A1#11.2233.44556677.88	    		// CAN0发数据
can1  5A1   [8]  11 22 33 44 55 66 77 88
root@ARM40:~# candump can0 &			                    	//将CAN0设置为接收
root@ARM40:~# cansend can1 5A1#11.2233.44556677.88	    		// CAN1发数据
can0  5A1   [8]  11 22 33 44 55 66 77 88

二、CAN总线发送和接收的C源码

2.1、CAN总线发送

  这个测试程序要用USB CAN II调试盒或者睿芯CAN转串口(USB串口)做接收,传送到PC机上。

/*
 * test_can_recv.c 
 *ARM40发送,PC接收
 */
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/sockios.h>
#include <linux/if.h>

int main( int argc,char* argv[] )
{
        int i, ret;
        int nbytes;
        int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
        char *interface = "can0";

        int can_fd = -1;
        struct sockaddr_can addr;
        struct ifreq ifr;
        struct can_frame frame_rev;

        printf("SocketCAN Test V1.0\n");

        can_fd = socket(family, type, proto);                // 创建SocketCAN 套接字
        printf("SOCK_RAW can sockfd:%d\n", can_fd);
        if( can_fd < 0 )
        {
                perror("socket");
                return can_fd;
        }

        int loopback = 0;         // 0 = disabled, 1 = enabled (default)
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

        strcpy(ifr.ifr_name, interface);        // 指定 can0 设备 strcpy(ifr.ifr_name, "can0" );
        ret = ioctl(can_fd, SIOCGIFINDEX, &ifr);        // 指定 can0 设备
        if(ret) {
                perror("ioctl:interface");
                goto abort;
        }

        addr.can_family = family;
        addr.can_ifindex = ifr.ifr_ifindex;
        ret = bind(can_fd, (struct sockaddr *)&addr, sizeof(addr));        // 将套接字与 can0 绑定
        if (ret)        {
                perror("bind\n");
                goto abort;
        }

        // 设置过滤规则,只接收表示符等于 0x123 的报文,如果没有这段,则接受所有报文
        struct can_filter rfilter;
        rfilter.can_id = 0x123;
        rfilter.can_mask = CAN_SFF_MASK;     							  // 0x000007FFU
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));        //设置过滤规则
        /*
         * 如果应用程序不需要接收报文,可以禁用过滤规则。这样的话,原始套接字就会忽略所有接收到的报文。
         * 在这种仅仅发送数据的应用中,可以在内核中省略接收队列,以此减少 CPU 资源的消耗。
         * 禁用方法如下:
         * setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);     //禁用过滤规则
         */
        memset(&frame_rev,0x0,sizeof(frame_rev));
        while(1) {
                nbytes = read(can_fd, &frame_rev, sizeof(frame_rev));               //接收报文
                if(nbytes < 0){
                        perror("read");
                        goto abort;
                }

                if(nbytes < sizeof(struct can_frame)){
                        printf("read:incomplete can frame\n");
                        goto abort;
                }

                printf("ID=0x%X,DLC=%d",frame_rev.can_id,frame_rev.can_dlc);        //显示报文
                for(i=0; i<frame_rev.can_dlc; i++)
                        printf(",data[%d]=%x", i,frame_rev.data[i]);
                printf("\n");

                memset(&frame_rev,0x0,sizeof(frame_rev));
        }
        close(can_fd);
        return 0;

abort:
        close(can_fd);
        return ret;
}

  测试结果为:

root@ARM40:~# ./test_can0_recv 
SocketCAN Test V1.0
SOCK_RAW can sockfd:3        // PC上发送数据,ARM40上可以接收到
ID=0x123,DLC=8,data[0]=0,data[1]=1,data[2]=2,data[3]=3,data[4]=4,data[5]=5,data[6]=6,data[7]=7
ID=0x123,DLC=8,data[0]=0,data[1]=1,data[2]=2,data[3]=3,data[4]=4,data[5]=5,data[6]=6,data[7]=7

2.2、CAN总线接收

  这个测试程序要用USB CAN II调试盒或者睿芯CAN转串口(USB串口)接到PC机上,PC发送,ARM40接收。

/*
 *test_can_send.c 
 *ARM40接收,PC发送
 */
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/sockios.h>
#include <linux/if.h>


int main( int argc,char* argv[] )
{
        int i, ret;
        int nbytes;
        int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
        char *interface = "can1";

        int can_fd = -1;
        struct sockaddr_can addr;
        struct ifreq ifr;
        struct can_frame frame_send;


        printf("SocketCAN Test V1.0\n");

        can_fd = socket(family, type, proto);                // 创建SocketCAN 套接字
        printf("SOCK_RAW can sockfd:%d\n", can_fd);
        if( can_fd < 0 )
        {
                perror("socket");
                return can_fd;
        }

        int loopback = 0; 									// 0 = disabled, 1 = enabled (default)
        setsockopt(can_fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

        strcpy(ifr.ifr_name, interface);        			// 指定 can0 设备 strcpy(ifr.ifr_name, "can0" );
        ret = ioctl(can_fd, SIOCGIFINDEX, &ifr);        	// 指定 can0 设备
        if(ret)
        {
                perror("ioctl:SIOCGIFINDEX");
                goto abort;
        }

        addr.can_family = family;
        addr.can_ifindex = ifr.ifr_ifindex;
        ret = bind(can_fd, (struct sockaddr *)&addr, sizeof(addr));        // 将套接字与 can0 绑定
        if(ret) {
                perror("bind\n");
                goto abort;
        }

		/* 发送一个字节的情况
        frame_send.can_id = 0x00;
        frame_send.can_dlc = 1;
        frame_send.data[0] = 'Y';
		*/
        frame_send.can_id = 0x123;
        frame_send.can_dlc = 8;        									 // 发送8个字节,一次最多发8个字节
        for(i=0; i<8; ++i)      {    
                frame_send.data[i] = i;
        }
        //strncpy(frame_send.data,"12345678",8);

        nbytes = write(can_fd, &frame_send, sizeof(frame_send));        //发送
        if(nbytes <0 ){
                perror("write");
                goto abort;
        }

        // 打印发送的字节
        printf("write %d bytes frame:can_id=0x%x,can_dlc=%d\n", i,frame_send.can_id,frame_send.can_dlc);
        for(i=0; i<frame_send.can_dlc; i++)
                        printf(",data[%d]=%x", i,frame_send.data[i]);
        printf("\n");

        close(can_fd);
        return 0;

abort:
        close(can_fd);
        return ret;
}

  测试结果为:

root@ARM40:~# ./test_can1_send
SocketCAN Test V1.0
SOCK_RAW can sockfd:3        // PC上收到的数据
write 8 bytes frame:can_id=0x123,can_dlc=8
,data[0]=0,data[1]=1,data[2]=2,data[3]=3,data[4]=4,data[5]=5,data[6]=6,data[7]=7
root@ARM40:~# 

参考文章:
  Linux内核 Documentation/networking/can.txt
  Low Level CAN Framework Application Programmers Interface
  Linux内核Socket CAN中文文档
  https://blog.csdn.net/yuanlulu/article/details/7220060
  Linux socket CAN编程示例
  https://blog.csdn.net/jirryzhang/article/details/79417986
  Linux CAN编程详解
  https://blog.csdn.net/reille/article/details/49980469
  linux can 总线socket接口测试使用
  http://blog.chinaunix.net/uid-13889805-id-3072479.html
  CAN接口测试方法
  http://www.embedsky.com/index.php?g=home&m=news&a=show&id=62
  https://github.com/linux-can/can-utils
  荟聚计划:共商 共建 共享 Grant

2016-09-15 16:07:13 ambercctv 阅读数 6087

Modbus和CAN做为两种工业上常用的总线协议在仪器仪表,汽车,轨道交通设备上获得了广泛的使用.

CAN总线由德国BOSCH公司开发,设计初衷是为汽车上电子设备提供互联,经过多年的发展,现在几乎所有的汽车级MCU都包含有CAN控制器(已然是各种MCU的标配外设)

CAN总线是一种对等的总线或者是多主总线,总线上的每一个设备都可以是主设备.CAN总线根据ID的大小来竞争获取总线控制权.

现在一般使用的CAN2.0B标准,有标准桢和扩展桢的2种格式,扩展桢支持29位ID,数据长度最大是8个字节,最大线速率是1M bps,接收端可以设置滤波器过滤总线上的数据包

CAN总线只是一种数据链路层的标准(ISO 7层协议中的第二层)所以对数据帧中payload的含义并没有规定,应用程序需要自己定义payload数据的具体含义.


Modbus最初由莫迪康(后被施奈德电气收购)公司开发的一种应用层的协议,Modbus协议定义了应用层的桢的格式,数据长度.寄存器地址,读写控制,桢间隔时间等信息.在物理层可以使用RS232/485/422 和Ethernet等传输介质.

Modbus是一种主从式协议或者Client/Server模式协议.Master发送读写等请求,Slave端做出响应.

modbus协议在工业自动化设备,仪器仪表行业应用非常广泛,比如PLC设备上, Modbus poll是一个非常好用的modbus 解析软件,常作为Master来使用,在调试slave端软件时很有帮助.


2018-10-07 20:27:08 a154299 阅读数 781

问题背景:本人开发板使用的是迅为iTOP4412精英版,额外购买的CAN/485模块,如下图:

但是插上模块之后,在终端使用ifconfig can0命令发现开发板读不到CAN设备,显示“ifconfig: SIOCGIFFLAGS: No such device”。如下图:

在重新配置内核后,可以读出CAN的设备来了。如下图

配置方法如下:

(1)打开官方搭建好环境的Ubuntu,进入内核目录

(2)在内核目录下输入命令“make menuconfig”进入内核配置界面

(3)因为CAN总线是GPIO上SPI的复用,所以首先要配置SPI。

首先进入“Device Drivers”;

再进入“SPI Support”

选中“GPIO-based Bitbanging SPI Master”和“Samsung S3C64XX series type SPI”两项

取消选中“RC522 Module driver support”这一项(防止占用CAN端口)

(4)配置CAN

回到主界面,进入“Networking Support”

进入“CAN bus system support”

进入“Can Device Drivers”

选中“Platform CAN drivers with Netlink support”,“CAN bit-timing calculation”,“Microchip MCP251x SPI CAN controllers”三项。

(5)退出内核配置界面,询问是否保存对话框选择“Yes”。

(6)使用“make zImage”编译内核后,将内核烧写进开发板即可。

 

注:如果在编译内核的过程中出现“recipe for target 'arch/arm/mach-exynos/cpu-exynos4.o' failed”的问题,请移步链接:https://blog.csdn.net/a154299/article/details/82955449

2020-03-07 10:51:45 cedian0443 阅读数 186

问题描述

硬件:研华工控机(型号忘记了)
系统:Debian 10 - 4.19.0-8
软件:研华CAN总线Linux下的 socket can 驱动程序,下载地址
问题:make的时候出错,安装CAN总线驱动失败。

原因1:没有安装系统对应的header

在这里插入图片描述解决方法:根据你的系统安装header。

注意不同的系统需要安装不同的header。
根据这里提示的系统版本,例如这里的4.19.0-8
然后使用apt search linux-headers来找到对应的软件包并安装

sudo apt install linux-headers-4.19.0-8-all

原因2:驱动程序的路径包含了空格

如果安装了headers还是不行,请检查你的驱动程序的路径是否包含了空格,如果有,去掉这些空格

正确安装

附上正确安装的流程。

sudo make
sudo make install

因为工控机没有在身边,不能看到can网卡,你可以再用ip link指令,查看can0是否正确检测到。

在这里插入图片描述

2017-01-12 17:14:59 qwaszx523 阅读数 687


转自http://www.cnblogs.com/general001/articles/2342728.html

 1引言

  基于嵌入式系统设计的工业控制装置,在工业控制现场受到各种干扰,如电磁、粉尘、天气等对系统的正常运行造成很大的影响。在工业控制现场各个设备之间要经常交换、传输数据,需要一种抗干扰性强、稳定、传输速率快的现场总线进行通信。文章采用CAN总线,基于嵌入式系统32位的S3C44B0X微处理器,通过其SPI接口MCP2510 CAN控制器扩展CAN总线;将嵌入式操作系统嵌入到S3C44B0X微处理器中,能实现多任务、友好图形用户界面;针对S3C44B0X微处理器没有内存管理单元MMU,采用uClinux嵌入式操作系统。这样在嵌入式系统中扩展CAN设备关键技术就是CAN设备在嵌入式操作系统下驱动程序的实现。文章重点解决了CAN总线在嵌入式操作系统下驱动程序实现的问题。对于用户来说,CAN设备在嵌入式操作系统驱动的实现为用户屏蔽了硬件的细节,用户不用关心硬件就可以编出自己的用户程序。实验结果表明驱动程序的正确性,能提高整个系统的抗干扰能力,稳定性好,最大传输速率达到1Mb/s;硬件的错误检定特性也增强了CAN的抗电磁干扰能力。

  2系统硬件设计

  系统采用S3C44B0X微处理器,需要扩展CAN控制器。常用的CAN控制器有SJA1000mcp2510,这两种芯片都支持CAN2.0B标准。SJA1000采用的总线是地址线和数据线复用的方式,但是嵌入式处理器外部总线大多是地址线和数据线分开的结构,这样每次对SJA1000操作时需要先后写入地址和数据2次数据,而且SJA1000使用5V逻辑电平。所以应用MCP2510控制器进行扩展,收发器采用82C250。MCP2510控制器特点:1.支持标准格式和扩展格式的CAN数据帧结构(CAN2.0B);2.0~8字节的有效数据长度,支持远程帧;3.最大1Mb/s的可编程波特率;4.2个支持过滤器的接受缓冲区,3个发送缓冲区;5.SPI高速串行总线,最大5MHz;6.3~5.5V宽电压范围供电。MCP2510工作电压为3.3V,能够直接与S3C44B0X微处理器I/O口相连。为了进一步提高系统抗干扰性,可在CAN控制器和收发器之间加一个光隔6N137。其结构原理框图如图1:

                图1.S3C44B0X扩展CAN结构框图

                   图2.字符设备注册表

  3CAN设备驱动程序的设计

  Linux把设备看成特殊的文件进行管理,添加一种设备,首先要注册该设备,增加它的驱动。设备驱动程序是操作系统内核与设备硬件之间的接口,并为应用程序屏蔽了硬件细节。在linux中用户进程不能直接对物理设备进行操作,必须通过系统调用向内核提出请求,由内核调用相应的设备驱动。因此首先建立Linux设备管理、设备驱动、设备注册、Linux中断这几个概念。

  3.1 Linux的设备管理

  Linux支持各种各样的外围设备,对这些设备的管理通称为设备管理。设备管理分为两部分:一部分是驱动程序的上层,与设备无关的,这部分根据输入输出请求,通过特定的设备驱动程序接口与设备进行通信;另一部分是下层,与设备有关的,通常称为设备驱动程序,它直接与硬件打交道,并且向上层提供一组访问接口。Linux设备管理为了对设备进行读、写等操作,把物理设备逻辑化,把它看成特殊的文件,称为设备文件,采用文件系统接口和系统调用来管理和控制设备。Linux把设备分为三类,块设备、字符设备和网络设备。每类设备都有不同管理控制方式和不同的驱动程序,这样方便于对系统进行裁减。Linux内核对设备的识别是根据设备类型和设备号。在字符设备中使用同一个驱动程序的每种设备都有唯一的主设备号。CAN设备通过在/vendor/Samsung/44b0/Makefile文件下设置设备类型和设备号分别为can、125。

  3.2 file_operaTIONs结构体

  Linux对设备操作的具体实现是由设备驱动程序完成。设备驱动程序加载到系统中通过设备注册实现。Linux驱动程序对文件的操作通过file_operations结构体来完成。file_operations结构体是文件操作函数指针的集合。在设备管理中该结构体各个成员项指向的操作函数就是设备驱动程序的各个操作例程,编写驱动程序实质上就是编写该结构体中的各个函数。对不同的设备可以配备其中全部或部分的操作函数,不使用的函数指针置为NULL。下面是CAN设备file_operations结构体:

  Static struct file_operations {

  write:   s3c44b0_mcp2510_write,//写操作

  read:    s3c44b0_mcp2510_read,//读操作

  ioctl:   s3c44b0_mcp2510_ioctl,//读写之外的操作

  open:    s3c44b0_mcp2510_open,//打开设备

  release:  s3c44b0_mcp2510_release};//关闭设备

  这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用,来调用自己的驱动接口,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。

  3.3 设备注册

  在linux中,当一种设备安装到系统时必须向系统进行注册,设备注册的主要任务是把设备驱动程序加载到系统中。Linux对不同的设备(如字符设备和块设备)分开进行注册管理。每个设备描述符包括两个指针:name指向设备名字符串,fops指向文件操作函数结构file_operations,该结构体中包含着指向驱动程序各个操作例程的指针。图2给出了linux字符设备注册表的示意图。CAN字符设备的注册函数是内核函数:register_chrdev(MAJOR_NR,device_NAME,&s3c44b0_mcp2510_fops);

  其中参数DEVICE_NAME表示设备名,s3c44b0_mcp2510_fops表示指向file_operations结构体的指针,即指向设备的驱动程序。

  3.4 Linux中断的处理

  在linux系统里,对中断的处理是属于系统核心部分,因而如果设备与系统之间以中断方式进行数据交换,就必须把该设备的驱动程序作为系统核心的一部分。设备驱动程序通过用request_irq函数来申请中断,通过free_irq来释放中断。由于本实验未用到中断,因此在此不作详细介绍。

  3.5 CAN驱动程序的实现

  3.5.1 编写驱动程序操作例程

  CAN设备属于字符设备,对于CAN总线设备,除了发送(使用write方法)、接受(使用read方法)以外,还需要控制CAN总线通信的波特率、设置工作模式、设置ID等,所以使用ioctl是最合适的方法。

  CAN驱动程序的入口函数:

  int __init s3c44b0_mcp2510_init(void){ARMTargetInit();//初始化ARM

  init_MCP2510(BandRat125kbps);//初始化CAN控制器  ret=register_chrdev(MAJOR_NR,DEVICE_NAME,&s3c44b0_mcp2510_fops);}//注册CAN设备

  CAN驱动程序的退出函数:void __exit s3c44b0_mcp2510_exit(void){

  unregister_chrdev(MAJOR_NR,DEVICE_NAME);printk("MCP2510 Eixt!n");}

  编写CAN设备驱动程序各个操作例程:

  1.ioctl函数:

  Static int s3c44b0_mcp2510_ioctl (struct inode * inode,struct file *file, unsined cmd ,unsigned long arg){switch(cmd){case SETBAND://设置波特率

  MCP2510_SetBandRate(BandRate,TRUE);break;case SETLPBK://设置工作方式

  MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLK| CLK1);break;case SETID://设置标识符

  MCP2510_Write_Can_ID(RXF0SIDH,U8 ID,0);break;case SETFILTER: //设置屏蔽码

  MCP2510_Write_Can_ID(RXM0SIDH,0x1ff,0);break;}}

  2.open函数(打开设备):

  static int s3c44b0_mcp2510_open(struct inode *inode,struct file *file)

  {printk("device openn");return 0;}

  3.write函数(发送数据):

  static ssize_t s3c44b0_mcp2510_write(struct file *file,const char *buffer,size_t count,loff_t *ppos){copy_from_user(&temp,buffer,sizeof(mcpcan_data));   canWrite(temp.id,temp.data,temp.DataLen,temp.IdType,temp.BufNo);}//发送数据函数

  4.read函数(接收数据):

  static ssize_t s3c44b0_mcp2510_read(struct file *file,char *buffer,size_t count,loff_t *ppos){Revdata(0x66,datas,0x08);//接收数据函数

  copy_to_user(buffer,Receivedata.data,0x08);return count;}

  3.5.2交叉编译CAN驱动程序

  交叉编译驱动程序需要一台装了Red Hat Linux的宿主机。安装交叉编译工具的方法请参考相关文档(交叉编译工具:arm-elf-tools-20030314.sh)。驱动程序的使用可以按照两种方式进行编译,一种是静态编译进内核,一种是编译成模块以供动态加载。由于uclinux不支持模块动态加载,所以这里只介绍将驱动程序静态编译进内核的方法。为了让编译器编译所添加的驱动程序,需要修改相关文件。

  1.修改/linux-2.4.x/driver/char/Makefile文件,增加:

  Ifeq((tab键)$(CONFIG_MCP2510),Y)      (换行)Obj-y+=akaeled.o

  Endif//这几句话的意思是如果配置了mcp2510,则把mcp2510.o加进内核。

  2.修改linux-2.4.x/driver/char/mem.c,在文件中增加如下代码:

  #ifdef CONFIG_MCP2510   (换行)extern void mcp2510_init();

  #endif//通过该文件告诉内核调用相应的CAN驱动程序

  #ifdef CONFIG_MCP2510     (换行)mcp2510_init();       (换行)#endif

  3.修改linux-2.4.x/driver/char/Config.in文件,在字符字段内添加如下代码:

  Bool ‘mcp2510 support’ CONFIG_MCP2510

  这样在make menuconfig时将出现mcp2510的配置选项。

  4.修改/uClinux/vendor/Samsung/44b0/Makefile

  在DEVICES部分添加内容:can, c, 125, 0。这句话的意思是在device中注册一个字符设备can,该设备主设备号为125,次设备号为0。在make menuconfig时进入Character devices,选中里面的support mcp2510。在root权限下执行下列命令编译内核:

  1、#make dep;2、#make lib_only;3、#make romfs;4、#make image;5、#make

  4  CAN驱动程序的测试

  4.1 编写应用程序

  为了验证所添加的驱动程序的正确性,编写一个应用程序CAN2510.C进行测试,在应用程序中使用下面函数创建一个线程用来发送数据:

  pthread_creat(&id,NULL,(void *)cansend,&sendata);

  在cansend()函数中用write()函数调用驱动程序s3c44b0_mcp2510_write()实现数据的发送,用read()函数调用驱动程序s3c44b0_mcp2510_read()接收节点发送过来的数据,用printf()输出节点发送过来的数据,验证接收到的数据是否正确。

  4.2  编译CAN应用程序

  编译应用程序有两种方法:一是放到内核中编译,这种方法需要写一个Makefile文件,还需要修改相应文件,比较麻烦;另外一种办法是单独编译,把编译产生的可执行文件添加到uclinux文件系统romfs中的bin文件夹下,重新编译内核。本实验采用了后者。执行:#arm-elf-gcc –elf2flt can2510.c –o can2510 –lpthread

  其中arm-elf-gcc是编译器,增加参数–elf2flt是由于uclinux只支持flat格式的可执行文件,-0是对编译进行优化,can2510是编译产生的可执行文件名称。把can2510复制到/home/cai/uclinux/romfs/bin目录下,重新编译内核,把产生的映像文件image.rom或image.ram下载到目标板,运行can2510进行CAN驱动测试。

  5  结论

  本文的创新点:在分析Linux设备驱动程序工作原理和结构的基础上,独立添加了CAN总线设备驱动程序到嵌入式操作系统Linux中。经实验表明嵌入式系统下扩展CAN总线传输数据可靠、抗干扰强,在工业控制场合有很大的使用价值;同时,CAN设备在嵌入式操作系统linux下驱动程序的成功实现,为在嵌入式系统中扩展其他硬件设备驱动程序提供了很好的参考价值。

Linux CAN编程详解

阅读数 22838