完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
在理解了CAN总线的自通信程序后,再来探讨CAN总线间的相互通信变得容易了许多。对于是自通信还是相互通信,这个肯定是需要对寄存器进行必要的设置的,分析PIAE的两个程序后不难发现,自通信和互通信需要设置的知识模式寄存器,这个是在SJA1000的初始化时进行设定的。
SJA1000的初始化程序我根据习惯,直接把它独立成一个子程序了。如下,是工作于自通信时的初始化程序。 /////////////////////////////////////////////// //函数:init_sja1000 //说明:独立CAN控制器SJA1000的初始化 //入口:无 //返回:无 /////////////////////////////////////////////// void init_sja1000(void) { uchar state; uchar ACRR[4]; uchar AMRR[4]; // 接收代码寄存器 ACRR[0] = 0xff; ACRR[1] = 0x22; ACRR[2] = 0x33; ACRR[3] = 0x44; // 接收屏蔽寄存器,只接收主机发送的信息 AMRR[0] = 0xff; AMRR[1] = 0Xff; AMRR[2] = 0xff; AMRR[3] = 0xff; // 使用do--while语句确保进入复位模式 do { // 设置MOD.0=1--进入复位模式,以便设置相应的寄存器 MODR = 0x09; state = MODR; } while( !(state & 0x01) ); // 对SJA1000部分寄存器进行初始化设置 CDR = 0x88; // CDR为时钟分频器,CDR.3=1--时钟关闭, //CDR.7=0---basic CAN, CDR.7=1---Peli CAN BTR0 = 0x31; // 总线定时寄存器0 ;总线波特率设定 BTR1 = 0x1c; // 总线定时寄存器1 ;总线波特率设定 IER = 0x01; // IER.0=1--接收中断使能; IER.1=0--关闭发送中断使能 OCR = 0xaa; // 配置输出控制寄存器 CMR = 0x04; // 释放接收缓冲器 // 初始化接收代码寄存器 ACR0 = ACRR[0]; ACR1 = ACRR[1]; ACR2 = ACRR[2]; ACR3 = ACRR[3]; // 初始化接收屏蔽寄存器 AMR0 = AMRR[0]; AMR1 = AMRR[1]; AMR2 = AMRR[2]; AMR3 = AMRR[3]; // 使用do--while语句确保进入自接收模式 do { //MOD.2=1--进入自接收模式,MOD.3=0--双滤波器模式 MODR = 0x04; state = MODR; } while( !(state & 0x04) ); } 两个数组ACRR[4]和AMRR[4]分别存储着需要设置的接收代码寄存器和接收屏蔽寄存器的数值。这两个数组的设置设计者可以根据需要自己设定(在互通信时就需要在这里做文章了)。AMRR的四个值都设定为OXFF说明无论总线上传输的ID值是什么,也不管ACRR的数值设定是什么,这个SJA1000都照单全收(至于为什么,上节关于验收滤波的日志做了详细讨论了)。 然后进入设定模式寄存器进入复位模式。在复位模式下,可以对SJA1000部分寄存器进行初始化设置,并且把刚才两个数组的数据存入接收代码寄存器和接收屏蔽寄存器里,自此初始化算是完成了。但是因为CAN总线控制器要进行自通信,所以必须对模式寄存器设定使得SJA1000进入复位模式,这就是最后的do--while语句的作用。 接下来,我们看CAN总线互相通信的初始化设置。 /////////////////////////////////////////////// //函数:init_sja1000 //说明:独立CAN控制器SJA1000的初始化 //入口:无 //返回:无 /////////////////////////////////////////////// void init_sja1000(void) { uchar state; uchar ACRR[4]; uchar AMRR[4]; // 接收代码寄存器 ACRR[0] = 0x11; ACRR[1] = 0x22; ACRR[2] = 0x33; ACRR[3] = 0x44; // 接收屏蔽寄存器 AMRR[0] = 0x00; AMRR[1] = 0Xff; AMRR[2] = 0x00; AMRR[3] = 0xff; // 使用do--while语句确保进入复位模式 do { // 设置MOD.0=1--进入复位模式,以便设置相应的寄存器 MODR = 0x09; state = MODR; } while( !(state & 0x01) ); // 对SJA1000部分寄存器进行初始化设置 CDR = 0x88; // CDR为时钟分频器,CDR.3=1--时钟关闭, //CDR.7=0---basic CAN, CDR.7=1---Peli CAN BTR0 = 0x31; // 总线定时寄存器0 ;总线波特率设定 BTR1 = 0x1c; // 总线定时寄存器1 ;总线波特率设定 IER = 0x01; // IER.0=1--接收中断使能; IER.1=0--关闭发送中断使能 OCR = 0xaa; // 配置输出控制寄存器 CMR = 0x04; // 释放接收缓冲器 // 初始化接收代码寄存器 ACR0 = ACRR[0]; ACR1 = ACRR[1]; ACR2 = ACRR[2]; ACR3 = ACRR[3]; // 初始化接收屏蔽寄存器 AMR0 = AMRR[0]; AMR1 = AMRR[1]; AMR2 = AMRR[2]; AMR3 = AMRR[3]; // 使用do--while语句确保退出复位模式 do { MODR = 0x08; //MOD.3=0--双滤波器模式 state = MODR; } while( state & 0x01 ); } 很容易可以发现,CAN互通信和自通信的初始化设置,只有最后的设置是不一样的,自通信时把模式寄存器的自通信寄存器位置位,而互通信时只要退出复位模式(同时把自通信寄存器位清零)即可。其它的设置根据需要设定。 上面讨论了自通信和互通信两种工作方式下的寄存器设置。那么,我就在想,如果用互通信的模式下,如果发送帧的ID设定和自身接收的验收滤波吻合,是不是也能进行自接收呢?答案是否定的,根据以上的设想做的实验表明,在互通信模式下,CAN总线上若只有一个节点,那么CAN总线是不会达到你预想的变化的,按下键后红灯会一直亮着,说明CAN总线陷入了无法接收或者正在接收的死循环跳不出来了。 另外,我还做了一个实验。就是当CAN节点1发送的数据帧ID不仅和节点2的吻合,也和自身的验收滤波吻合,那么当节点1的数据帧发送后是不是节点1和节点2都能接收到数据呢?结果证明这个设想是成立的。这也就说明了挂靠在CAN总线上的每一个节点,只要CAN总线上的数据帧ID和某节点验收滤波通过,该节点就可以接收数据。 在初始化设置了模式寄存器后,下一步就是设定不同的发送帧的ID和本节点的接收代码寄存器值和屏蔽寄存器值。我这里只有两个节点通信,一般如果要使CAN总线上的两个节点相互接收到对方的数据。那么根据上一节的原理设定接收代码寄存器值和屏蔽寄存器值以及发送帧的ID值就可以了。 在看懂并且理解了PIAE工作组的CAN自通信和互通信后,我想对于CAN总线协议的工作方式算是已经入门了,剩下的就是继续从官方或者第三方提供的datasheet里补知识,根据不同的场合和不同的应用把CAN总线控制器的寄存器设置用活来。 |
|
|
|
只有小组成员才能发言,加入小组>>
如何使用STM32+nrf24l01架构把有线USB设备无线化?
2547 浏览 7 评论
请问能利用51单片机和nRF24L01模块实现实时语音无线传输吗?
2332 浏览 5 评论
3159 浏览 3 评论
2804 浏览 8 评论
为什么ucosii上移植lwip后系统进入了HardFault_Handler?
2762 浏览 4 评论
请教各位大咖:有没有接收频率32M左右的芯片推荐的?先感谢啦!
610浏览 1评论
855浏览 0评论
970浏览 0评论
623浏览 0评论
449浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 20:16 , Processed in 1.092066 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号