<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32的can現(xiàn)場(chǎng)總線實(shí)驗(yàn)心得分享

          STM32的can現(xiàn)場(chǎng)總線實(shí)驗(yàn)心得分享

          作者: 時(shí)間:2016-11-13 來(lái)源:網(wǎng)絡(luò) 收藏
          最近在搞stm32實(shí)驗(yàn)板的can現(xiàn)場(chǎng)總線實(shí)驗(yàn),之前只是搞過(guò)STC51的串口通信,相比之下,發(fā)覺(jué)can總線都挺復(fù)雜的。開(kāi)始時(shí),知道自己是新手,只知道can總線跟串行通信,485通信,I2C通信一樣都是用來(lái)傳輸數(shù)據(jù)通信的,對(duì)其工作原理一竅不通,還是從基礎(chǔ)開(kāi)始看書(shū)看資料,先了解它的基本原理吧。
          原來(lái)can總線有以下特點(diǎn):
          主要特點(diǎn)
          支持CAN協(xié)議2.0A和2.0B主動(dòng)模式
          波特率最高可達(dá)1兆位/秒
          支持時(shí)間觸發(fā)通信功能
          發(fā)送
          3個(gè)發(fā)送郵箱
          發(fā)送報(bào)文的優(yōu)先級(jí)特性可軟件配置
          記錄發(fā)送SOF時(shí)刻的時(shí)間戳
          接收
          3級(jí)深度的2個(gè)接收FIFO
          14個(gè)位寬可變的過(guò)濾器組-由整個(gè)CAN共享
          標(biāo)識(shí)符列表
          FIFO溢出處理方式可配置
          記錄接收SOF時(shí)刻的時(shí)間戳
          可支持時(shí)間觸發(fā)通信模式
          禁止自動(dòng)重傳模式
          16位自由運(yùn)行定時(shí)器
          定時(shí)器分辨率可配置
          可在最后2個(gè)數(shù)據(jù)字節(jié)發(fā)送時(shí)間戳
          管理
          中斷可屏蔽
          郵箱占用單獨(dú)1塊地址空間,便于提高軟件效率
          看完這些特點(diǎn)后,疑問(wèn)一個(gè)一個(gè)地出現(xiàn),
          1. 什么是時(shí)間觸發(fā)功能?
          2. 發(fā)送郵箱是什么來(lái)的?
          3. 報(bào)文是什么來(lái)的?
          4. 什么叫時(shí)間戳?
          5. 什么叫接收FIFO?
          6. 什么叫過(guò)濾器?
          好了,帶著疑問(wèn)往下看,看完一遍后,
          報(bào)文:
          報(bào)文包含了將要發(fā)送的完整的數(shù)據(jù)信息
          發(fā)送郵箱:
          共有3個(gè)發(fā)送郵箱供軟件來(lái)發(fā)送報(bào)文。發(fā)送調(diào)度器根據(jù)優(yōu)先級(jí)決定哪個(gè)郵箱的報(bào)文先被發(fā)送。
          接收過(guò)濾器:
          共有14個(gè)位寬可變/可配置的標(biāo)識(shí)符過(guò)濾器組,軟件通過(guò)對(duì)它們編程,從而在引腳收到的報(bào)文中選擇它需要的報(bào)文,而把其它報(bào)文丟棄掉。
          接收FIFO
          共有2個(gè)接收FIFO,每個(gè)FIFO都可以存放3個(gè)完整的報(bào)文。它們完全由硬件來(lái)管理
          工作模式
          bxCAN有3個(gè)主要的工作模式:初始化、正常和睡眠模式。
          初始化模式
          *軟件通過(guò)對(duì)CAN_MCR寄存器的INRQ位置1,來(lái)請(qǐng)求bxCAN進(jìn)入初始化模式,然后等待硬件對(duì)CAN_MSR寄存器的INAK位置1來(lái)進(jìn)行確認(rèn)
          *軟件通過(guò)對(duì)CAN_MCR寄存器的INRQ位清0,來(lái)請(qǐng)求bxCAN退出初始化模式,當(dāng)硬件對(duì)CAN_MSR寄存器的INAK位清0就確認(rèn)了初始化模式的退出。
          *當(dāng)bxCAN處于初始化模式時(shí),報(bào)文的接收和發(fā)送都被禁止,并且CANTX引腳輸出隱性位(高電平)
          正常模式
          在初始化完成后,軟件應(yīng)該讓硬件進(jìn)入正常模式,以便正常接收和發(fā)送報(bào)文。軟件可以通過(guò)對(duì)CAN_MCR寄存器的INRQ位清0,來(lái)請(qǐng)求從初始化模式進(jìn)入正常模式,然后要等待硬件對(duì)CAN_MSR寄存器的INAK位置1的確認(rèn)。在跟CAN總線取得同步,即在CANRX引腳上監(jiān)測(cè)到11個(gè)連續(xù)的隱性位(等效于總線空閑)后,bxCAN才能正常接收和發(fā)送報(bào)文。
          過(guò)濾器初值的設(shè)置不需要在初始化模式下進(jìn)行,但必須在它處在非激活狀態(tài)下完成(相應(yīng)的FACT位為0)。而過(guò)濾器的位寬和模式的設(shè)置,則必須在初始化模式下,進(jìn)入正常模式前完成。
          睡眠模式(低功耗
          *軟件通過(guò)對(duì)CAN_MCR寄存器的SLEEP位置1,來(lái)請(qǐng)求進(jìn)入這一模式。在該模式下,bxCAN的時(shí)鐘停止了,但軟件仍然可以訪問(wèn)郵箱寄存器。
          *當(dāng)bxCAN處于睡眠模式,軟件想通過(guò)對(duì)CAN_MCR寄存器的INRQ位置1,來(lái)進(jìn)入初始化式,那么軟件必須同時(shí)對(duì)SLEEP位清0才行
          *有2種方式可以喚醒(退出睡眠模式)bxCAN:通過(guò)軟件對(duì)SLEEP位清0,或硬件檢測(cè)CAN總線的活動(dòng)。
          工作流程
          那么究竟can是怎樣發(fā)送報(bào)文的呢?
          發(fā)送報(bào)文的流程為:
          應(yīng)用程序選擇1個(gè)空發(fā)送郵箱;設(shè)置標(biāo)識(shí)符,數(shù)據(jù)長(zhǎng)度和待發(fā)送數(shù)據(jù);然后對(duì)CAN_TIxR寄存器的TXRQ位置1,來(lái)請(qǐng)求發(fā)送。TXRQ位置1后,郵箱就不再是空郵箱;而一旦郵箱不再為空,軟件對(duì)郵箱寄存器就不再有寫(xiě)的權(quán)限。TXRQ位置1后,郵箱馬上進(jìn)入掛號(hào)狀態(tài),并等待成為最高優(yōu)先級(jí)的郵箱,參見(jiàn)發(fā)送優(yōu)先級(jí)。一旦郵箱成為最高優(yōu)先級(jí)的郵箱,其狀態(tài)就變?yōu)轭A(yù)定發(fā)送狀態(tài)。一旦CAN總線進(jìn)入空閑狀態(tài),預(yù)定發(fā)送郵箱中的報(bào)文就馬上被發(fā)送(進(jìn)入發(fā)送狀態(tài))。一旦郵箱中的報(bào)文被成功發(fā)送后,它馬上變?yōu)榭锗]箱;硬件相應(yīng)地對(duì)CAN_TSR寄存器的RQCP和TXOK位置1,來(lái)表明一次成功發(fā)送。
          如果發(fā)送失敗,由于仲裁引起的就對(duì)CAN_TSR寄存器的ALST位置1,由于發(fā)送錯(cuò)誤引起的就對(duì)TERR位置1。
          原來(lái)發(fā)送的優(yōu)先級(jí)可以由標(biāo)識(shí)符和發(fā)送請(qǐng)求次序決定:
          由標(biāo)識(shí)符決定
          當(dāng)有超過(guò)1個(gè)發(fā)送郵箱在掛號(hào)時(shí),發(fā)送順序由郵箱中報(bào)文的標(biāo)識(shí)符決定。根據(jù)CAN協(xié)議,標(biāo)識(shí)符數(shù)值最低的報(bào)文具有最高的優(yōu)先級(jí)。如果標(biāo)識(shí)符的值相等,那么郵箱號(hào)小的報(bào)文先被發(fā)送。
          由發(fā)送請(qǐng)求次序決定
          通過(guò)對(duì)CAN_MCR寄存器的TXFP位置1,可以把發(fā)送郵箱配置為發(fā)送FIFO。在該模式下,發(fā)送的優(yōu)先級(jí)由發(fā)送請(qǐng)求次序決定。該模式對(duì)分段發(fā)送很有用。
          時(shí)間觸發(fā)通信模式
          在該模式下,CAN硬件的內(nèi)部定時(shí)器被激活,并且被用于產(chǎn)生時(shí)間戳,分別存儲(chǔ)在CAN_RDTxR/CAN_TDTxR寄存器中。內(nèi)部定時(shí)器在接收和發(fā)送的幀起始位的采樣點(diǎn)位置被采樣,并生成時(shí)間戳(標(biāo)有時(shí)間的數(shù)據(jù))。
          接著又是怎樣接收?qǐng)?bào)文的呢?
          接收管理
          接收到的報(bào)文,被存儲(chǔ)在3級(jí)郵箱深度的FIFO中。FIFO完全由硬件來(lái)管理,從而節(jié)省了CPU的處理負(fù)荷,簡(jiǎn)化了軟件并保證了數(shù)據(jù)的一致性。應(yīng)用程序只能通過(guò)讀取FIFO輸出郵箱,來(lái)讀取FIFO中最先收到的報(bào)文。
          有效報(bào)文
          根據(jù)CAN協(xié)議,當(dāng)報(bào)文被正確接收(直到EOF域的最后1位都沒(méi)有錯(cuò)誤),且通過(guò)了標(biāo)識(shí)符過(guò)濾,那么該報(bào)文被認(rèn)為是有效報(bào)文。
          接收相關(guān)的中斷條件
          * 一旦往FIFO存入1個(gè)報(bào)文,硬件就會(huì)更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位為1,那么就會(huì)產(chǎn)生一個(gè)中斷請(qǐng)求。
          * 當(dāng)FIFO變滿時(shí)(即第3個(gè)報(bào)文被存入),CAN_RFxR寄存器的FULL位就被置1,并且如果CAN_IER寄存器的FFIE位為1,那么就會(huì)產(chǎn)生一個(gè)滿中斷請(qǐng)求。
          * 在溢出的情況下,F(xiàn)OVR位被置1,并且如果CAN_IER寄存器的FOVIE位為1,那么就會(huì)產(chǎn)生一個(gè)溢出中斷請(qǐng)求
          標(biāo)識(shí)符過(guò)濾
          在CAN協(xié)議里,報(bào)文的標(biāo)識(shí)符不代表節(jié)點(diǎn)的地址,而是跟報(bào)文的內(nèi)容相關(guān)的。因此,發(fā)送者以廣播的形式把報(bào)文發(fā)送給所有的接收者。(注:不是一對(duì)一通信,而是多機(jī)通信)節(jié)點(diǎn)在接收?qǐng)?bào)文時(shí)-根據(jù)標(biāo)識(shí)符的值-決定軟件是否需要該報(bào)文;如果需要,就拷貝到SRAM里;如果不需要,報(bào)文就被丟棄且無(wú)需軟件的干預(yù)。為滿足這一需求,bxCAN為應(yīng)用程序提供了14個(gè)位寬可變的、可配置的過(guò)濾器組(13~0),以便只接收那些軟件需要的報(bào)文。硬件過(guò)濾的做法節(jié)省了CPU開(kāi)銷,否則就必須由軟件過(guò)濾從而占用一定的CPU開(kāi)銷。每個(gè)過(guò)濾器組x由2個(gè)32位寄存器,CAN_FxR0和CAN_FxR1組成。
          過(guò)濾器的模式的設(shè)置
          通過(guò)設(shè)置CAN_FM0R的FBMx位,可以配置過(guò)濾器組為標(biāo)識(shí)符列表模式或屏蔽位模式。
          為了過(guò)濾出一組標(biāo)識(shí)符,應(yīng)該設(shè)置過(guò)濾器組工作在屏蔽位模式。
          為了過(guò)濾出一個(gè)標(biāo)識(shí)符,應(yīng)該設(shè)置過(guò)濾器組工作在標(biāo)識(shí)符列表模式。
          應(yīng)用程序不用的過(guò)濾器組,應(yīng)該保持在禁用狀態(tài)。
          過(guò)濾器優(yōu)先級(jí)規(guī)則
          位寬為32位的過(guò)濾器,優(yōu)先級(jí)高于位寬為16位的過(guò)濾器
          對(duì)于位寬相同的過(guò)濾器,標(biāo)識(shí)符列表模式的優(yōu)先級(jí)高于屏蔽位模式
          位寬和模式都相同的過(guò)濾器,優(yōu)先級(jí)由過(guò)濾器號(hào)決定,過(guò)濾器號(hào)小的優(yōu)先級(jí)高
          上面的例子說(shuō)明了bxCAN的過(guò)濾器規(guī)則:在接收一個(gè)報(bào)文時(shí),其標(biāo)識(shí)符首先與配置在標(biāo)識(shí)符列表模式下的過(guò)濾器相比較;如果匹配上,報(bào)文就被存放到相關(guān)聯(lián)的FIFO中,并且所匹配的過(guò)濾器的序號(hào)被存入過(guò)濾器匹配序號(hào)中。如同例子中所顯示,報(bào)文標(biāo)識(shí)符跟#4標(biāo)識(shí)符匹配,因此報(bào)文內(nèi)容和FMI4被存入FIFO。
          如果沒(méi)有匹配,報(bào)文標(biāo)識(shí)符接著與配置在屏蔽位模式下的過(guò)濾器進(jìn)行比較。
          如果報(bào)文標(biāo)識(shí)符沒(méi)有跟過(guò)濾器中的任何標(biāo)識(shí)符相匹配,那么硬件就丟棄該報(bào)文,且不會(huì)對(duì)軟件有任何打擾。
          接收郵箱(FIFO)
          在接收到一個(gè)報(bào)文后,軟件就可以訪問(wèn)接收FIFO的輸出郵箱來(lái)讀取它。一旦軟件處理了報(bào)文(如把它讀出來(lái)),軟件就應(yīng)該對(duì)CAN_RFxR寄存器的RFOM位進(jìn)行置1,來(lái)釋放該報(bào)文,以便為后面收到的報(bào)文留出存儲(chǔ)空間。
          中斷
          bxCAN占用4個(gè)專用的中斷向量。通過(guò)設(shè)置CAN中斷允許寄存器(CAN_IER),每個(gè)中斷源都可以單獨(dú)允許和禁用。
          發(fā)送中斷可由下列事件產(chǎn)生:
          ─ 發(fā)送郵箱0變?yōu)榭?,CAN_TSR寄存器的RQCP0位被置1。
          ─ 發(fā)送郵箱1變?yōu)榭眨珻AN_TSR寄存器的RQCP1位被置1。
          ─ 發(fā)送郵箱2變?yōu)榭?,CAN_TSR寄存器的RQCP2位被置1。
          FIFO0中斷可由下列事件產(chǎn)生:
          ─ FIFO0接收到一個(gè)新報(bào)文,CAN_RF0R寄存器的FMP0位不再是‘00’。
          ─ FIFO0變?yōu)闈M的情況,CAN_RF0R寄存器的FULL0位被置1。
          ─ FIFO0發(fā)生溢出的情況,CAN_RF0R寄存器的FOVR0位被置1。
          FIFO1中斷可由下列事件產(chǎn)生:
          ─ FIFO1接收到一個(gè)新報(bào)文,CAN_RF1R寄存器的FMP1位不再是‘00’。
          ─ FIFO1變?yōu)闈M的情況,CAN_RF1R寄存器的FULL1位被置1。
          ─ FIFO1發(fā)生溢出的情況,CAN_RF1R寄存器的FOVR1位被置1。
          錯(cuò)誤和狀態(tài)變化中斷可由下列事件產(chǎn)生:
          ─ 出錯(cuò)情況,關(guān)于出錯(cuò)情況的詳細(xì)信息請(qǐng)參考CAN錯(cuò)誤狀態(tài)寄存器(CAN_ESR)。
          ─ 喚醒情況,在CAN接收引腳上監(jiān)視到幀起始位(SOF)。
          ─ CAN進(jìn)入睡眠模式。
          工作流程大概就是這個(gè)樣子,接著就是一大堆煩人的can寄存器,看了一遍總算有了大概的了解,況且這么多的寄存器要一下子把他們都記住是不可能的。根據(jù)以往的經(jīng)驗(yàn),只要用多幾次,對(duì)寄存器的功能就能記住。
          好了,到讀具體實(shí)驗(yàn)程序的時(shí)候了,這時(shí)候就要打開(kāi)“STM32庫(kù)函數(shù)”的資料。因?yàn)樗锩嬗蠸TM32打包好的庫(kù)函數(shù)的解釋,對(duì)讀程序很有幫助。
          下面是主程序:
          int main(void)
          {
          // int press_count = 0;
          char data = '0';
          int sent = FALSE;
          #ifdef DEBUG
          debug();
          #endif
          /* System Clocks Configuration */
          RCC_Configuration();
          /* NVIC Configuration */
          NVIC_Configuration();
          /* GPIO ports pins Configuration */
          GPIO_Configuration();
          USART_Configuration();
          CAN_Configuration();
          Serial_PutString("rn偉研科技 http://www.gzweiyan.comrn");
          Serial_PutString("CAN testrn");
          while(1){
          if(GPIO_Keypress(GPIO_KEY, BUT_RIGHT)){
          GPIO_SetBits(GPIO_LED, GPIO_LD1);//檢測(cè)到按鍵按下
          if(sent == TRUE)
          continue;
          sent = TRUE;
          data++;
          if(data > 'z')
          data = '0';
          CAN_TxData(data);
          }
          else{//按鍵放開(kāi)
          GPIO_ResetBits(GPIO_LED, GPIO_LD1);
          sent = FALSE;
          }
          }
          }
          前面的RCC、NVIC、GPIO、USART配置和之前的實(shí)驗(yàn)大同小異,關(guān)鍵是分析CAN_Configuration()函數(shù)如下:
          void CAN_Configuration(void)//CAN配置函數(shù)
          {
          CAN_InitTypeDef CAN_InitStructure;
          CAN_FilterInitTypeDef CAN_FilterInitStructure;
          /* CAN register init */
          CAN_DeInit();
          // CAN_StructInit(&CAN_InitStructure);
          /* CAN cell init */
          CAN_InitStructure.CAN_TTCM=DISABLE;//禁止時(shí)間觸發(fā)通信模式
          CAN_InitStructure.CAN_ABOM=DISABLE;//,軟件對(duì)CAN_MCR寄存器的INRQ位進(jìn)行置1隨后清0后,一旦硬件檢測(cè)
          //到128次11位連續(xù)的隱性位,就退出離線狀態(tài)。
          CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通過(guò)清除CAN_MCR寄存器的SLEEP位,由軟件喚醒
          CAN_InitStructure.CAN_NART=ENABLE;//DISABLE;CAN報(bào)文只被發(fā)送1次,不管發(fā)送的結(jié)果如何(成功、出錯(cuò)或仲裁丟失)
          CAN_InitStructure.CAN_RFLM=DISABLE;//在接收溢出時(shí)FIFO未被鎖定,當(dāng)接收FIFO的報(bào)文未被讀出,下一個(gè)收到的報(bào)文會(huì)覆蓋原有
          //的報(bào)文
          CAN_InitStructure.CAN_TXFP=DISABLE;//發(fā)送FIFO優(yōu)先級(jí)由報(bào)文的標(biāo)識(shí)符來(lái)決定
          // CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
          CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN硬件工作在正常模式
          CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳躍寬度1個(gè)時(shí)間單位
          CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;//時(shí)間段1為8個(gè)時(shí)間單位
          CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//時(shí)間段2為7個(gè)時(shí)間單位
          CAN_InitStructure.CAN_Prescaler = 9; //(pclk1/((1+8+7)*9)) = 36Mhz/16/9 = 250Kbits設(shè)定了一個(gè)時(shí)間單位的長(zhǎng)度9
          CAN_Init(&CAN_InitStructure);
          /* CAN filter init 過(guò)濾器初始化*/
          CAN_FilterInitStructure.CAN_FilterNumber=0;//指定了待初始化的過(guò)濾器0
          CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定了過(guò)濾器將被初始化到的模式為標(biāo)識(shí)符屏蔽位模式
          CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//給出了過(guò)濾器位寬1個(gè)32位過(guò)濾器
          CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;//用來(lái)設(shè)定過(guò)濾器標(biāo)識(shí)符(32位位寬時(shí)為其高段位,16位位寬時(shí)為第一個(gè))
          CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//用來(lái)設(shè)定過(guò)濾器標(biāo)識(shí)符(32位位寬時(shí)為其低段位,16位位寬時(shí)為第二個(gè)
          CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//用來(lái)設(shè)定過(guò)濾器屏蔽標(biāo)識(shí)符或者過(guò)濾器標(biāo)識(shí)符(32位位寬時(shí)為其高段位,16位位寬時(shí)為第一個(gè)
          CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;//用來(lái)設(shè)定過(guò)濾器屏蔽標(biāo)識(shí)符或者過(guò)濾器標(biāo)識(shí)符(32位位寬時(shí)為其低段位,16位位寬時(shí)為第二個(gè)
          CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;//設(shè)定了指向過(guò)濾器的FIFO0
          CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//使能過(guò)濾器
          CAN_FilterInit(&CAN_FilterInitStructure);
          /* CAN FIFO0 message pending interrupt enable */
          CAN_ITConfig(CAN_IT_FMP0, ENABLE);//使能指定的CAN中斷
          }
          再看看發(fā)送程序:
          TestStatus CAN_TxData(char data)
          {
          CanTxMsg TxMessage;
          u32 i = 0;
          u8 TransmitMailbox = 0;
          /*
          u32 dataLen;
          dataLen = strlen(data);
          if(dataLen > 8)
          dataLen = 8;
          */
          /* transmit 1 message生成一個(gè)信息 */
          TxMessage.StdId=0x00;// 設(shè)定標(biāo)準(zhǔn)標(biāo)識(shí)符
          TxMessage.ExtId=0x1234;// 設(shè)定擴(kuò)展標(biāo)識(shí)符
          TxMessage.IDE=CAN_ID_EXT;// 設(shè)定消息標(biāo)識(shí)符的類型
          TxMessage.RTR=CAN_RTR_DATA;// 設(shè)定待傳輸消息的幀類型
          /* TxMessage.DLC= dataLen;
          for(i=0;i
          TxMessage.Data = data;
          */
          TxMessage.DLC= 1; //設(shè)定待傳輸消息的幀長(zhǎng)度
          TxMessage.Data[0] = data;// 包含了待傳輸數(shù)據(jù)
          TransmitMailbox = CAN_Transmit(&TxMessage);//開(kāi)始一個(gè)消息的傳輸
          i = 0;
          while((CAN_TransmitStatus(TransmitMailbox) != CANTXOK) && (i != 0xFF))//通過(guò)檢查CANTXOK位來(lái)確認(rèn)發(fā)送是否成功
          {
          i++;
          }
          return (TestStatus)ret;
          }
          CAN_Transmit()函數(shù)的操作包括:
          1. [選擇一個(gè)空的發(fā)送郵箱]
          2. [設(shè)置Id]*
          3. [設(shè)置DLC待傳輸消息的幀長(zhǎng)度]
          4. [請(qǐng)求發(fā)送]
          請(qǐng)求發(fā)送語(yǔ)句:
          CAN->sTxMailBox[TransmitMailbox].TIR |= TMIDxR_TXRQ;//對(duì)CAN_TIxR寄存器的TXRQ位置1,來(lái)請(qǐng)求發(fā)送
          發(fā)送方面搞定了,但接收方面呢?好像在主程序里看不到有接收的語(yǔ)句。立刻向師兄求救。
          原來(lái)是用來(lái)中斷方式來(lái)接收數(shù)據(jù),原來(lái)它和串口一樣可以有兩種方式接收數(shù)據(jù),一種是中斷方式一種是輪詢方式,若采用輪詢方式則要調(diào)用主函數(shù)的CAN_Polling(void)函數(shù)。
          接著又遇到一個(gè)問(wèn)題,為什么中斷函數(shù)CAN_Interrupt(void)的最后要關(guān)中斷呢?
          因?yàn)橐坏┩鵉IFO存入1個(gè)報(bào)文,硬件就會(huì)更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位為1,那么就會(huì)產(chǎn)生一個(gè)中斷請(qǐng)求。所以中斷函數(shù)執(zhí)行完后就要清除FMPIE標(biāo)志位。這時(shí)我才回想起來(lái),原來(lái)我對(duì)CAN的理解還不夠,對(duì)程序設(shè)計(jì)的初衷不夠明確,于是我重新看了一遍CAN的工作原理,這時(shí)后我發(fā)現(xiàn)比以前容易理解了,可能是因?yàn)榭戳顺绦蛞院笾懒舜蟾诺牧鞒蹋缓罂促Y料就有了針對(duì)性。
          發(fā)送者以廣播的形式把報(bào)文發(fā)送給所有的接收者(注:不是一對(duì)一通信,而是多機(jī)通信)節(jié)點(diǎn)在接收?qǐng)?bào)文時(shí)-根據(jù)標(biāo)識(shí)符的值-決定軟件是否需要該報(bào)文;如果需要,就拷貝到SRAM里;如果不需要,報(bào)文就被丟棄且無(wú)需軟件的干預(yù)。一旦往FIFO存入1個(gè)報(bào)文,硬件就會(huì)更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位為1,那么就會(huì)產(chǎn)生一個(gè)中斷請(qǐng)求。所以中斷函數(shù)執(zhí)行完后就要清除FMPIE標(biāo)志位。


          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();