首页 > 学院 > 开发设计 > 正文

can1--can初探

2019-11-09 14:29:39
字体:
来源:转载
供稿:网友


转自http://www.cnblogs.com/-song/archive/2012/05/10/3331873.html

mcp2515寄存器一览几个寄存器名称及地址TXBnCTRL——发送缓冲器n 控制寄存器(地址:30h, 40h, 50h)TXBnSIDH——发送缓冲器n 标准标识符高位(地址:31h, 41h, 51h)TXBnSIDL——发送缓冲器n 标准标识符低位(地址:32h, 42h, 52h)TXBnEID8——发送缓冲器n 扩展标识符高位(地址:33h, 43h, 53h)TXBnEID0——发送缓冲器n 扩展标识符低位(地址:34h, 44h, 54h)TXBnDLC——发送缓冲器n 数据长度码(地址:35h, 45h, 55h)TXBnDm——发送缓冲器n 数据字节m(地址:36h - 3Dh, 46h - 4Dh, 56h - 5Dh)RXBnCTRL——接收缓冲器n 控制寄存器(地址:60h,70h)RXBnSIDH——接收缓冲器n 标准标识符高位(地址:61h, 71h)RXBnSIDL——接收缓冲器n 标准标识符低位(地址:62h, 72h)RXBnEID8——接收缓冲器n 扩展标识符高位(地址:63h, 73h)RXBnEID0——接收缓冲器n 扩展标识符低位(地址:64h, 74h)RXBnDLC——接收缓冲器n 数据长度码(地址:65h, 75h)RXBnDM——接收缓冲器n 数据字段字节M(地址:66h - 6Dh, 76h - 7Dh)spi接口操作mcp2515使用的命令can物理信号can信号使用差分电压传送,两条信号线被称为CAN_H和CAN_L。静态时均是2.5v左右,此时状态表示为逻辑“1”,也可以叫做隐性。用CAN_H比CAN_L高表示逻辑“0”,称为显性,此时通常电压值为CAN_H=3.5V和CAN_L=1.5V。

1.标准帧结构--refer to mcp2515说明书CAN 标准数据帧如图所示。与其他所有帧一样,帧以起始帧(SOF)位开始, SOF 为显性状态,允许所有节点的硬同步。SOF之后是仲裁字段,由12个位组成,分别为11个标识位和一个远程发送请求(Remote Transmission Request,RTR)位。RTR 位用于区分报文是数据帧(RTR 位为显性状态)还是远程帧(RTR 位为隐性状态)。仲裁字段之后是控制字段,由6 个位组成。控制字段的第一位为标识扩展(Identifier Extension,IDE)位,该位应是显性状态来指定标准帧。标识扩展位的下一位为零保留位(RB0),CAN 协议将其定义为显性位。控制字段的其余4 位为数据长度码(Data Length Code,DLC),用来指定报文中包含的数据字节数(0 到8 字节)。控制字段之后为数据字段,包含要发送的任何数据字节。数据字段长度由上述DLC 定义(0 到8 字节)。数据字段之后为循环冗余校验(CRC)字段,用来检测报文传输错误。CRC 字段包含一个15 位的CRC 序列,之后是隐性的CRC 定界位。最后一个字段是确认字段(ACK),由2 个位组成。在确认时隙(ACK Slot)位执行期间,发送节点发出一个隐性位。任何收到无错误帧的节点会发回一个显性位(无论该节点是否配置为接受该报文与否)来确认帧收到无误。确认字段以隐性确认定界符结束,该定界符可能不允许被改写为显性位。标准帧和mcp2515的寄存器对应关系一览:详见mcp2515手册对于接受操作:对于发送操作:2.扩展帧结构在扩展CAN 数据帧中(如图2-2 所示),紧随SOF 位的是32 位的仲裁字段。仲裁字段的前11 位为29 位标识符的最高有效位(Most Significant bit,MSb)(基本lD) 。紧随这11 位的是替代远程请求(Substitute Remote Request, SRR)位,定义为隐性状态。SRR位之后是lDE 位,该位为隐性状态时表示这是扩展的CAN 帧。应该注意的是,如果发送完扩展帧标识符的前11 位后,总线仲裁无果,而此时其中一个等待仲裁的节点发出标准CAN 数据帧(11 位标识符),那么,由于节点发出了显性lDE 位而使标准CAN 帧赢得总线仲裁。另外,扩展CAN 帧的SRR 位应为隐性,以允许正在发送标准CAN 远程帧的节点发出显性RTR 位。SRR和lDE位之后是标识符的其余18位(扩展lD)及一个远程发送请求位。为使标准帧和扩展帧都能在共享网络上发送,应将29位扩展报文标识符拆成高11 位和低18 位两部分。拆分后可确保lDE 位在标准数据帧和扩展数据帧中的位置保持一致。仲裁字段之后是6 位控制字段。控制字段前两位为保留位,必须定义为显性位。其余4 位为DLC,用来指定报文中包含的数据字节数。扩展数据帧的其他部分(数据字段、CRC 字段、确认字段、帧结尾和间断)与标准数据帧的结构相同(见第2.1 节“标准数据帧”)。扩展帧和mcp2515的寄存器对应关系一览:详见mcp2515手册对于接受操作:接收时,若得到IDE位为1,表示接收到的是扩展帧。对于发送操作:发送时,置IDE位为1,表示发送的是扩展帧。can的无地址编码与485的有地址编码比如485的modbus帧发出:01 03 00 00 00 03 05 CB                  //01站地址,03功能号,00 00 起始地址,00 03要读的数据个数接收:01 03 06 00 00 00 01 00 02 F1 74    //01站地址,03功能号,06返回的字节数,00 00 00 01 00 02 对应6个字节3个数(03读取保持寄存器,保持寄存器为可读可写,http://blog.csdn.net/songQQnew/article/details/6938039)主机发出的帧中的第一个字节是目的地址即01。所有的设备都可以收到这个帧,只有地址是01的设备才需要响应这个帧,响应帧的第一个字节规定必须是本机地址即01.而can的帧/*  * Controller Area Network Identifier structure  *  * bit 0-28 : CAN identifier (11/29 bit)  * bit 29   : error frame flag (0 = data frame, 1 = error frame)  * bit 30   : remote transmission request flag (1 = rtr frame)  * bit 31   : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)  */  typedef __u32 canid_t;    /**  * struct can_frame - basic CAN frame structure  * @can_id:  the CAN ID of the frame and CAN_*_FLAG flags, see above.  * @can_dlc: the data length field of the CAN frame  * @data:    the CAN frame payload.  */  struct can_frame {      canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */      __u8    can_dlc; /* data length code: 0 .. 8 */      __u8    data[8] __attribute__((aligned(8)));  };  主机向总线发出如下帧,帧的内容是hello,并设置标示符为123,这样总线上123号站应当对此帧有反应。由于都可以作为主机而主动向总线发数据,所以就没必要向modbus那样非得要主机发命令让从机干嘛从机才可以干嘛。比如1号站有可用数据了,那么他直接将数据发送can总线,希望得到哪个站的处理就设置标示符为哪个站比如为123。在硬件层和驱动层,can总线上的所有非123号站也会收到站1发来的数据。但只有123号站应该对其处理--在应用层可以设置是只将驱动接收到的指定can标示符的can_frame上报给应用层,如下    struct can_filter rfilter;//过滤      rfilter.can_id   = 0x123;//选择监听can_frame中标示符是0x123的can帧,不过滤则监听所有。    rfilter.can_mask = CAN_SFF_MASK;      setsockopt(m_can, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));  站123处理完了之后,根据需要要么回复一下(要不不回复),回复的时候也会使用相同的帧结构,回复的时候身份就变成了主机。看来can总线上流动的数据都是某个站主动发出的。而modbus总线上仅可以有一个主机,通信必须采用一问一答的形式,由于主机问的问题有好几种,所以从机针对每个问题回复的modbus帧也些差别。不像can的帧,仅有一种(仅讨论标注帧),每帧最大限制为8个字节。DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[1]=24//TXBnSIDH--?     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[2]=60//TXBnSIDL--?     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[3]=1//TXBnEID8--?     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[4]=23//TXBnEID0--?     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[5]=5//TXBnDLC     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[6]=68//TXBnD0     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[7]=65//TXBnD1     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[8]=6c//TXBnD2     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[9]=6c//TXBnD3     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[10]=6f//TXBnD4     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[11]=0//TXBnD5     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[12]=0//TXBnD6     DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[13]=0//TXBnD7   can的多主与485的单主Can总线本身就是为多主系统设计的,可以在一根总线上有多个主站。而485本身只能是单主的,只能通过其他的办法(如令牌)来变成一个多主系统。这是由硬件特点决定的。485总线上如果有两个节点同时都发送了信号,总线状态无法不确定的,即发送的报文可能已经被破坏了,为了解决这个问题,在某一时刻只能有一个站点主动发起通讯,其他站点都可看成从站。而Can的对比的主要优点在于可以实现非破坏仲裁,为此在硬件上进行了特殊设计,从总线可以看成是一个线与的结构,如果两个或以上节点发送信号电平不一致,总线电平显示为显性,这意味着至少有一个站点的报文没有被破坏。为了仲裁节点在发送信号的同时还在监测总线,如果发送和检测不一致则认为本节点发送报文已经被破坏。节点会自动退出发送状态等待发送结束以后开始下一次发送。而报文始终正确的站点最终取得总线控制权。有一个问题哦,can是多主的总线,spi是单主的总线,那么6410的spi和mcp2515连起来之后怎么就变成了多主了呢?以图说明每个6410下只挂一个mcp2515。6410的cs引脚配置为输出,用于选中从机。当6410.1有数据要发送时,6410.1作为spi主机向mcp2515.1发送数据,然后mcp2515.1作为主机,向总线发送数据。当mcp2515.2从can总线上接收到数据时,它会向6410.2产生一个中断,此时6410.2会作为spi主机从mcp2515.2中主动读到数据。看来是多亏了那根中断线,使得6410都可以作为spi主机主动从与之相连的mcp2515读数据。can的错误检测
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表