新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32之CAN ---CAN ID過濾器分析

        STM32之CAN ---CAN ID過濾器分析

        作者: 時間:2016-11-10 來源:網絡 收藏

        1 前言

        CAN協議里,報文的標識符不代表節點的地址,而是跟報文的內容相關的。因此,發送者以廣播的形式把報文發送給所有的接收者。節點在接收報文時,根據標識符(CAN ID)的值決定軟件是否需要該報文;如果需要,就拷貝到SRAM里;如果不需要,報文就被丟棄且無需軟件的干預。
        為滿足這一需求,bxCAN為應用程序提供了14個位寬可變的、可配置的過濾器組(13~0),以便只接收那些軟件需要的報文。硬件過濾的做法節省了CPU開銷,否則就必須由軟件過濾從而占用一定的CPU開銷。每個過濾器組x由2個32位寄存器,CAN_FxR0和CAN_FxR1組成。

        本文引用地址:http://www.104case.com/article/201611/317116.htm

        為了讓大家了解STM32的bxCAN的接收過濾機制,首先大家需要了解幾個概念。

        2 幾個重要的概念

        2.1 過濾器組

        STM32總共提供14個過濾器組來處理CAN接收過濾問題,每個過濾器組包含兩個32位寄存器CAN_FxR0和CAN_FxR1組成,在設置為屏蔽位模式下,其中一個作為標識符寄存器,另一個作為屏蔽碼寄存器。過濾器組中的每個過濾器,編號(叫做過濾器號)從0開始,到某個最大數值(這時最大值并非13,而是取決于14個過濾器組的模式和位寬的設置,當全部配置為位寬為16,且為標識符列表模式時,最大編號為14*4-1=55)。

        2.2 過濾器的過濾模式

        STM32提供兩種過濾模式供用戶設置:屏蔽位模式和標識符列表模式。

        2.2.1 屏蔽位模式

        為了過濾出一組標識符,應該設置過濾器組工作在屏蔽位模式。

        在屏蔽位模式下,標識符寄存器和屏蔽寄存器一起,指定報文標識符的任何一位,應該按照“必須匹配”或“不用關心”處理。

        2.2.2 標識符列表模式

        為了過濾出一個標識符,應該設置過濾器組工作在標識符列表模式。

        在標識符列表模式下,屏蔽寄存器也被當作標識符寄存器用。因此,不是采用一個標識符加一個屏蔽位的方式,而是使用2個標識符寄存器。接收報文標識符的每一位都必須跟過濾器標識符相同。

        2.3 過濾器的位寬

        每個過濾器組的位寬都可以獨立配置,以滿足應用程序的不同需求。根據位寬的不同,每個過濾器組可提供:
        ●1個32位過濾器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
        ●2個16位過濾器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

        2.3 過濾器組的過濾模式和位寬設置

        過濾器組可以通過相應的CAN_FMR寄存器(CAN過濾器主控寄存器)配置。但是不是什么時候都可以直接配置,在配置一個過濾器組前,必須通過清除CAN_FAR寄存器(CAN過濾器激活寄存器)的FACT位,把它設置為禁用狀態。然后才能設置或設置過濾器組的配置。

        • 通過設置CAN_FS1R(CAN過濾器位寬寄存器)的相應FSCx位,可以配置一個過濾器組的位寬。
        • 通過CAN_FM1R(CAN過濾器模式寄存器)的FBMx位,可以配置對應的屏蔽/標識符寄存器的標識符列表模式或屏蔽位模式。(見后續3.2節)

        應用程序不用的過濾器組,應該保持在禁用狀態。

        關于過濾器配置,可參見下圖:

        圖1

        2.4 過濾器匹配序號

        一旦收到的報文被存入FIFO,就可被應用程序訪問。通常情況下,報文中的數據被拷貝到SRAM中;為了把數據拷貝到合適的位置,應用程序需要根據報文的標識符來辨別不同的數據。bxCAN提供了過濾器匹配序號,以簡化這一辨別過程。

        根據過濾器優先級規則,過濾器匹配序號和報文一起,被存入郵箱中。因此每個收到的報文,都有與它相關聯的過濾器匹配序號。

        過濾器匹配序號可以通過下面兩種方式來使用:
        ● 把過濾器匹配序號跟一系列所期望的值進行比較
        ● 把過濾器匹配序號當作一個索引來訪問目標地址
        對于標識符列表模式下的過濾器(非屏蔽方式的過濾器),軟件不需要直接跟標識符進行比較。
        對于屏蔽位模式下的過濾器,軟件只須對需要的那些屏蔽位(必須匹配的位)進行比較即可。
        在給過濾器編號時,并不考慮過濾器組是否為激活狀態。另外,每個FIFO各自對其關聯的過濾器進行編號,如下圖:

        圖2

        2.5 過濾器優先級規則

        根據過濾器的不同配置,有可能一個報文標識符能通過多個過濾器的過濾;在這種情況下,存放在接收郵箱中的過濾器匹配序號,根據下列優先級規則來確定:
        ● 位寬為32位的過濾器,優先級高于位寬為16位的過濾器
        ● 對于位寬相同的過濾器,標識符列表模式的優先級高于屏蔽位模式
        ● 位寬和模式都相同的過濾器,優先級由過濾器號決定,過濾器號小的優先級高

        如下圖:

        圖3

        如上圖,在接收一個報文時,其標識符首先與配置在標識符列表模式下的過濾器相比較;如果匹配上,報文就被存放到相關聯的FIFO中,并且所匹配的過濾器的序號(這時為4)被存入過濾器匹配序號中。如同例子中所顯示,報文標識符跟#4標識符匹配,因此報文內容和FMI4被存入FIFO。

        如果沒有匹配,報文標識符接著與配置在屏蔽位模式下的過濾器進行比較。
        如果報文標識符沒有跟過濾器中的任何標識符相匹配,那么硬件就丟棄該報文,且不會對軟件有任何打擾。

        3 與過濾器相關的寄存器

        3.1 CAN 過濾器主控寄存器 (CAN_FMR)

        地址偏移量: 0x200

        復位值: 0x2A1C 0E01

        注: 該寄存器的非保留位完全由軟件控制。

        圖4

        位31:1保留位,強制為復位值。
        位0FINIT : 過濾器初始化模式
        針對所有過濾器組的初始化模式設置。
        0: 過濾器組工作在正常模式;
        1: 過濾器組工作在初始化模式。

        3.2 CAN 過濾器模式寄存器 (CAN_FM1R)

        地址偏移量: 0x204
        復位值: 0x0000 0000
        注: 只有在設置CAN_FMR(FINIT=1),使過濾器處于初始化模式下,才能對該寄存器寫入。

        圖5

        位31:14保留位,硬件強制為0
        位13:0FBMx : 過濾器模式
        過濾器組x的工作模式。
        0: 過濾器組x的2個32位寄存器工作在標識符屏蔽位模式;
        1: 過濾器組x的2個32位寄存器工作在標識符列表模式。

        3.3 CAN 過濾器位寬寄存器 (CAN_FS1R)

        地址偏移量: 0x20C
        復位值: 0x0000 0000
        注: 只有在設置CAN_FMR(FINIT=1),使過濾器處于初始化模式下,才能對該寄存器寫入。

        圖6

        位31:14保留位,硬件強制為0
        位13:0FSCx : 過濾器位寬設置
        過濾器組x(13~0)的位寬。
        0:過濾器位寬為2個16位;
        1:過濾器位寬為單個32位。

        3.4 CAN 過濾器FIFO關聯寄存器 (CAN_FFA1R)

        地址偏移量: 0x214
        復位值: 0x0000 0000
        注: 只有在設置CAN_FMR(FINIT=1),使過濾器處于初始化模式下,才能對該寄存器寫入。

        圖7

        位31:14保留位,硬件強制為0。
        位13:0FFAx : 過濾器位寬設置
        報文在通過了某過濾器的過濾后,將被存放到其關聯的FIFO中。
        0:過濾器被關聯到FIFO0;
        1:過濾器被關聯到FIFO1。

        3.5 CAN 過濾器激活寄存器 (CAN_FA1R)

        地址偏移量: 0x21C
        復位值: 0x0000 0000

        圖7

        位31:14保留位,硬件強制為0。
        位13:0FACTx : 過濾器激活
        軟件對某位設置1來激活相應的過濾器。只有對FACTx位清0,或對CAN_FMR寄存器的FINIT位設置1后,才能修改相應的過濾器寄存器x(CAN_FxR[0:1])。
        0:過濾器被禁用;
        1:過濾器被激活。

        3.6 CAN 過濾器組x寄存器 (CAN_FiRx) (i=0..13,x=1..2)

        地址偏移量:0x240h..0x2AC
        復位值:未定義位
        注: 共有14組過濾器:i=0..13。每組過濾器由2個32位的寄存器,CAN_FiR[2:1]組成。只有在CAN_FaxR寄存器(CAN過濾器激活寄存器)相應的FACTx位清’0’,或CAN_FMR寄存器(CAN過濾器主控寄存器)的FINIT位為’1’時,才能修改相應的過濾器寄存器。

        圖8

        位31:0FB[31:0] : 過濾器位
        • 當為標識符模式時:
        寄存器的每位對應于所期望的標識符的相應位的電平。
        0: 期望相應位為顯性位;
        1: 期望相應位為隱性位。
        • 當為屏蔽位模式時:
        寄存器的每位指示是否對應的標識符寄存器位一定要與期望的標識符的相應位一致。
        0: 不關心,該位不用于比較;
        1: 必須匹配,到來的標識符位必須與濾波器對應的標識符寄存器位相一致。
        注: 根據過濾器位寬和模式的不同設置,過濾器組中的兩個寄存器的功能也不盡相同。。關于過濾器的映射,功能描述和屏蔽寄存器的關聯,請參見2節標識符過濾。

        屏蔽位模式下的屏蔽/標識符寄存器,跟標識符列表模式下的寄存器位定義相同。

        4 代碼實例

        4.1 CAN ID值的結構分析

        在講到代碼實例之前,首先大家都弄懂一件事,當給定一個CAN ID,如0x1800f001,當然這個是擴展ID,這里要問的是,這個CAN ID的值本身包含兩部分,即基本ID與擴展ID,即么你知道這個擴展ID0x1800f001的哪些位是基本ID,哪些位又是擴展ID?(在基本CANID格式下不存在這個問題)

        在回答這個問題之前我們來看看ISO11898的定義,如下圖:

        圖9

        如上圖,基本格式不存在擴展ID,而擴展格式中ID0~ID17為Extension ID,而ID18~ID28為Base ID.

        因此CAN ID值0x1800f001用二進制表示為:0b 0001 1000 0000 0000 1111 0000 0000 0001,用括號分別區別為:0b 000[1 1000 0000 00][00 1111 0000 0000 0001],紅色部分為擴展ID,藍色部分為基本ID。那么知道這些有什么用呢?接下來的代碼示例中你就會有什么用了。

        4.2 位寬為32位的屏蔽模式

        在此種模式下中過濾多個CAN ID,此時,過濾器包含兩個寄存器,屏蔽碼寄存器和標識符寄存器。此模式下最多只存在一個屏蔽過濾器。

        如下圖所示:

        圖10

        如上圖,上面的ID為標識符寄存器,中間部分的MASK為屏蔽碼寄存器。每個寄存器都是32位的。最下邊顯示的是與CAN ID各位定位的映射關系。由4.1的知識很快可以發現,上圖最下邊的映射關系恰好等于擴展CAN值左移3位再補上IDE(擴展幀標識),RTR(遠程幀標志)。

        因此,我們初步得出這樣的推論:對于一個擴展CAN ID,不能單純地將它看到的一個數,而應該將它看成兩部分,基本ID和擴展ID(當然標準CAN ID只包含基本ID部分),過濾器屏蔽碼寄存器和標識符寄存器也應該看成多個部分,然后問題就變成了如何將CAN ID所表示的各部分如何針對過濾器寄存器各部分對號入座的問題了。

        對號入座的方法多種多樣,但萬變不離其心,主要是掌握其核心思想即可:1:在各種過濾器模式下,CAN ID與寄存器相應位置一定要匹配;2:在屏蔽方式下,屏蔽碼寄存器某位為1表示接收到的CAN ID對應的位必須對驗證碼寄存器對應的位相同。

        下面給出一個代碼例子,假設我們要接收多個ID:0x7e9,0x1800f001,前面為標準ID,后面為擴展ID,要同時能接收這兩個ID,那么該如何設置這個過濾器呢?

        1. CAN_FilterInitTypeDefCAN_FilterInitStructure;
        2. U16std_id=0x7e9;
        3. U32ext_id=0x1800f001;
        4. U32mask=0;
        5. CAN_FilterInit(&CAN_FilterInitStructure);//初始化CAN_FilterInitStructrue結構體變量
        6. CAN_FilterInitStructure.CAN_FilterNumber=0;//設置過濾器組0,范圍為0~13
        7. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//設置過濾器組0為屏蔽模式
        8. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//設置過濾器組0位寬為32位
        9. //標識位寄存器的設置
        10. //ext_id<<3對齊,見上圖9,再>>16取高16位
        11. CAN_FilterInitStructure.CAN_FilterIdHigh=((ext_id<<3)>>16)&0xffff;//設置標識符寄存器高字節。
        12. CAN_FilterInitStructure.CAN_FilterIdLow=(U16)(ext_id<<3)|CAN_ID_EXT;//設置標識符寄存器低字節
        13. //這里也可以這樣設置
        14. //CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5;//設置標識符寄存器高字節.這里為什么是左移5位呢?從上圖可以看出,CAN_FilterIdHigh包含的是STD[0~10]和EXID[13~17],標準CANID本身是不包含擴展ID數據,因此為了要將標準CANID放入此寄存器,標準CANID首先應左移5位后才能對齊.
        15. //CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_EXT;//設置標識符寄存器低字節,這里也可以設置為CAN_ID_STD
        16. //屏蔽寄存器的設置
        17. //這里的思路是先將標準CANID和擴展CANID對應的ID值先異或后取反,為什么?異或是為了找出兩個CANID有哪些位是相同的,是相同的位則說明需要關心,需要關心的位對應的屏蔽碼位應該設置為1,因此需要取反一下。最后再整體左移3位。
        18. mask=(std_id<<18);//這里為什么左移18位?因為從ISO11898中可以看出,標準CANID占ID18~ID28,為了與CAN_FilterIdHigh對齊,應左移2位,接著為了與擴展CAN對應,還應該再左移16位,因此,總共應左移2+16=18位。也可以用另一個方式來理解:直接看Mapping的內容,發現STDID相對EXID[0]偏移了18位,因此左移18位.
        19. mask^=ext_id;//將對齊后的標準CAN與擴展CAN異或后取反
        20. mask=~mask;
        21. mask<<=3;//再整體左移3位
        22. mask|=0x02;//只接收數據幀,不接收遠程幀
        23. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(mask>>16)&0xffff;//設置屏蔽寄存器高字節
        24. CAN_FilterInitStructure.CAN_FilterMaskIdLow=mask&0xffff;//設置屏蔽寄存器低字節
        25. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;//此過濾器組關聯到接收FIFO0
        26. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活此過濾器組
        27. CAN_FilterInit(&CAN_FilterInitStructure);//設置過濾器

        總結可知,當過濾器為屏蔽模式時,標識符寄存器對應的ID內容可為任意一需求接收的ID值,當同時要接收標準幀和擴展幀時,標識符寄存器對應IDE位也隨意設置,屏蔽寄存器的IDE位設置為0,表示不關心標準幀還是擴展幀。而屏蔽寄存器對應的ID內容為各需求接收的ID值依次異或的結果再取反。

        4.3 位寬為32位的標識符列表模式

        在此種模式下,過濾器組包含的兩個寄存器含義一樣,此模式下只多存在兩個標識符列表過濾器如下圖:

        圖11


        1. CAN_FilterInitTypeDefCAN_FilterInitStructure;
        2. U16std_id=0x7e9;
        3. U32ext_id=0x1800f001;
        4. CAN_FilterInit(&CAN_FilterInitStructure);//初始化CAN_FilterInitStructrue結構體變量
        5. CAN_FilterInitStructure.CAN_FilterNumber=0;//設置過濾器組0,范圍為0~13
        6. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;//設置過濾器組0為標識符列表模式
        7. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//設置過濾器組0位寬為32位
        8. //設置屏蔽寄存器,這里當標識符寄存器用
        9. CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5);//為什么左移5位?與上面相同道理,這里不再重復解釋
        10. CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_STD;//設置標識符寄存器低字節,CAN_FilterIdLow的ID位可以隨意設置,在此模式下不會有效。
        11. //設置標識符寄存器
        12. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=((ext_id<<3)>>16)&0xffff;//設置屏蔽寄存器高字節
        13. CAN_FilterInitStructure.CAN_FilterMaskIdLow=((ext_id<<3)&0xffff)|CAN_ID_EXT;//設置屏蔽寄存器低字節
        14. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;//此過濾器組關聯到接收FIFO0
        15. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活此過濾器組
        16. CAN_FilterInit(&CAN_FilterInitStructure);//設置過濾器

        4.4 位寬為16位的屏蔽碼模式

        在此模式下,最多存在兩個屏蔽碼過濾器,如下圖:

        圖12

        由上圖映射可知,最下面的映射只包含STDID0~ID10,因此,此模式下的兩個屏蔽過濾器只能實現對標準ID的過濾。具體代碼就不介紹了,參見上圖的映射即可。

        4.5 位寬為16位的標識符列表模式

        圖13

        在此模式下,由于標識符寄存器的高16位和低16位,屏蔽寄存器的高16位和低16位都用來做標識符寄存器,因此,最多可存在4個標識符過濾器。同樣,只能實現對標準幀的過濾。具體代碼就不介紹了,參見上圖的映射即可。



        關鍵詞: STM32CANID過濾

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 宜兴市| 从化市| 光泽县| 买车| 共和县| 驻马店市| 油尖旺区| 马关县| 泊头市| 荔浦县| 宜兰市| 全州县| 嘉义市| 丁青县| 收藏| 西城区| 澳门| 尼玛县| 岢岚县| 温泉县| 卢湾区| 渭源县| 长顺县| 许昌市| 营口市| 山阴县| 元谋县| 邹城市| 娄烦县| 德庆县| 乌兰察布市| 额济纳旗| 庄河市| 全州县| 都江堰市| 中牟县| 保康县| 伊宁市| 九台市| 平顺县| 滁州市|