C18是MCHP老早針對PIC18高端片子自己出的編譯器環境,可能是用戶覆蓋面的原因,個人感覺比PIC16上的Hi-tech PICC要難用很多。
針對不同的單片機要安裝不同升級包,因爲官方的頭文件支持一直在更新;使用較新的單片機時,建議安裝最新的C18 upgrade installation升級包。
下面說說不同之處和比較難配置的關鍵的幾個點:
-------------------------------------------------------------------------------------
#pragma指令:
這個C/C++語言常見的預處理指令,是用來定位代碼區域的,定位到RAM區和ROM區,以及類似Config關鍵配置字的作用。這個跟Freescale的HCS08/12系列單片機的Codewarrior環境風格有點像。這玩意兒是編譯器相關的,也就是說有的編譯環境支持,有的壓根不支持,所以得仔細去讀C18文檔。。。頭大。我就做個簡單學習加翻譯了!
# pragma udata [ 屬性列表] [section-name [=address]]
# pragma idata [ 屬性列表] [section-name [=address]]
# pragma romdata [overlay] [section-name [=address]]
# pragma code [overlay] [section-name [=address]]
但是每個PIC18器件的設定值並不相同,不能閉着眼睛猜,官方的C18用戶手冊是這麼說的:
2.9.5.1
語法
pragma-config僞指令:
# pragma config setting-listsetting-list: setting
| setting-list, settingsetting:
setting-name = value-name
setting-name和value-name是特定於器件的,可通過使用 --help-config命令行選項來確定。另外,PIC18 Configuration Settings Addendum(DS51537)中給出了每個器件的有效設置和相關值。
然後在MCHP官網上,已經停止更新這個文檔了:
PIC18
CONFIGURATION SETTINGS ADDENDUM
Page 4. PIC18 Configuration Settings Addendum DS51537E-page iv 296
Page
6. PIC18 Configuration Settings Addendum DS51537E-page vi
http://ww1.microchip.com/downloads/en/DeviceDoc/C18_Config_Settings_51537e.pdf
The PIC18 Configuration Settings Addendum is no longer published as a .PDF file. It is included with MPLAB IDE and MPLAB C18 C Compiler as on-line help.
網上可以找到的是陳舊的2006年版本的,已經不需要看了,直接在打開MPLAB IDE--Help---Topic,裏面找PIC18 Config Setting 裏面很方便!!
---------------------------------------------------------------------
The ANSI C standard provides each C implementation a method for defining uniqueconstructs, as required by the architecture of the target processor. This is done using
the #pragma directive. The most common #pragma directive in the MPLAB C18
compiler identifies the section of memory to be used in the PIC18XXXX. For instance,
#pragma code
tells MPLAB 18 to compile the C language code following this directive into the “code”
section of program memory. The code section is defined in the associated linker script
for each PIC18XXXX device, specifying the program memory areas where instructions
can be executed. This directive can be inserted as shown, or it can also be followed by
an address in the code areas of the target processor, allowing full control over the
location of code in memory. Usually, it doesn’t matter, but in some applications, such
as bootloader, it is very important to have strict control over where certain blocks of
code will be executed in the application.
指令 | 用途 |
---|---|
code | 程序空間指令:將其後所有指令編譯到目標PIC18單片機的程序空間。 |
romdata | 存儲在程序空間的數據:將其後所有靜態數據存入目標PIC18單片機的程序空間。 |
udata | 未初始化的數據:將後續需要的未初始化的靜態變量,分配給數據data存儲器空間。 |
idata | 初始化過的數據:將後續需要的靜態變量,分配給數據data存儲器空間,且這些變量是在源代碼中設過初始值的。 |
config | 定義PIC18單片機的配置字,這些將會在鏈接輸出的hex文件中生成幷包含在固件內寫入單片機。 |
interrupt | 將已定義命名的C函數編譯爲高優先級的中斷服務ISR程序; |
interruptlow | 將已定義命名的C函數編譯爲較低優先級的中斷服務ISR程序; |
varlocate | 定義變量將要存儲的位置,以便於編譯器避免設定bank地址翻頁。 |
詳細內容要參見C18 User's Guide用戶參考手冊!
2.9.1.5 定位代碼
在 #pragma code 僞指令後生成的所有代碼將被分配到指定的代碼段,直到遇到下一個 #pragma code 僞指令。絕對代碼段允許將代碼分配到一個特定的地址。例如:
#pragma code my_code=0x2000
將把代碼段 my_code 分配到程序存儲器地址0x2000。鏈接器會強制將代碼段放入程序存儲區;然而,代碼段也可以位於指定的存儲區。可以用鏈接器描述文件中的SECTION 僞指令把一個段分配到特定的存儲區。下面鏈接器描述文件中的僞指令把代碼段my_code1 分配到存儲區page1:
SECTION NAME=my_code1 ROM=page1
2.9.1.6 定位數據
對於MPLAB C18 編譯器,數據可以放入數據存儲器或者程序存儲器。如果沒有用戶提供的附加代碼,片內程序存儲器中的數據只能讀不能寫。如果沒有用戶提供的附加代碼,片外程序存儲器中的數據一般是隻能讀或者只能寫。
例如,下面的語句爲靜態分配的未初始化數據(udata)聲明瞭一個位於絕對地址0x120 的段:
#pragma udata my_new_data_section=0x120
rom 關鍵字告知編譯器應該將變量放入程序存儲器。編譯器會把這個變量分配到當前
的romdata 型段。例如:
#pragma romdata const_table
const rom char my_const_array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
/* Resume allocation of romdata into the default section */
#pragma romdata
鏈接器強制將romdata 段放入程序存儲區,將udata 和 idata 段放入數據存儲區;
然而,數據段也可以位於指定的存儲區。可以使用鏈接器描述文件中的SECTION 僞
指令把一個段分配到一個特定的存儲區。下面的語句將把udata 段my_data 分配到
存儲區gpr1:
SECTION NAME=my_data RAM=gpr1
-----------------------------------------------------------------------
我摸索了一陣子,還發現C18的另外幾個特點:
1. 新來的rom指令(注意必須小寫,否則C18編譯器不認識),作用類似於#pragma romdata xxxxx
//The direction that the mouse will move in
rom signed char dir_table[]={-4,-4,-4, 0, 4, 4, 4, 0};
2. PORTBbits.RB3和LATBbits.LATB0的區別,
RB1=0;
RB2=1;
上面這種端口引腳定義在C18裏是沒法直接用的,所有bits位必須帶寄存器名的前綴,比如PORTBbits.RB1;這跟PICC編譯器的風格有很大不同,所以我剛開始感覺很不習慣。當然這樣統一標準其實也有好處,就是增加程序代碼的可讀性和可辨識性,一眼就能看出bits操作。操作PortX作爲digital IO輸出端口時,儘量用latch寄存器來操作,避免用PORTBbits.RB3,因爲後者只是用來讀取端口狀態的;
#define LED0 LATBbits.LATB0
#define LED1 LATBbits.LATB1
#define LED2 LATBbits.LATB2
LED0=!LED0;