色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深度解析鏈表在STM32中的應用

GReq_mcu168 ? 來源:開源博客 ? 作者:Firefly_cjd ? 2021-05-02 10:33 ? 次閱讀

1、為何引入鏈表

在程序中經常面臨一個問題,我們需要保存一定數量的對象,但是對象數目是不確定的,或者說是隨時增加或減少的。這時候最簡單的方法是創建一個足夠大的數組,用來存儲這些對象。我最近開發一個項目就遇到類似的問題,下面我把問題簡化一下。

需求:通過PC下發一些矩形的坐標和寬高信息,每個區域有個ID編號,并在這些矩形內填充一定的數據。

通常情況下,最簡單易懂的做法是,限制最多5個區域,每個區域存儲1K數據。因此設置了這樣的一個結構體(類似于面向對象語言里說的成員屬性)。

typedef struct Area_Inf{ uint8_t ID; uint8_t X; uint8_t Y; uint8_t Width; uint8_t Height; uint8_t data_len;}Area_Inf_Typedef;

然后定義結構體的實體。

#define Area_Num 5#define Area_cache 1024

Area_Inf_Typedef Area_Info[Area_Num];uint8_t Area_Data[Area_Num*Area_cache];//存儲區域的數據

/*找到ID為5的區域,并將數據拷貝出去*/void main(){ uint8_t i; uint8_t data[1024]; for(i = 0;i 《 Area_Num;i++) { if(Area_Info[i].ID == 5) { memcpy(data,&Area_Data[i*Area_cache ],Area_Info[i].data_len); } }}

上面這種做法是最簡單易懂的,但不靈活,比如有客戶要求10個區域,但是每個區域存儲的數據很少,根本用不到1K。雖然上面的程序已經使用了宏定義,只需要修改宏定義就能實現要求。但這意味著不同的客戶,需要編譯不同的固件。

#define Area_Num 10#define Area_cache 512

這樣的程序存在的問題:

1、在內存資源很緊缺的單片機程序中,當區域數據很少時,這種程序的處理方法浪費了大量的內存空間。

2、數值固定,需要存儲更多區域,即使還有內存,還是需要修改宏定義,重新編譯固件,不靈活。

這時需要引入鏈表來解決這個問題。

2、鏈表實現

鏈表實際上是線性表的鏈式存儲結構,與數組不同的是,它是用一組任意的存儲單元來存儲線性表中的數據,存儲單元不一定是連續的,且鏈表的長度不是固定的,鏈表數據的這一特點使其可以非常的方便地實現節點的插入和刪除操作。鏈表的每個元素稱為一個節點,每個節點都可以存儲在內存中的不同的位置,為了表示每個元素與后繼元素的邏輯關系,以便構成“一個節點鏈著一個節點”的鏈式存儲結構,除了存儲元素本身的信息外,還要存儲其直接后繼信息,因此,每個節點都包含兩個部分,第一部分稱為鏈表的數據區域,用于存儲元素本身的數據信息。

6ee7ead4-9e2c-11eb-8b86-12bb97331649.png

對于上面的問題,我們使用鏈表解決,需要配合內存管理才能實現。內存管理這一塊,大家可以自己編寫內存管理驅動,也可以使用C庫的malloc和free函數。如何字節編寫內存管理驅動不是本文的重點,下文將使用C庫的malloc和free函數進行內存管理。

使用鏈表的方式,在原有的成員屬性結構體的前提上,還要再封裝多一層鏈表管理。以單向鏈表為例:

typedef struct Area_Inf{ uint8_t ID; uint8_t X; uint8_t Y; uint8_t Width; uint8_t Height; uint8_t data_len; uint8_t* Area_Data;}Area_Inf_Typedef;

typedef struct Area_List_Inf{ Area_Inf_Typedef *Area_Inf; struct Area_List_Inf *next_Area_Inf; //用于指向下一個}Area_List_Inf_Typedef;

Area_List_Inf_Typedef *Head_Area_List; //鏈表的頭指針

由于在定義的時候,只定義了一個頭指針,那么它也只是個指向了Area_List_Inf_Typedef也就是鏈表結構體的指針,同樣沒有內存空間,在沒有創建新增鏈表之前,它是一個野指針。

所以,在具體應用之前,需要先執行一個初始化操作,也就是申請空間給鏈表管理結構體,然后頭指針指向這個空間。

/*** @brief 動態區鏈表初始化* @return int */int Area_List_Init(void){ //申請鏈表類型大小的空間,并讓頭指針指向它 Head_Area_List = (Area_List_Inf_Typedef*)malloc(sizeof(Area_List_Inf_Typedef)); if(Head_Area_List == NULL) return false; //同時要標記下一個信息為空 Head_Area_List-》next_Area_Inf = NULL; return true;}

通過PC下發一個新的區域信息后,增加新區域到鏈表末尾。

/*** @brief 在鏈表末尾增加一個區域參數* @param Area_Inf 增加的區域區參數指針* @return int */int Add_Area_ToList(Area_Inf_Typedef *Area_Inf){ Area_List_Inf_Typedef *p = Head_Area_List; while(p-》next_Area_Inf!=NULL) { p = p-》next_Area_Inf; } //先申請鏈表結構體的空間,因為后續還要繼續增加 p-》next_Area_Inf = (Area_List_Inf_Typedef*)malloc(sizeof(Area_List_Inf_Typedef)); if(p-》next_Area_Inf == NULL) return false;//申請不到內存,返回失敗 //指向剛剛申請的空間,并為需要存放的動態區信息申請對應的內存 p = p-》next_Area_Inf; p-》Area_Inf = (Area_Inf_Typedef*)malloc(sizeof(Area_Inf_Typedef)); if(p-》Area_Inf == NULL) { free(p);//由于申請失敗,先前申請的鏈表空間也要釋放 return false; } memcpy(p-》Area_Inf,Area_Inf,sizeof(Area_Inf_Typedef)); /*拷貝數據*/ p-》Area_Inf-》Area_Data = (uint8_t*)malloc(Area_Inf-》data_len); if(p-》Area_Inf-》Area_Data == NULL) { free(p-》Area_Inf); free(p); return false; } memcpy(p-》Area_Inf-》Area_Data,Area_Inf-》Area_Data,Area_Inf-》data_len); //標記這個鏈表的尾部 p-》next_Area_Inf=NULL; //添加成功 return true;}

通過PC下發一個刪除指定ID的區域命令。

/*** @brief 根據區域ID刪除動態區* @param num 區域ID* @return int */int Delete_Area_Accordingn_ID(int num){ int res = false; Area_List_Inf_Typedef *p = Head_Area_List; while(p-》next_Area_Inf!=NULL) { Area_List_Inf_Typedef *temp = p; p = p-》next_Area_Inf; if(p-》Area_Inf-》ID == num)//匹配到對應的值 { temp-》next_Area_Inf = p-》next_Area_Inf; //釋放內存空間 free(p-》Area_Inf-》Area_Data); free(p-》Area_Inf); free(p); p=temp; res = true; } } return res;}

看了上面的驅動函數,相信大家已經明白,大家可以自行編寫一些驅動,下面我實現的三個簡單函數。

/*** @brief 根據區域ID找到鏈表* @param data_p 鏈表指針* @param num 區域ID編號* @return int */int Find_Area_According_ID(Area_Inf_Typedef **data_p,int num){ Area_List_Inf_Typedef *p = Head_Area_List; while(p-》next_Area_Inf!=NULL) { p = p-》next_Area_Inf; if(p-》Area_Inf-》ID == num)//匹配到對應的值 { *data_p = p-》Area_Inf; return true; } } return false;}/*** @brief 刪除所有區域* */int Delete_All_Area(void){ int res = false; Area_List_Inf_Typedef *p = Head_Area_List; while(p-》next_Area_Inf!=NULL) { Area_List_Inf_Typedef *temp = p; p = p-》next_Area_Inf; temp-》next_Area_Inf = p-》next_Area_Inf; //釋放內存空間 free(p-》Area_Inf-》Area_Data); free(p-》Area_Inf); free(p); p=temp; res = true; } return res;}/*** @brief 打印鏈表信息* */void Printf_Area_Inf(void){ int i=0; Area_List_Inf_Typedef *p = Head_Area_List; printf(“list ID X Y Width Height Area_Data

”); while(p-》next_Area_Inf!=NULL) { p = p-》next_Area_Inf; printf(“ %d %d %d %d %d %d %s

”,i,p-》Area_Inf-》ID,p-》Area_Inf-》X,p-》Area_Inf-》Y,p-》Area_Inf-》Width,p-》Area_Inf-》Height,p-》Area_Inf-》Area_Data); i++; } printf(“----------------------end-----------------------

”);}

3、測試函數

下面編寫一個測試函數,可以測試,鏈表的初始化,增加一個區域,刪除指定區域,根據ID返回區域信息,刪除所有區域接口

/*** @brief 鏈表測試函數* */void list_main(){ int i,j; Area_Inf_Typedef temp; Area_Inf_Typedef **data_p; data_p = NULL; printf(“------------------List test---------------------

”); if(!Area_List_Init( )) { printf(“Memory fail.。

”); } for(i=0;i《5;i++) { temp.ID = i; temp.X = 5+i; temp.Y = i; temp.Width = 10+i; temp.Height = 10+i; temp.data_len = i+1; temp.Area_Data = (uint8_t*)malloc(temp.data_len+1); for(j=0;j《temp.data_len;j++) { temp.Area_Data[j] = j+0x30; } temp.Area_Data[j] = 0; if(!Add_Area_ToList(&temp)) { printf(“Add Area %d Area_Info fail

”,i); } } Printf_Area_Inf(); printf(“

-------------Delete ID of Area is 3-------------

”); Delete_Area_Accordingn_ID(3); Printf_Area_Inf(); temp.ID = 9; temp.data_len = 10; temp.Area_Data = (uint8_t*)malloc(temp.data_len+1); for(j=0;j《temp.data_len;j++) { temp.Area_Data[j] = j+0x30; } temp.Area_Data[j] = 0; if(!Add_Area_ToList(&temp)) { printf(“Add Area %d info fail

”,temp.ID); } printf(“

--------------Add ID of Area is 9---------------

”); Printf_Area_Inf(); Find_Area_According_ID(data_p,2); temp.ID = (*data_p)-》ID; Delete_All_Area(); printf(“

--------------Delete All Area-------------------

”); Printf_Area_Inf(); while(1);}

測試結果

6ef62022-9e2c-11eb-8b86-12bb97331649.png

如果大家手中有板子可以調試,可以看《一文了解串口打印》文章,使用串口打印。如果臨時沒有板子可以debug,可以模擬測試,IAR設置如下:

選擇Simulator調試

6eff06a6-9e2c-11eb-8b86-12bb97331649.png

打開View-》TerminalI/O,就可以看到打印信息

6f0adc92-9e2c-11eb-8b86-12bb97331649.png

編輯:lyn

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • STM32
    +關注

    關注

    2270

    文章

    10895

    瀏覽量

    355744
  • 鏈表
    +關注

    關注

    0

    文章

    80

    瀏覽量

    10558

原文標題:鏈表在STM32中的應用

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    深度解析研華全棧式AI產品布局

    人工智能邁向邊緣智能化的浪潮,研華科技通過“Edge AI+生態協同”戰略推動AIoT 2.0時代的產業落地。本文專訪研華科技產品總監邱柏儒,深度解析研華全棧式AI產品布局、差異化
    的頭像 發表于 12-05 09:51 ?217次閱讀

    GPU深度學習的應用 GPUs圖形設計的作用

    隨著人工智能技術的飛速發展,深度學習作為其核心部分,已經成為推動技術進步的重要力量。GPU(圖形處理單元)深度學習扮演著至關重要的角色,其強大的并行處理能力使得訓練復雜的神經網絡模
    的頭像 發表于 11-19 10:55 ?435次閱讀

    NPU深度學習的應用

    設計的硬件加速器,它在深度學習的應用日益廣泛。 1. NPU的基本概念 NPU是一種專門針對深度學習算法優化的處理器,它與傳統的CPU和GPU有所不同。NPU通常具有高度并行的處理能力,能夠高效地執行
    的頭像 發表于 11-14 15:17 ?510次閱讀

    FPGA深度神經網絡的應用

    、低功耗等特點,逐漸成為深度神經網絡邊緣計算和設備端推理的重要硬件平臺。本文將詳細探討FPGA深度神經網絡的應用,包括其優勢、設計流程
    的頭像 發表于 07-24 10:42 ?656次閱讀

    溫度補償振蕩器TG-3541CE的深度解析

    溫度補償振蕩器TG-3541CE的深度解析
    的頭像 發表于 07-18 17:48 ?320次閱讀

    深度神經網絡雷達系統的應用

    深度神經網絡(Deep Neural Networks,DNN)雷達系統的應用近年來取得了顯著進展,為雷達信號處理、目標檢測、跟蹤以及識別等領域帶來了革命性的變化。以下將詳細探討深度
    的頭像 發表于 07-15 11:09 ?715次閱讀

    深度學習算法集成電路測試的應用

    隨著半導體技術的快速發展,集成電路(IC)的復雜性和集成度不斷提高,對測試技術的要求也日益增加。深度學習算法作為一種強大的數據處理和模式識別工具,集成電路測試領域展現出了巨大的應用潛力。本文將從深度學習算法的基本原理、
    的頭像 發表于 07-15 09:48 ?970次閱讀

    深度學習視覺檢測的應用

    深度學習是機器學習領域中的一個重要分支,其核心在于通過構建具有多層次的神經網絡模型,使計算機能夠從大量數據自動學習并提取特征,進而實現對復雜任務的處理和理解。這種學習方式不僅提高了機器對數據的解釋
    的頭像 發表于 07-08 10:27 ?700次閱讀

    深度學習自動駕駛的關鍵技術

    隨著人工智能技術的飛速發展,自動駕駛技術作為其中的重要分支,正逐漸走向成熟。自動駕駛系統深度學習技術發揮著至關重要的作用。它通過模擬人腦的學習過程,實現對車輛周圍環境的感知、理解和決策。本文將深入探討
    的頭像 發表于 07-01 11:40 ?755次閱讀

    為什么STM32F0 modbus解析接收不到任何數據?

    我看了很久也找不到為什么我的modbus解析接收不到任何數據,求大神幫助下,感激不盡
    發表于 04-25 06:28

    深度解析深度學習下的語義SLAM

    隨著深度學習技術的興起,計算機視覺的許多傳統領域都取得了突破性進展,例如目標的檢測、識別和分類等領域。近年來,研究人員開始視覺SLAM算法引入深度學習技術,使得
    發表于 04-23 17:18 ?1286次閱讀
    <b class='flag-5'>深度</b><b class='flag-5'>解析</b><b class='flag-5'>深度</b>學習下的語義SLAM

    FPGA深度學習應用或將取代GPU

    硬件公司供貨的不斷增加,GPU 深度學習的市場需求還催生了大量公共云服務,這些服務為深度學習項目提供強大的 GPU 虛擬機。 但是顯卡也受硬件和環境的限制。Larzul 解釋說:
    發表于 03-21 15:19

    數組和鏈表在內存的區別 數組和鏈表的優缺點

    內存的存儲方式: 數組是一種連續存儲的數據結構,它將元素存儲相鄰的內存位置。這使得數組的訪問效率高,可以通過下標來直接訪問任何一個元素。 鏈表是一種離散存儲的數據結構,它將元素
    的頭像 發表于 02-21 11:30 ?1022次閱讀

    數組和鏈表有何區別

    數組和鏈表的區別,這個問題,不僅面試中經常遇到,考研的同學也得掌握才行。
    的頭像 發表于 02-19 15:33 ?503次閱讀
    數組和<b class='flag-5'>鏈表</b>有何區別

    XMLHarmonyOS的生成,解析與轉換(下)

    一、XML 解析 對于以 XML 作為載體傳遞的數據,實際使用需要對相關的節點進行解析,一般包括解析 XML 標簽和標簽值、解析 XML
    的頭像 發表于 02-18 10:07 ?735次閱讀
    主站蜘蛛池模板: 免费无遮挡又黄又爽网站| 国产精品女上位在线观看| 亚洲精品tv久久久久久久久久| 两性色午夜视频免费国产| 国产成人无码一区AV在线观看| 中文无码不卡的岛国片国产片| 色即是空之甜性涩爱| 快播性爱电影| 国精产品一区一区三区有限公司| 白丝女仆被强扒内裤| 在线观看视频国产| 亚洲国产欧美在线人成aaaa20| 国产精品福利电影| 99人精品福利在线观看| 一级特黄aa大片欧美| 性色无码AV久久蜜臀| 色噜噜色啪在线视频| 欧美18videosex性欧美老师| 久久成人免费观看全部免费| 国产免费看黄的私人影院| 高h乱np甄宓| 第一次破女初国产美女| AV多人爱爱XXx| 99国产精品偷窥熟女精品视频| 亚洲日韩国产精品乱-久| 胸太大被男同桌吃好爽| 息与子在线交尾中文字幕| 婷婷综合亚洲爱久久| 少妇的肉体AA片免费观看| 日本xxxxxxx| 秋霞午夜理论理论福利无码| 免费精品一区二区三区AA片| 美女张开腿让我了一夜| 脔到她哭H粗话HWWW男男动漫| 久久这里只有热精品18| 久久青青草原综合伊人| 久久热在线视频精品1| 快插我我好湿啊公交车上做| 伦 乱真实故事| 欧美69xxx| 日本xxxxx按摩19|