查看: 362|回复: 2
打印 上一主题 下一主题

【Seeed开发板试用体验】应用篇(4)CAN通信

[复制链接] qrcode

33

主题

38

帖子

113

积分

注册会员

Rank: 2

积分
113
楼主
跳转到指定楼层
发表于 2015-11-25 09:50 PM | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

一、CAN简介

    CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议。此后,CAN 通过ISO11898 及ISO11519 进行了标准化,现在在欧洲已是汽车网络的标准协议。
    现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。
    CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。
    CAN协议具有一下特点:
1)  多主控制。在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
2)  系统的若软性。与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
3)  通信速度较快,通信距离远。最高1Mbps(距离小于40M),最远可达10KM(速率低于5Kbps)。
4)  具有错误检测、错误通知和错误恢复功能。所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
5)  故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
6)  连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。
    正是因为CAN协议的这些特点,使得CAN特别适合工业过程监控设备的互连,因此,越来越受到工业界的重视,并已公认为最有前途的现场总线之一。
    CAN协议经过ISO标准化后有两个标准:ISO11898标准和ISO11519-2标准。其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准,而ISO11519-2是针对通信速率为125Kbps以下的低速通信标准。
本章,我们使用的是450Kbps的通信速率,使用的是ISO11898标准,该标准的物理层特征如图30.1.1所示:

    从该特性可以看出,显性电平对应逻辑0,CAN_H和CAN_L之差为2.5V左右。而隐性电平对应逻辑1,CAN_H和CAN_L之差为0V。在总线上显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。另外,在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射。


二、BBG上的CAN接口

    在BBG上,通过扩展接口,引出了两路CAN接口,具体如下图所示。分别由P921和P22组成CAN0接口,和分别由P924和P926组成CAN1接口。

    在Linux内核中,把CAN总线封装成了一个网络接口,详细可参考。也就是说,我们在linux应用层,进行CAN总线通信时,可使用类似操作Sokect编程的方法,进行数据的通信。同样也可以使用命令行进行调试操作,在BBG提供的镜像文件中,已经为我们加载了操作CAN相关的命令工具,具体源码也可以参考官方提供的链接,如果想详细了解CAN协议栈,也可以说下载CANFestival开源项目的源码,进行研究。


三、CAN通信

(一)终端测试

1 启动CAN接口

    在BBG中,默认是没有启动CAN接口,需要用户手动启动,好在在/lib/firmware目录下,已经提供了有关CAN的设备树源文件和编译文件,为了保险起见,我们复制一份,然后将其编译,生成可加载文件,然后使用echo加载。注意加载了,会提示如下错误,没有关系,原因未知,可以暂时不用理会这个提示。


2 查看CAN网络

加载后,使用ifconfig -a命令,查看是否加载使用,如下显示,说明加载成功


3 准备接收数据

由于串口已被使用,则使用SSH的登录方式,再打开一个端口,用来准备接收CAN通信的数据,打开后,输入candump can0命令


4 配置CAN接口并发送数据

使用如下图所示的命令,分别配置CAN接口的波特率为1M,开启采样模式,打开回环功能,并启动CAN网络。最后输入命令cansend can0 1 2 4 5 ,发送数据1 2 4 5。


5 查看数据

再返回第3步打开的终端窗口,发现已接收到了刚才发送的命令


(二)CAN外部通信

由第一部分知道,CAN通信的接口分别为CANH和CANL,而在BBG上,引出的CAN接口却是TXD和RXD,故要想使用BBG上的CAN接口,和其他的CAN设备进行数据通信,还需要一个CAN收发器模块

1 CAN收发器

CAN收发器在此介绍两种:

一种是BBB Cape类型的,如TT3201 CAN Cape,它提供3路CAN接口,由BBG主控芯片AM335x CAN控制器和2个Microchip公司的MCP2515芯片组成,如下图左1所示;如BeagleBone Serial CAN RS485 RS232 Cape,这个模块不仅提供了CAN接口,还提供了RS485和RS232接口,如中间所示;还有一个叫CAN Bus Cape,该模块使用了AM335x的CAN1接口,将其引出,支持SocketCAN通信方式,如下图最右边所示。


一种是单片机中,经常用到的CAN模块,当然了,收发器芯片有很多种,但最常用的就是TJA1050,如下图所示。该模块电路也很简单,使用其数据手册推荐的电路即可。本实验就使用该模块。




2 CAN编程

在BBG中,对CAN操作,前面部分也提到了,使用SocketCAN,关于它的介绍,可参见。下面是本人在项目中使用过的部分代码,仅供参考。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc,char *argv[])
{
        int sock_can=0,i;
        int nbytes;
        struct sockaddr_can addr;
        static struct can_frame can_frame;
        struct ifreq ifr;

      if((sock_can=socket(PF_CAN,SOCK_RAW,CAN_RAW))<0)
        {
                perror("Create socket failed");
                exit(-1);
        }

        strcpy(ifr.ifr_name,"can0");
        ioctl(sock_can,SIOCGIFINDEX,&ifr);
        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;

        if(bind(sock_can,(struct sockaddr *) &addr,sizeof(addr))<0)  //[24;63H
        {
                exit(-2);
        }

        can_frame.can_id = 0x0220;
        can_frame.can_dlc = 2;
        can_frame.data[0]=0x01;
        can_frame.data[1]=0x20;

        printf(" Going to write 0x0120n");
//        nbytes=write(sock_can,&can_frame,sizeof(struct can_frame));
        printf("Write %d bytesn",nbytes);

        memset(&can_frame,0,sizeof(can_frame));
        printf(" Going to read ...n");
        nbytes = read(sock_can,&can_frame,sizeof(struct can_frame));
        if(nbytes < 0)
        {
                perror("can raw read error");
                exit(-3);
        }

      printf("can_id: %X data length: %d data:n",can_frame.can_id,can_frame.can_dlc);
        for(i=0;i);

        printf("n");
        return 0;
}



关注微信公众号【口袋物联】,微信号为koudaiwulian更多物联网知识等着你



BeagleBone Green开发板试用帖汇总


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

0

主题

89

帖子

18

积分

新手上路

Rank: 1

积分
18
沙发
发表于 2015-11-27 02:55 PM | 只看该作者

等更新

回复 支持 反对

使用道具 举报

3

主题

83

帖子

25

积分

新手上路

Rank: 1

积分
25
板凳
发表于 2015-11-28 01:48 AM | 只看该作者
谢谢社区老大的支持,已更新!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表