实际上 void CAN_SetRxMsgObj(********) { if (idType == CAN_STD_ID) { CANx->sMsgObj[msg_if].M1R = 0; CANx->sMsgObj[msg_if].M2R = STD_RANGE_ID_MSK(idLow, idHigh);
CANx->sMsgObj[msg_if].A1R = 0; CANx->sMsgObj[msg_if].A2R = CAN_A2R_MSGVAL |STD_RANGE_ID_ARB(idLow, idHigh); } ....... } #define RANGE_ID_MSK(range_start, range_end) (~((range_end) - (range_start))) #define RANGE_ID_ARB(range_start, range_end) ((range_start) & (range_end))
#define STD_RANGE_ID_MSK(range_start, range_end) ((u16)((RANGE_ID_MSK((range_start), (range_end)) & 0x7FF) << 2)) #define STD_RANGE_ID_ARB(range_start, range_end) ((u16)(RANGE_ID_ARB((range_start), (range_end)) << 2)) 实际上地址过滤就是设置MSK和ID(总裁)。两者一起合作来过滤地址。
而ST采用的供给用户的软件算法是这样的: MSR:~(idhigh - idlow);为1的位则对应该位的ID位必须对应,不对应则过滤 ID:(idhigh & idlow);ID总裁作用 可以看出,用户其实是必须设定了ID位,再通过MSR来确定ID的哪几位用作匹配。 实际上它是不能完全起作用的, 举例说明: 用户设定: idhigh:0x3FF idlow: 0x100 那么:MSR:为10100000000 ID: 为00100000000 所以实际的匹配为为第9和第11位:0x1xxxxxxxx(x表任意值) 但是可以发现其实,这是有漏洞的,即0x2xx的地址段也包含在用户需要的地址段中, 但是它却会被过滤掉,因为第9位被确定为了1,而0x2xx的第9位为0。 所以实际的接收地址为0x100~0x1FF和 0x300~0x3FF两段。
所以,在使用提供函数设置地址过滤的时候,最好自己推算一下。
另外,如果设置唯一地址时,只需要ID放地址然后将MSR置全1即可,可以不需要用ST提供的函数。
|