最近因為項目需要開始使用IAR for AVR,我用的是5.40版本的,主要是5.40以上才包括了aTtiny87,至于安裝文件和和諧文件,大家自己找吧,很好找的。
1.編譯報錯如圖所示:
很顯然你沒有使能寄存器的位定義。方法如下:Project ——> Option ——> General Options ——> System(如下圖所示),勾選
Enable bit definitions in I/O-Include files即可
2.MCU型號選擇
如果和我一樣都次都是以空工程創建的話,不過忘了第一步先進Project ——> Option ——> General Options ——> Target選擇所使用的MCU型號,不然編譯免不了要報錯,如下圖所示。
3. 堆棧大小
今天下午編譯一個程序,0錯誤0警告,挺好,可一運行就跑飛,根本不能正常運行。
其實是我沒有正常設置堆棧大小導致的這種問題,尤其是在寫大工程時,這種錯誤出現的概率很高。GCC和IAR分配堆棧的方式不同,IAR先分配堆棧空間,相當于定義一個全局數組為堆棧空間,堆棧初始為堆棧空間最高地址;GCC不用先分配堆棧,自動把RAM剩余空間作為堆棧空間,堆棧初始為RAM最高地址。
先編譯看看自己的程序用了多少ram,在看看總共有多少ram。
然后Project ——> Option ——> Linker ——> List選擇生成LIST文件,并包含stack選項,如下圖所示。
在./Debug/list目錄下,得到.map(可能是.lst等其他格式)文件,用記事本打開,找到以下內容:
****************************************
* *
* CALL GRAPH *
* *
****************************************
->Sub-tree of type: Interrupt function tree that does not make
: indirect calls
CSTACK
| Stack used (prev) : 00000000
01 int_T0_OV
| Stack used (prev) : 00000000
| + function block : 0000000C
......(省略N行)
01 main
| Stack used (prev) : 0000003A
| + function block : 00000000
<-Sub-tree of type: Function tree
| Stack used : 000000E2
找到最大的Stack used,我的就是000000E2,這就是用到的最大的堆棧空間,保守一點,我設置成0x100字節,沒有超過剩余RAM,再重新編譯,運行,仿真器沒有堆棧不足警告,程序也能正常運行了。
如下圖所示:
4. 查看匯編
相信一個優秀的單片機軟件工程師都多多少少會去看看編譯器的匯編代碼,看看有沒有什么問題或者看看編譯器有沒有自作聰明的做些什么
Project ——> Option ——> C/C++ complier ——> List,勾選output assembler files,編譯后則生成離線匯編代碼文件
此時在工程目錄下的Debug-->List即可看到所有參加編譯的C文件對應的匯編文件,后綴名為*.s90
5.內聯函數
inline函數傳統上只有C++支持,但IAR EW也支持在C代碼中使用inline.
#pragma inline:建議編譯器對緊隨其后的函數進行inline處理
#pragma inline = forced: 強制編譯器對緊隨其后的函數進行inline處理
/***************************** 錯誤描述 ******************************************/ // tft.c中定義內聯函數 #pragma inline = forced //強制inline void TFT_Write_Colour(const RGB_COLOUR *rgb) { //...code.... } // tft.h中聲明函數 void TFT_Write_Colour(const RGB_COLOUR *rgb); // main.c中調用函數 // 編譯報錯:main中引用了未定義的外部函數TFT_Write_Colour。 /***************************** 解決辦法 ******************************************/ // tft.h中“定義函數” #pragma inline = forced //在IAR EW430中,這里必須用強制inline;用inline可能導致編譯器忽略內聯,而定義成普通函數而出錯。 void TFT_Write_Colour(const RGB_COLOUR *rgb) { //...code.... } // main.c中包含tft.h,并調用函數 // 結果:編譯正確
6. 如何把變量定義到flash空間
unsigned char __flash temptab[] = {1,2,3,4,5}; <br>__flash unsigned char a @ 0x8; // 定義變量存放在flash 空間0X08單元 |
7. 關于內存模型
AVR 微控制器的其中一個特點是它有一種存儲器訪問方法均衡了“cheap access limited to small memory areas”與“more expensive accessmethods that can access any location in memory”。
在AVR_IAR C/C++編譯器中,通過選擇某種存儲模式(memory model),可設置一些訪問方法為默認的存儲器訪問方法(default memory accessmethod)。共有三種可用的存儲模式——Tiny,Small 和Large。你的處理器選項決定了哪些模式可以使用。如果你不指定一種存儲模式,則編譯器自動設定-v0、-v1、-v2、-v3、-v5 選項下的默認方法為Tiny,-v4 和-v6 選項下的訪問方法為Small。
8. 關于生成文件格式的設置
如圖,在linker -> outpu ->other中可設置相應的輸出文件格式.
比如要生成bin格式,選擇raw-binary就可以了, 如果是要生成hex格式,那么可以選intel-extern ,不過這個時候文件擴展名是*.a90,可以把"Override default " 打鉤,然后修改后綴名為hex就行了.
------------------------------------------------------------------------------------------------------------------