有理解了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总线操控器的寄存器设置用活来。