色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > CAN總線學(xué)習(xí)筆記四:CAN總線通信

          CAN總線學(xué)習(xí)筆記四:CAN總線通信

          作者: 時間:2015-01-17 來源:網(wǎng)絡(luò) 收藏

            在理解了的自通信程序后,再來探討間的相互通信變得容易了許多。對于是自通信還是相互通信,這個肯定是需要對寄存器進(jìn)行必要的設(shè)置的,分析PIAE的兩個程序后不難發(fā)現(xiàn),自通信和互通信需要設(shè)置的知識模式寄存器,這個是在的初始化時進(jìn)行設(shè)定的。

          本文引用地址:http://cafeforensic.com/article/268271.htm

            的初始化程序我根據(jù)習(xí)慣,直接把它獨(dú)立成一個子程序了。如下,是工作于自通信時的初始化程序。

            ///////////////////////////////////////////////

            //函數(shù):init_sja1000

            //說明:獨(dú)立CAN控制器的初始化

            //入口:無

            //返回:無

            ///////////////////////////////////////////////

            void init_sja1000(void)

            {

            uchar state;

            uchar ACRR[4];

            uchar AMRR[4];

            // 接收代碼寄存器

            ACRR[0] = 0xff;

            ACRR[1] = 0x22;

            ACRR[2] = 0x33;

            ACRR[3] = 0x44;

            // 接收屏蔽寄存器,只接收主機(jī)發(fā)送的信息

            AMRR[0] = 0xff;

            AMRR[1] = 0Xff;

            AMRR[2] = 0xff;

            AMRR[3] = 0xff;

            // 使用do--while語句確保進(jìn)入復(fù)位模式

            do

            { // 設(shè)置MOD.0=1--進(jìn)入復(fù)位模式,以便設(shè)置相應(yīng)的寄存器

            MODR = 0x09;

            state = MODR;

            }

            while( !(state & 0x01) );

            // 對SJA1000部分寄存器進(jìn)行初始化設(shè)置

            CDR = 0x88; // CDR為時鐘分頻器,CDR.3=1--時鐘關(guān)閉, //CDR.7=0---basic CAN, CDR.7=1---Peli CAN

            BTR0 = 0x31; // 總線定時寄存器0 ;總線波特率設(shè)定

            BTR1 = 0x1c; // 總線定時寄存器1 ;總線波特率設(shè)定

            IER = 0x01; // IER.0=1--接收中斷使能; IER.1=0--關(guān)閉發(fā)送中斷使能

            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語句確保進(jìn)入自接收模式

            do

            { //MOD.2=1--進(jìn)入自接收模式,MOD.3=0--雙濾波器模式

            MODR = 0x04;

            state = MODR;

            }

            while( !(state & 0x04) );

            }

            兩個數(shù)組ACRR[4]和AMRR[4]分別存儲著需要設(shè)置的接收代碼寄存器和接收屏蔽寄存器的數(shù)值。這兩個數(shù)組的設(shè)置設(shè)計(jì)者可以根據(jù)需要自己設(shè)定(在互通信時就需要在這里做文章了)。AMRR的四個值都設(shè)定為OXFF說明無論總線上傳輸?shù)腎D值是什么,也不管ACRR的數(shù)值設(shè)定是什么,這個SJA1000都照單全收(至于為什么,上節(jié)關(guān)于驗(yàn)收濾波的日志做了詳細(xì)討論了)。

            然后進(jìn)入設(shè)定模式寄存器進(jìn)入復(fù)位模式。在復(fù)位模式下,可以對SJA1000部分寄存器進(jìn)行初始化設(shè)置,并且把剛才兩個數(shù)組的數(shù)據(jù)存入接收代碼寄存器和接收屏蔽寄存器里,自此初始化算是完成了。但是因?yàn)?a class="contentlabel" href="http://cafeforensic.com/news/listbylabel/label/CAN總線">CAN總線控制器要進(jìn)行自通信,所以必須對模式寄存器設(shè)定使得SJA1000進(jìn)入復(fù)位模式,這就是最后的do--while語句的作用。

            接下來,我們看CAN總線互相通信的初始化設(shè)置。

            ///////////////////////////////////////////////

            //函數(shù):init_sja1000

            //說明:獨(dú)立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語句確保進(jìn)入復(fù)位模式

            do

            { // 設(shè)置MOD.0=1--進(jìn)入復(fù)位模式,以便設(shè)置相應(yīng)的寄存器

            MODR = 0x09;

            state = MODR;

            }

            while( !(state & 0x01) );

            // 對SJA1000部分寄存器進(jìn)行初始化設(shè)置

            CDR = 0x88; // CDR為時鐘分頻器,CDR.3=1--時鐘關(guān)閉, //CDR.7=0---basic CAN, CDR.7=1---Peli CAN

            BTR0 = 0x31; // 總線定時寄存器0 ;總線波特率設(shè)定

            BTR1 = 0x1c; // 總線定時寄存器1 ;總線波特率設(shè)定

            IER = 0x01; // IER.0=1--接收中斷使能; IER.1=0--關(guān)閉發(fā)送中斷使能

            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語句確保退出復(fù)位模式

            do

            {

            MODR = 0x08; //MOD.3=0--雙濾波器模式

            state = MODR;

            }

            while( state & 0x01 );

            }

            很容易可以發(fā)現(xiàn),CAN互通信和自通信的初始化設(shè)置,只有最后的設(shè)置是不一樣的,自通信時把模式寄存器的自通信寄存器位置位,而互通信時只要退出復(fù)位模式(同時把自通信寄存器位清零)即可。其它的設(shè)置根據(jù)需要設(shè)定。

            上面討論了自通信和互通信兩種工作方式下的寄存器設(shè)置。那么,我就在想,如果用互通信的模式下,如果發(fā)送幀的ID設(shè)定和自身接收的驗(yàn)收濾波吻合,是不是也能進(jìn)行自接收呢?答案是否定的,根據(jù)以上的設(shè)想做的實(shí)驗(yàn)表明,在互通信模式下,CAN總線上若只有一個節(jié)點(diǎn),那么CAN總線是不會達(dá)到你預(yù)想的變化的,按下鍵后紅燈會一直亮著,說明CAN總線陷入了無法接收或者正在接收的死循環(huán)跳不出來了。

            另外,我還做了一個實(shí)驗(yàn)。就是當(dāng)CAN節(jié)點(diǎn)1發(fā)送的數(shù)據(jù)幀ID不僅和節(jié)點(diǎn)2的吻合,也和自身的驗(yàn)收濾波吻合,那么當(dāng)節(jié)點(diǎn)1的數(shù)據(jù)幀發(fā)送后是不是節(jié)點(diǎn)1和節(jié)點(diǎn)2都能接收到數(shù)據(jù)呢?結(jié)果證明這個設(shè)想是成立的。這也就說明了掛靠在CAN總線上的每一個節(jié)點(diǎn),只要CAN總線上的數(shù)據(jù)幀ID和某節(jié)點(diǎn)驗(yàn)收濾波通過,該節(jié)點(diǎn)就可以接收數(shù)據(jù)。

            在初始化設(shè)置了模式寄存器后,下一步就是設(shè)定不同的發(fā)送幀的ID和本節(jié)點(diǎn)的接收代碼寄存器值和屏蔽寄存器值。我這里只有兩個節(jié)點(diǎn)通信,一般如果要使CAN總線上的兩個節(jié)點(diǎn)相互接收到對方的數(shù)據(jù)。那么根據(jù)上一節(jié)的原理設(shè)定接收代碼寄存器值和屏蔽寄存器值以及發(fā)送幀的ID值就可以了。

            在看懂并且理解了PIAE工作組的CAN自通信和互通信后,我想對于CAN總線協(xié)議的工作方式算是已經(jīng)入門了,剩下的就是繼續(xù)從官方或者第三方提供的datasheet里補(bǔ)知識,根據(jù)不同的場合和不同的應(yīng)用把CAN總線控制器的寄存器設(shè)置用活來。

          通信相關(guān)文章:通信原理


          分頻器相關(guān)文章:分頻器原理


          關(guān)鍵詞: CAN總線 SJA1000

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉