1. 前言
bxCAN是STM32系列最穩(wěn)定的IP核之一,無論有哪個(gè)新型號(hào)出來,這個(gè)IP核基本未變,可見這個(gè)IP核的設(shè)計(jì)是相當(dāng)成熟的。本文所講述的內(nèi)容屬于這個(gè)IP核的一部分,掌握了本文所講內(nèi)容,就可以很方便地適用于所有STM32系列中包含bxCAN外設(shè)的型號(hào)。有關(guān)bxCAN的過濾器部分的內(nèi)容在參考手冊中往往看得“不甚明白“,本文就過濾器的4種工作模式進(jìn)行詳細(xì)講解并使用具體的代碼進(jìn)行演示,這些代碼都進(jìn)行過實(shí)測驗(yàn)證通過的,希望能給讀者對于bxCAN過濾器有一個(gè)清晰的理解。
在這里,我們可以將CAN總線看成一個(gè)廣播消息通道,上面?zhèn)鬏斨鞣N類型的消息,好比報(bào)紙,有體育新聞,財(cái)經(jīng)新聞,政治新聞,還有軍事新聞,每個(gè)人都有自己的喜好,不一定對所有新聞都感興趣,因此,在看報(bào)紙的時(shí)候,一般人都是只看自己感興趣的那類新聞,而過濾掉其他不感興趣的內(nèi)容。那么我們一般是怎么過濾掉那些不感興趣的內(nèi)容的呢?下面有兩種方法來實(shí)現(xiàn)這個(gè)目的:
第一種方法:
每次看報(bào)紙時(shí),你都看下每篇文章的標(biāo)題,如果感興趣則繼續(xù)看下去,如果不感興趣,則忽略掉。
第二種方法:
你告訴郵遞員,你只對財(cái)經(jīng)新聞感興趣,請只將財(cái)經(jīng)類報(bào)紙送過來,其他的就不要送過來了,就這樣,你看到的內(nèi)容必定是你感興趣的財(cái)經(jīng)類新聞。
上面那種方法好呢?很明顯,第二種方法是最好的,因?yàn)槟悴挥米约好看闻袛嗄男┬侣剝?nèi)容是你感興趣的,可以免受“垃圾”新聞干擾,從而可以節(jié)省時(shí)間忙其他事。bxCAN的過濾器就是采用上述第二種方法,你只需要設(shè)置好你感興趣的那些CAN報(bào)文ID,那么MCU就只能收到這些CAN報(bào)文,是從硬件上過濾掉,完全不需要軟件參與進(jìn)來,從而節(jié)省了大大節(jié)省了MCU的時(shí)間,可以更加專注于其他事務(wù),這個(gè)就是bxCAN過濾器的意義所在。
2.2.兩種過濾模式(列表模式與掩碼模式)假設(shè)我們是bxCAN這個(gè)IP的設(shè)計(jì)者,現(xiàn)在由我們來設(shè)計(jì)過濾器,那么我們該如何設(shè)計(jì)呢?
首先我們是不是很快就會(huì)想到只要準(zhǔn)備好一張表,把我們需要關(guān)注的所有CAN報(bào)文ID寫上去,開始過濾的時(shí)候只要對比這張表,如果接收到的報(bào)文ID與表上的相符,則通過,如果表上沒有,則不通過,這個(gè)就是簡單的過濾方案。恭喜你!bxCAN過濾器的列表模式采用的就是這種方案。
但是,這種列表方案有點(diǎn)缺陷,即如果我們只關(guān)注一個(gè)報(bào)文ID,則需要往列表中寫入這個(gè)ID,如果需要關(guān)注兩個(gè),則需要寫入兩個(gè)報(bào)文ID,如果需要關(guān)注100個(gè),則需要寫入100個(gè),如果需要1萬個(gè),那么需要寫入1萬個(gè),可問題是,有這個(gè)大的列表供我們使用嗎?大家都知道,MCU上的資源是有限的,不可能提供1萬個(gè)或更多,甚至100個(gè)都嫌多。非常明顯,這種列表的方式受到列表容量大小的限制,實(shí)際上,bxCAN的一個(gè)過濾器若工作在列表模式下,scale為32時(shí),每個(gè)過濾器的列表只能寫入兩個(gè)報(bào)文ID,若scale為16時(shí),每個(gè)過濾器的列表最多可寫入4個(gè)CAN ID,由此可見,MCU的資源是非常非常有限的,并不能任我們隨心所欲。因此,我們需要考慮另外一種替代方案,這種方案應(yīng)該不受到數(shù)量限制。
下面假設(shè)我們是古時(shí)候一座城鎮(zhèn)的守衛(wèi),城主要求只有1156年出生的人才可以進(jìn)城,我們又該如何執(zhí)行呢?假設(shè)古時(shí)候的人也有類似今天的身份證(...->_<-…),大家都知道,身份份證號(hào)碼中有4位是表示出生年月,如下圖:
圖 1 18位身份證號(hào)碼的各位定義
如上圖,身份證中第7~10這4位數(shù)表示的是出生年份,那么,我們可以這么執(zhí)行:
檢查想要進(jìn)城的所有人的身份證號(hào)碼的第7~10位數(shù)字,如果這個(gè)數(shù)字依次為1156則可以進(jìn)入,否則則不可以,至于身份證號(hào)碼的其他位則完全不關(guān)心。假如過幾天城主放寬進(jìn)城條件為只要是1150年~1160前的人都可以進(jìn)城,那么,我們就可以只關(guān)注身份證號(hào)碼的第7~9這3位數(shù)是否為115就可以了,對不對?這樣一來,我們就可以非常完美地執(zhí)行城主的要求了。
再變下,假設(shè)現(xiàn)在使用機(jī)器來當(dāng)守衛(wèi),不再是人來執(zhí)行這個(gè)“篩選”工作。機(jī)器是死的,沒有人那么靈活,那么機(jī)器又該如何執(zhí)行呢?
對于機(jī)器來說,每一步都得細(xì)化到機(jī)器可以理解的程度,于是我們可以作如下細(xì)化:
第一步:獲取想進(jìn)城的人的身份證號(hào)碼
第二步:只看獲取到身份證的第7~9位,其他位忽略
第三步:將忽略后的結(jié)果與1156進(jìn)行比較
第四步:比較結(jié)果相同則通過,不同則不能通過
這種方式,我們稱之為掩碼模式。
2.3.驗(yàn)證碼與屏蔽碼仔細(xì)查看上面4個(gè)步驟,這不就是C代碼中的if語句嗎?如下:
if(x&y==z)//x表示待檢查身份證號(hào)碼,y表示只關(guān)注第7~9位的屏蔽碼,Z則為1156,這里叫做驗(yàn)證碼
{
//可以通過
}
else
{
//不可以通過
}
對于機(jī)器來說,我們要為它準(zhǔn)備好兩張紙片,一片寫上屏蔽碼,另一片紙片寫上驗(yàn)證碼,屏蔽碼上相應(yīng)位為1時(shí),表示此位需要與驗(yàn)證碼對應(yīng)位進(jìn)行比較,反之,則表示不需要。機(jī)器在執(zhí)行任務(wù)的時(shí)候先將獲取的身份證號(hào)碼與屏蔽碼進(jìn)行“與”操作,再將結(jié)果與驗(yàn)證碼的進(jìn)行比較,根據(jù)判斷是否相同來決定是否通過。整個(gè)判別流程如下所示:
圖 2 掩碼模式的計(jì)算過程
從上圖可以很容易地理解屏蔽碼與驗(yàn)證碼的含義,這樣一來,能通過的結(jié)果數(shù)量就完全取決于屏蔽碼,設(shè)得寬,則可以通過的多(所有位為0,則不過任何過濾操作,則誰都可以通過),設(shè)得窄,則通過的少(所有位設(shè)為1,則只有一個(gè)能通過)。那么知道這個(gè)有什么用呢?因?yàn)閎xCAN的過濾器的掩碼模式就是采用這種方式,在bxCAN中,分別采用了兩個(gè)寄存器(CAN_FiR1,CAN_FiR2)來存儲(chǔ)屏蔽碼與驗(yàn)證碼,從而實(shí)現(xiàn)掩碼模式的工作流程的。這樣,我們就知道了bxCAN過濾器的掩碼模式的大概工作原理。
但是,我們得注意到,采用掩碼模式的方式并不能精確的對每一個(gè)ID進(jìn)行過濾,打個(gè)比方,還是采用之前的守衛(wèi)的例子,假如城主要求只有1150~1158年出生的人能通過,那么,若我們還是才用掩碼模式,那么掩碼就設(shè)為第7~9位為”1”,對應(yīng)的,驗(yàn)證碼的7~9位分別為”115”,這樣就可以了。但是,仔細(xì)一想,出生于1159的人還是可以通過,是不是?但總體來說,雖然沒有做到精確過濾,但我們還是能做到大體過濾的,而這個(gè)就是掩碼模式的缺點(diǎn)了。在實(shí)際應(yīng)用時(shí),取決于需求,有時(shí)我們會(huì)同時(shí)使用到列表模式和掩碼模式,這都是可能的。
綜合之前所述,下面我們來對比一下列表模式與掩碼模式這兩種模式的優(yōu)缺點(diǎn)。
1986 年德國電氣商BOSCH公司開發(fā)出面向汽車的CAN 通信協(xié)議,剛開始的時(shí)候,CAN ID定義為11位,我們稱之為標(biāo)準(zhǔn)格式,ISO11898-1標(biāo)準(zhǔn)中CAN的基本格式如下圖所示:
圖 3 標(biāo)準(zhǔn)CAN報(bào)文格式定義
如上圖所示,標(biāo)準(zhǔn)CAN ID存放在上圖ID18~ID28中,共11位。隨著工業(yè)發(fā)展,后來發(fā)現(xiàn)11位的CAN ID已經(jīng)不夠用,于是就增加了18位,擴(kuò)展CAN ID到29位,如下圖所示:
圖 4 擴(kuò)展CAN報(bào)文格式定義
從上圖對比擴(kuò)展CAN報(bào)文與標(biāo)準(zhǔn)CAN報(bào)文,發(fā)現(xiàn)在仲裁域部分,擴(kuò)展CAN報(bào)文的CAN ID包含了base Identifier與extension Identifier,即基本ID與擴(kuò)展ID,而標(biāo)準(zhǔn)CAN報(bào)文的CAN ID部分只包含基本ID,擴(kuò)展ID(ID0~ID17)被放在基本ID的右方,也就是說,屬于低位。知道這些有什么用呢?至少我們可以得到這兩條信息:
標(biāo)準(zhǔn)ID一般小于或等于<=0x7FF(11位),只包含基本ID。
對于擴(kuò)展CAN的低18位為擴(kuò)展ID,高11位為基本ID。
例如標(biāo)準(zhǔn)CAN ID 0x7E1,二進(jìn)制展開為0b 0[111 1110 0001],只有中括號(hào)內(nèi)的11位才有效,其全部是基本ID。
再例如擴(kuò)展CAN ID 0x1835f107,二進(jìn)制展開為0b 000[1 1000 0011 10][01 11110001 0000 0111],只有紅色中括號(hào)和綠色中括號(hào)內(nèi)的位才有效,總共29位,左邊紅色中括號(hào)中的11位為基本ID,右邊綠色中括號(hào)內(nèi)的18位為擴(kuò)展ID,請記住這個(gè)信息!知道這個(gè)之后,我們可以很方便地將一個(gè)CANID拆分成基本ID和擴(kuò)展ID,這個(gè)也將在后續(xù)的內(nèi)容中多次用到,再次留意一下,擴(kuò)展ID是位于基本ID的右方,在擴(kuò)展CAN ID的構(gòu)成中,擴(kuò)展ID位于低18位,而基本ID位于高11位,于是要獲取一個(gè)擴(kuò)展CANID的基本ID,就只需要將這個(gè)CANID右移18位(這種算法后續(xù)將多次用到,請務(wù)必記住!)。
3. bxCAN的過濾器的解決方案終于進(jìn)入到正題了!前面已經(jīng)介紹了過濾器的列表模式與掩碼模式,以及掩碼模式下的屏蔽碼與驗(yàn)證碼的含義,還介紹了標(biāo)準(zhǔn)CAN ID與擴(kuò)展CAN ID的組成部分。現(xiàn)在我們終于要站在bxC