有人问我一段以前写的代码的细节,函数名是xxx_CAN_Config_Rx_ID_Group,用的是ST的芯片
1 tmpOrRes = 0; 2 tmpAndRes = xxx_CAN_ID_MAX; 3 4 for(uint32_t i = 0; i < len; i++) 5 { 6 if(Rx_ID_Arr[i] > xxx_CAN_ID_MAX) 7 { 8 return -1; 9 } 10 else 11 { 12 tmpAndRes &= Rx_ID_Arr[i]; 13 tmpOrRes |= Rx_ID_Arr[i]; 14 } 15 } 16 17 tmpFilter = tmpAndRes; 18 tmpMask = (tmpOrRes ^ xxx_CAN_ID_MAX) | tmpAndRes;
上面是核心部分的展示,困惑的点是17,18行,filter和mask干什么用的,为什么这么算。
这代码我都写了两年,不看回技术文档,only god knows。
怼了他一遍要看技术文档后,我看见这是数学相关的操作,就尝试直接从代码入手看下能不能看懂,毕竟这也是我一直在锻炼的能力。
1.还是要先搞清楚目的,输入和输出。看了下函数名,这个明显是CAN的组过滤的配置,而Rx_ID_Arr就是要过滤出来的id的数组,len就是这个数组的长度,tmpFilter和tmpMask后面赋给了ST库api所需要的实例的成员变量。那显而易见,这个代码片段的作用就是根据要过滤出来的id组生成st寄存器需要用到的filter和mask。
2.看了下循环,显然,目的有两个,id的合法性检查以及得到这些id的与值和或值
3.对与和或值的理解改变一下,tmpAndRes:指示所有id里都为1的位;tmpOrRes:指示所有id里置过1的位
4.对18行的算式分成两部分 (tmpOrRes ^ xxx_CAN_ID_MAX) 和 tmpAndRes 进行理解,第一部分代表了将所有id里都为0的位置1,第二部分代表了将所有id里都为1的位置1,即tmpMask的作用是将所有id里同一位都相同的位置1
5.结合17行,可以推断(对 这块只能推断,不看文档只看代码哪有那么多100%)寄存器里filter和mask的作用效果是符合 0 == ((id ^ filter) & mask) 的id将满足过滤条件
6.由此看出这个函数的group配置只能符合满足的最小集合,不能做到只匹配组内成员,比如我要过滤0x21和0x22,那很遗憾,0x20和0x23必然也会被过滤出来
好了,推完了,拿回技术文档出来对比了下,确实如此,nice。
