<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 牛人業(yè)話(huà) > 妙用結構體 簡(jiǎn)化報文封裝和解析

妙用結構體 簡(jiǎn)化報文封裝和解析

作者:馬步 時(shí)間:2020-04-13 來(lái)源:電子產(chǎn)品世界 收藏

佛門(mén)里有句話(huà):諸法無(wú)自性,盡隨汝心轉。就是說(shuō),同樣一個(gè)東西,在不同的人眼中,呈現的是不同的印象。

本文引用地址:http://dyxdggzs.com/article/202004/411937.htm

比如,同樣是榴蓮,有人視為美味,直流口水,有人卻覺(jué)得聞起來(lái)臭穢,吃起來(lái)反胃,正所謂汝之蜜糖,彼之砒霜。

這一點(diǎn)倒是和“一千個(gè)讀者的眼中就有一千個(gè)哈姆雷特”有點(diǎn)異曲同工之妙。

同樣的東西,在不同使用者手中也能發(fā)揮不同的作用。比如倚天劍,張無(wú)忌拿它主持武林正義,護佑天下蒼生,滅絕師太卻拿它發(fā)泄更年期的怒火,切蘿卜似地大殺四方。

比如中的,有的人輕車(chē)熟路,信手拈來(lái),經(jīng)??滓壹核频亍澳憧芍?a class="contentlabel" href="http://dyxdggzs.com/news/listbylabel/label/結構體">結構體和聯(lián)合體有幾種用法?”

有的人卻笨手笨腳,不得章法。

說(shuō)他不會(huì )用吧,他便漲紅了臉,額上的青筋條條綻出,爭辯道:“用得不好不能算不會(huì )用。。。不用。。。碼農的事,能說(shuō)不會(huì )用嗎?”接著(zhù)便是難懂的話(huà),什么“不同的變量干嘛揉在一起”,什么“物以類(lèi)聚人以群分”之類(lèi),引得眾人都哄笑起來(lái),辦公室里充滿(mǎn)了快活的空氣。

灑家向來(lái)中規中矩,也沒(méi)研究過(guò)結構體到底有幾種用法,直到有一天,用它解決了工作中的一個(gè)大問(wèn)題,才領(lǐng)會(huì )了它的妙用。

代碼交接也許是碼農最不愿意干的事情之一了,尤其是要接過(guò)一個(gè)要離職的“兄弟”的代碼的時(shí)候。

當其時(shí)也,真個(gè)是左右為難。

卡得嚴一點(diǎn)吧,害怕傷交情,人都要走了,好說(shuō)好散,何必在這個(gè)時(shí)候讓人為難?放松一點(diǎn)吧,苦的是自己,人都要走了,一拍兩散,他甩下的鍋有那么容易刷完?

總之,一邊是交情,一邊是心情,左右都不是,為難了自己。該為他想吧,該為自己想吧,我已糾結地不可自拔。

當小韓離職、領(lǐng)導讓我交接他的代碼時(shí),我陷入的便是這樣的困境。

小韓交接給我的是一個(gè)半成品的電動(dòng)防夾車(chē)窗控制器,雖然一時(shí)半會(huì )我還看不大懂他的防夾算法,但是應用部分還是比較容易理解的。待我沉下心去一看,我很快被代碼中此起彼伏的位操作語(yǔ)句淹沒(méi)了。

代碼里到處涌現的這些位操作是干嘛的呢?原來(lái),這個(gè)產(chǎn)品是個(gè)CAN節點(diǎn),這些位操作是用來(lái)提取CAN報文里的某個(gè)“信號”,或者給CAN報文的某個(gè)“信號”賦值的。

這里面實(shí)際上牽扯到一個(gè)挺麻煩的事情,因為,傳統的CAN信號讀取和賦值方法以報文字節數組為操作對象,讀取某個(gè)CAN信號或者對某個(gè)CAN信號賦值時(shí),確實(shí)需要對報文字節數組中的某個(gè)字節進(jìn)行位操作。

但是,根據具體應用不同,一個(gè)CAN節點(diǎn)需要讀取和賦值的CAN信號可能多達數十個(gè)甚至上百個(gè),這種位操作方式使得解析和賦值CAN信號的工作非常繁重,而且容易出錯。當CAN節點(diǎn)功能升級造成網(wǎng)絡(luò )矩陣表發(fā)生改變時(shí),CAN信號解析和賦值操作也會(huì )隨CAN信號位置或長(cháng)度的變化而變化,這時(shí)又會(huì )造成大量的修改操作。

也就是說(shuō),且不說(shuō)小韓的半成品代碼里是不是埋了雷,就是以后要做一點(diǎn)修改時(shí),也會(huì )很麻煩。

這可咋整?

進(jìn)一步行文之前,還是有必要先給大家科普一下。

在CAN網(wǎng)路中,CAN報文是底層通信接收和發(fā)送的主體,每條CAN報文中的數據場(chǎng)為8個(gè)字節。在這八個(gè)字節里,有很多“信號”,這些信號一般是位形式,比如車(chē)窗命令可以用一個(gè)2位的信號表示-01上升10下降11停止。

這么說(shuō)吧,從“通信”的角度,報文收發(fā)的操作對象是“字節形式”的報文數據,但是從“邏輯”的角度,應用的操作對象是“位形式”的CAN信號。

一邊是字節形式的報文數據,一邊是位形式的CAN信號,顯然需要通過(guò)一種手段把它們聯(lián)系起來(lái)。

位操作當然是手段之一。

就像小韓在代碼里寫(xiě)的那樣,先把CAN報文寄存器里的字節形式的數據賦值給具體報文中的某個(gè)字節,比如:

WDW_CMD_REQ[0]=(unsigned char)(CANmsgReceiveNow[1]>>8);

再用位操作提取該報文該字節里面的信號,比如:

Lf_cmd=WDW_CMD_REQ[0]&0x03;

在寫(xiě)代碼和讀代碼時(shí),位操作畢竟比不得直接的加、減、邏輯、賦值操作那樣容易理解,但是,程序員的心一般都比較大,應該不怕自己人讀時(shí)頭大。

而且,就算如前文所說(shuō),信號在字節中的位置發(fā)生了變化,無(wú)非是多費點(diǎn)腦汁,重寫(xiě)一下這個(gè)位操作語(yǔ)句就行了。

總之,位操作是麻煩了點(diǎn),但是好像也不是多大的硬傷。

好吧,如果你沒(méi)有覺(jué)得哪里有什么不對勁,請你思考一下這個(gè)問(wèn)題:

每個(gè)報文對應八個(gè)字節,這八個(gè)字節里可能有二三十個(gè)信號,如果每個(gè)信號都定義一個(gè)變量,一條報文就差不多消耗三十來(lái)個(gè)字節的RAM,如果報文多了,會(huì )消耗多少RAM資源呢?要知道,在MCU里面,RAM可算是寸土寸金吶!

信號對應的RAM資源其實(shí)是可以省掉的!方法就是本文要說(shuō)的聯(lián)合體和結構體。

聯(lián)合體可以節省RAM空間,這是里的常識??墒?,怎么把字節形式和位形式“聯(lián)合”為一體呢?

方法就是根據報文的信號矩陣設計信號組結構體。即根據網(wǎng)絡(luò )矩陣表給出的每個(gè)報文的所有CAN信號的名稱(chēng)、起始位和長(cháng)度信息,每個(gè)報文都設計一個(gè)由一組位信號組成的結構體。

這里首先要注意你所用處理器的大小端模式,看看是先定義第一個(gè)字節里的信號,還是先定義最后一個(gè)字節里的信號。然后根據信號的占位(第幾個(gè)字節的哪幾位),把它定義在相應的位置,如果在報文里有空位,比如說(shuō)第二個(gè)字節的0-3位沒(méi)有定義,這時(shí)也要以占位符信號的形式把它定義出來(lái)。

然后為每個(gè)報文定義一個(gè)聯(lián)合體類(lèi)型。聯(lián)合體有兩個(gè)成員變量,一個(gè)是數組變量,一個(gè)是上述信號組結構體變量。根據聯(lián)合體的定義,數組變量和信號組結構體變量的尺寸相同,存放于相同的地址空間(同一個(gè)RAM地址)里,無(wú)論誰(shuí)發(fā)生了變化,另一方也會(huì )同步發(fā)生改變。

在這個(gè)聯(lián)合體中,數組變量是以單字節類(lèi)型定義的數組,存儲字節形式的報文數據,它用于報文的收發(fā),對應于底層通信。

信號組結構體變量是以上述信號組結構體類(lèi)型定義的結構體,存儲信號組形式的報文數據,它用于信號的解析和封裝,對應于上層應用。

1586754731303299.png

報文聯(lián)合體和信號組結構體內存空間示意圖

CAN節點(diǎn)接收報文并放入報文緩沖區后,進(jìn)行報文解析時(shí),首先根據報文ID,找出對應的報文,然后將報文緩沖區當前報文的數據寫(xiě)入對應的報文聯(lián)合體變量的數組變量中,由于聯(lián)合體字節數組和聯(lián)合體信號組結構體位于相同的地址空間上,數組變量的內容更新直接更新了該聯(lián)合體變量中的信號組結構體變量的內容,當提取和解析CAN信號時(shí),直接讀取該報文聯(lián)合體中的結構體中定義的信號即可。

當需要發(fā)送報文時(shí),如果需要賦值信號,直接賦值該報文聯(lián)合體中的結構體中定義的信號,不需要進(jìn)行位操作對報文數據進(jìn)行封裝,然后將該報文聯(lián)合體中的字節數組填充到CAN控制器的發(fā)送寄存器中,啟動(dòng)CAN控制器的發(fā)送就可以完成報文的發(fā)送。

這種實(shí)現方案是不是很酷?Super Cool!

這種對結構體和聯(lián)合體的妙用,只需要在定義結構體的時(shí)候膽大心細一些,便可以將CAN信號的解析及封裝畢其功于一役,之后的工作就像那橋邊姑娘,風(fēng)華模樣,落落大方了。

如果是底層報文收發(fā),你就對聯(lián)合體中的數組形式的字節變量進(jìn)行操作,如果是應用層CAN信號的讀取和賦值,你就對聯(lián)合體中信號組結構體形式的位變量進(jìn)行操作。

有了聯(lián)合體,報文里字節形式的數據變化后,位形式的信號量自動(dòng)發(fā)生變化,直接拿來(lái)用即可。反之,在應用中對某個(gè)位形式的信號更新賦值了以后,報文里的字節數據自動(dòng)發(fā)生變化,該發(fā)送時(shí)直接發(fā)送即可!

再也沒(méi)有惱人的位操作了,是不是非常地神清氣爽?

總之,假輿馬者,非利足也,而致千里;假舟楫者,非能水也,而絕江河。君子生非異也,善假于物也!

就在于這個(gè)善假于物也!



關(guān)鍵詞: C語(yǔ)言 結構體

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>