虽然CAN总线中,所有设备都是主机,并没有严格的主从关系。但是由于实际应用中,每个设备都发出消息的话,及其容易触发仲裁机制从而丢失数据。 一般而言,我们会设定某一个CAN设备作为中控设备,其他设备只响应特殊ID(作为本身的ID号)的操作,来避免通讯次序混乱。 其中,读取操作也是CAN操作中的重要一环。这里以两种实际中的应用来讲解CAN如何读取数据。 首先一种情况是,如果需要读取的数据是固定的,也就是说CAN的中控设备每次请求的数据都是同一个变量,可以使用CAN的远程帧。 CAN的远程帧是不携带数据的,可以以最快的效率通知到CAN的从设备,从设备接收到远程帧以后再将准备好的数据发送回去。这样就完成了固定数据的读取。 但是,上面这种通讯还有一种情况,如果有多个CAN从机怎么办呢?答案是让CAN从机在发送的时候,从数据区域带上自己的标识。这样就可以不用管收发之间的数据时序问题了,直接发完几个请求。在接收的FIFO区域中,使用数据解析的时候一起处理了即可。 以下是使用远程帧进行数据请求:
- <font size="5">CAN1_Tx.FF = STANDARD_FRAME; // 标准帧
- CAN1_Tx.RTR = 1; // 0:数据帧,1:远程帧
- CAN1_Tx.DLC = 0x01; // 数据长度
- CAN1_Tx.ID = 0x000a; // CAN ID
- CanSendMsg(&CAN1_Tx);</font>
复制代码
接收端处理上,判断远程帧标志位进行数据回传即可。 上面讲的是第一种,也就是不需要请求不同的数据的情况。那么万一我有两种数据可以返回。并且这两种数据的生成速率不一样。每次只用传输一种的情况,这应该怎么获取呢? 其实这个时候就可以不用远程帧了,直接使用数据帧中定义数据获取的触发位。触发以后直接对主机ID发送一次数据就可以了。到这里其实已经有一些在CAN之上另外自定义协议的意思了。其实CAN本身十分灵活,怎么使用,完全看操作者的定义以及代码的编写。 以下是使用标志位进行数据请求(截取自STC-FOC Lite V2,回传实际编码器数据): - <font size="5">if (can_dat->DataBuffer[Dat_Ctrl] & Get_Dat)
- {
- _out_postion = Read_Postion_Out_Data();
- Can_Send_Flag = 1; // 进行一次数据发送
- CAN2_Tx.FF = STANDARD_FRAME; // 标准帧
- CAN2_Tx.RTR = 0; // 0:数据帧,1:远程帧
- CAN2_Tx.DLC = 0x05; // 数据长度
- CAN2_Tx.ID = 0x0f; // CAN ID,15
- CAN2_Tx.DataBuffer[0] = (u8)((long)(_out_postion) >> 24); // 数据内容
- CAN2_Tx.DataBuffer[1] = (u8)((long)(_out_postion) >> 16); // 回传实际位置,绝对累计位置
- CAN2_Tx.DataBuffer[2] = (u8)((long)(_out_postion) >> 8);
- CAN2_Tx.DataBuffer[3] = (u8)((long)(_out_postion));
- CAN2_Tx.DataBuffer[4] = (u8)(User_Can_ID);
- }</font>
复制代码
综合来说,合适的才是最好的。
|