在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

            妙用結構體 簡化報文封裝和解析

            作者:馬步 時間:2020-04-13 來源:電子產品世界 收藏

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

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

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

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

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

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

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

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

            灑家向來中規(guī)中矩,也沒研究過結構體到底有幾種用法,直到有一天,用它解決了工作中的一個大問題,才領會了它的妙用。

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

            當其時也,真?zhèn)€是左右為難。

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

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

            當小韓離職、領導讓我交接他的代碼時,我陷入的便是這樣的困境。

            小韓交接給我的是一個半成品的電動防夾車窗控制器,雖然一時半會我還看不大懂他的防夾算法,但是應用部分還是比較容易理解的。待我沉下心去一看,我很快被代碼中此起彼伏的位操作語句淹沒了。

            代碼里到處涌現(xiàn)的這些位操作是干嘛的呢?原來,這個產品是個CAN節(jié)點,這些位操作是用來提取CAN報文里的某個“信號”,或者給CAN報文的某個“信號”賦值的。

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

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

            也就是說,且不說小韓的半成品代碼里是不是埋了雷,就是以后要做一點修改時,也會很麻煩。

            這可咋整?

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

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

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

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

            位操作當然是手段之一。

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

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

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

            Lf_cmd=WDW_CMD_REQ[0]&0x03;

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

            而且,就算如前文所說,信號在字節(jié)中的位置發(fā)生了變化,無非是多費點腦汁,重寫一下這個位操作語句就行了。

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

            好吧,如果你沒有覺得哪里有什么不對勁,請你思考一下這個問題:

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

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

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

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

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

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

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

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

            1586754731303299.png

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

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

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

            這種實現(xiàn)方案是不是很酷?Super Cool!

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

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

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

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

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

            就在于這個善假于物也!



            關鍵詞: C語言 結構體

            評論


            相關推薦

            技術專區(qū)

            關閉