在MDK上建立一個C++的STM32開發(fā)工程
我之前對C++有曲解,總認為C++只適合做上層應用軟件開發(fā),不適用于單片機開發(fā)。一方面是因為C++喜歡來不不就new一個對象。對于內(nèi)存空間非常緊張的單片機,只能望海興嘆。二是C++生成的代碼量較C龐大,效率上可能沒有C高。對于主頻較低的單片機,也用一點勉強。但是,這并不能掩蓋C++的優(yōu)勢。C++是面向?qū)ο蟮某绦蛘Z言,能非常靈活地進行繼承與派生,還能實現(xiàn)多態(tài)。對于較大一點的程序而言,用C作開發(fā),不異于用磚頭砌坐20層的大廈。這樣的大廈既不穩(wěn)定,也不好維護。相反,C++則可以很好地完成這樣大的任務(wù)。但是,你就蓋個兩層樓的小平房,需得著什么房屋框架嗎?也沒必要呀。
總而言之,C與C++各有各的優(yōu)勢,就看你怎么用。
我手頭一有塊STM32的開發(fā)板。于是,我嘗試在MDK上建一個基于C++的Demo工程。板子上有64KB的SRAM,主頻可達72MHz,也差不多了。
想到C++,我就想到了new 這個關(guān)鍵字。這個new 就是從堆里取一塊內(nèi)存空間,并執(zhí)行類的構(gòu)造函數(shù)。
那么這里就要涉及到堆的問題,你必須得告訴程序一個問題:(1)堆在哪里?(2)堆有多大?
以下是我在main()中對堆的實現(xiàn):
- #include
//_init_alloc - #defineHEAP_SIZE(0x3000)
- INT32Uheap_zone[HEAP_SIZE]={0};
- intmain()
- {
- NVIC_Configuration();
- OSInit();
- _init_alloc((INT32U)heap_zone,(INT32U)&heap_zone[HEAP_SIZE-1]);
- CStartTaskstart;
- start.Create();
- OSStart();
- return0;
- }
首先聲明,這個main()所在的文件必須是以.cpp文件,不然編譯當成C語言進行編譯。C++可以調(diào)用C,C不能調(diào)用C++,這點要記住。以上對堆的實現(xiàn)分兩步:
(1)要在SRAM中留一塊空間來做堆。上代就用定義數(shù)組的方式實現(xiàn)。 INT32U heap_zone[HEAP_SIZE] = 0;
(2)告訴程序堆的起止地址。通過調(diào)用 _init_alloc( startAddr,endAddr );
也不一定非要用這做笨絀的方法定義一塊堆空間。我這塊開發(fā)板上還用FSMC擴展了一個512KB的SRAM。那么我可以用這塊空間來做堆空間。如下:
- #include
//_init_alloc - #defineHEAP_BASEBank1_SRAM3_ADDR
- #defineHEAP_TOP(Bank1_SRAM3_ADDR+0x100000)
- intmain()
- {
- NVIC_Configuration();
- FSMC_SRAM_Init();//初始化對SRAM的訪問
- OSInit();
- _init_alloc(HEAP_BASE,HEAP_TOP);//設(shè)置堆空間
- CStartTaskstart;
- start.Create();
- OSStart();
- return0;
- }
SRAM 的首地址就是 HEAP_BASE = Bank1_SRAM3_ADDR , 止地址就是 HEAP_TOP =Bank1_SRAM3_ADDR+0x100000 。
如上調(diào)用完 _init_alloc() 函數(shù)后,你就可以使用 new 進行申請空間與創(chuàng)建對象了。
在工程中凡是 .c 文件都是C源文件,凡是 .cpp 文件都是C++源文件。在將原來部分C語言代碼移植到C++的時候,要在頭文件的開始與終止處添加以下內(nèi)容:
- #ifdef__cplusplus
- extern"C"{
- #endif
- ……//正文
- #ifdef__cplusplus
- }
- #endif
extern "C" { } 用于告訴編譯器,大括號以內(nèi)的東西以C的方式進行編譯。因為原來.C的頭文件被.CPP文件包含了,那么編譯器便按C++的方式進行編譯,導致與原來.C文件中定義的不一致,編譯報錯。
評論