之前做的STC32G12K128的CAN测试程序中,预想要达到的测试目的是:CAN1发送数据,CAN2接收数据;CAN2发送数据,CAN1接收数据。但实际测试中,出现的结果是:CAN1发送数据,CAN1接收数据;CAN2发送数据,CAN2接收数据。在我搭配的电路如下:
按照这个电路,CAN1和CAN2是使用相同的总线,因此无论是哪个CAN发送了数据,CAN1和CAN2都会收到数据。那么为了实现我的目的,就需要配置CAN,使自己的CAN发送的数据,被自己屏蔽掉,只接受自身以外的CAN发送的数据。
根据STC32G12K128的说明,需要配置验收器和屏蔽器。STC32G12K128的CAN1和CAN2都配置有属于自己的验收器(总线验收代码寄存器ACR0~ACR3)和屏蔽器(总线验收屏蔽寄存器AMR0~AMR3)。理论上,只要在初始化时配置好这两组寄存器就可以。如果使用单滤波模式,需要配置CAN 模式寄存器(MR)中的B0位AFM为1,即
CanWriteReg(MR ,0x01); // 使用单滤波模式
按照滤波的规则,每一位验收屏蔽分别对应每一位验收代码,
1)当该位验收屏蔽位为“1”的时候(即设为无关),接收的相应帧 ID 位无论是否和相应的验收代码位相同均会表示为接收;
2)当验收屏蔽位为“0”的时候(即设为相关),只有相应的帧 ID 位和相应的验收代码位值相同的情况才会表示为接收。
3)只有在所有的位都表示为接收的时候,CAN 控制器才会接收该报文。
滤波器配置定义了一个长滤波器(4 字节、32 位),由 4 个验收码寄存器和 4 个验收屏蔽寄存器组
成的验收滤波器,滤波器字节和信息字节之间位的对应关系取决于当前接收帧格式。
接收 CAN 标准帧单滤波器配置:对于标准帧,11 位标识符、RTR 位、数据场前两个字节参与滤波;
对于参与滤波的数据,当AMR中对应的位Bx= 0时,对应的 ACR中Bx的位和参与滤波数据的对应位Bx必须相同才算验收通过;
如果由于置位 RTR=1 位而没有数据字节,或因为设置相应的数据长度代码而没有或只有一个数据字节信息,报文也会被接收。
对于一个成功接收的报文,所有单个位在滤波器中的比较结果都必须为“接受”;
注意 AMR1 和 ACR1 的低四位是不用的,为了和将来的产品兼容,这些位可通过设置 AMR1.3、AMR1.2、AMR1.1 和 AMR1.0 为 1 而定为“不影响”。
所以单滤波模式下,只需要针对扩展帧中的报文识别码来配置就行,不需要数据位的参与。
程序中,CAN的ID配置为,
CAN1_ID = 0x01303132;
CAN2_ID = 0x03333435;
根据滤波规则,当AMR中对应的位Bx= 0时,对应的 ACR中Bx的位和参与滤波数据的对应位Bx必须相同才算验收通过;
那么对于CAN1,为了能只让CAN2 的数据被接收,因此配置成:验收代码位与CAN2的ID一致的数据,表示只接受CAN2发送的数据;验收屏蔽位全部设成0,表示直接和验收收代位一致的ID(即CAN2的ID)发送的数据。
同样,需要配置CAN2的验收代码位为CAN1对应的ID,验收屏蔽位全部设成0。
改变CAN1和CAN2的初始化部分程序,
// 总线验收代码寄存器
// CAN1_ID = 0x01303132;
// CAN2_ID = 0x03333435;
// 对CAN1,ACR配置成CAN2的ID
CAN_InitStructure.CAN_ACR0 = 0x03; //总线验收代码寄存器 0~0xFF
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR1 = 0x33;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR2 = 0x34;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR3 = 0x35;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR0 = 0x00; //总线验收屏蔽寄存器 0~0xFF
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR1 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR2 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR3 = 0x00;
CAN_Inilize(CAN1,&CAN_InitStructure); //CAN1 初始化
// 总线验收代码寄存器
// CAN1_ID = 0x01303132;
// CAN2_ID = 0x03333435;
// 对CAN2,ACR配置成CAN1的ID
CAN_InitStructure.CAN_ACR0 = 0x01; //总线验收代码寄存器 0~0xFF
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR1 = 0x30;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR2 = 0x31;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR3 = 0x32;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR0 = 0x00; //总线验收屏蔽寄存器 0~0xFF
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR1 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR2 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR3 = 0x00;
CAN_Inilize(CAN2,&CAN_InitStructure); //CAN2 初始化
编译、下载、运行,结果显示,接收处理部分没有收到数据。OLED上的显示只有发送部分的数据,至少说明屏蔽起作用了。
问题出在哪里呢?难道是ID配置错了?根据手册
难道是ID的位顺序不对?ID只使用29位,从B0开始到B28。这个ID.后面跟着的顺序号和B的位顺序号是一致的,还是正好相反的?
为了验证,只对CAN1做验证、屏蔽处理,CAN2可以接受任意数据,并把发送方的ID显示出来。
// 总线验收代码寄存器
// CAN1_ID = 0x01303132;
// CAN2_ID = 0x03333435;
// 对CAN1,ACR配置成CAN2的ID
CAN_InitStructure.CAN_ACR0 = 0x03; //总线验收代码寄存器 0~0xFF
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR1 = 0x33;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR2 = 0x34;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR3 = 0x35;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR0 = 0x00; //总线验收屏蔽寄存器 0~0xFF
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR1 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR2 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR3 = 0x00;
CAN_Inilize(CAN1,&CAN_InitStructure); //CAN1 初始化
// 总线验收代码寄存器
// CAN1_ID = 0x01303132;
// CAN2_ID = 0x03333435;
// 对CAN2,ACR配置成CAN1的ID
CAN_InitStructure.CAN_ACR0 = 0x00; //总线验收代码寄存器 0~0xFF
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR1 = 0x00;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR2 = 0x00;
// 总线验收代码寄存器
CAN_InitStructure.CAN_ACR3 = 0x00;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR0 = 0xFF; //总线验收屏蔽寄存器 0~0xFF
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR1 = 0xFF;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR2 = 0xFF;
// 总线验收屏蔽寄存器
CAN_InitStructure.CAN_AMR3 = 0xFF;
CAN_Inilize(CAN2,&CAN_InitStructure); //CAN2 初始化
结果依然不对。上次发的测试的那个,CAN2发送,CAN2是可以接收自己的。现在依然没有接收。
问题出在哪里呢?