新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > IAR的MSP430 C編程基礎(chǔ)知識

IAR的MSP430 C編程基礎(chǔ)知識

作者: 時(shí)間:2016-11-26 來源:網(wǎng)絡(luò) 收藏
通常我們開發(fā)單片機(jī)程序都是使用C語言的,為什么C語言比匯編方便呢?原因就是C編譯器在為我們做著大量的瑣碎的組織翻譯工作。在此感謝IAR,辛辛苦苦的勞動(dòng)著,卻沒有辛苦錢!
好,我們從新建一個(gè)工程開始,打開IAR,空白,project,create new project,C,main,確定。給工程起個(gè)名字,保存。OK,工程建立完畢了。這時(shí)工程里已經(jīng)有個(gè)main.c了,并且有一個(gè)完整的程序,如下:

#include "io430.h"

int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;

return 0;
}
Make一下,保存工作區(qū)文件,就可順利編譯通過了。
(本人所使用的IAR版本為5.3,為了能體驗(yàn)更好的IAR特性,請使用較新且較穩(wěn)定的版本)
從頭文件包含說起,這個(gè)io430.h是IAR為C語言所推薦的頭文件,這個(gè)頭文件以匿名結(jié)構(gòu)體的形式對430的寄存器進(jìn)行聲明,匿名結(jié)構(gòu)體已經(jīng)在C11中納入標(biāo)準(zhǔn)C,這種聲明方式在ARM中廣為流傳。之前較早的版本可能使用的是msp430.h,這個(gè)頭文件都是以宏定義的形式對寄存器進(jìn)行聲明的,C和匯編都可以包含此文件,這里有豐富的宏定義,如SELA__REFOCLK,選擇REFOCLK作為ACLK。這在io430.h是沒有的,因此如果以前的工程包含的是msp430.h,那么移植到使用io430.h將會(huì)出現(xiàn)一些問題。
頭文件的選擇根據(jù)自己的習(xí)慣決定,但是像畫蛇添足一樣把頭文件改成#inlcude “msp430f149.h”就沒有必要了,因?yàn)镮AR已經(jīng)自動(dòng)幫我們選擇了合適的頭文件,這在移植到其他的器件時(shí),不用做任何更改;我們所要做的就是在工程的option中,選擇我們的device,我們新建的這個(gè)工程默認(rèn)的device為msp430f149,現(xiàn)在我們更換器件為msp430f5418A,重新make一下。我們來看工程左邊的文件拓?fù)浣Y(jié)構(gòu),如圖1.1:

1.IAR為我們自動(dòng)包含了io430f5418a.h和intrinsics.h
2.就是test.d43所包含的這些文件:test.d43是最終生成的可執(zhí)行文件。這個(gè)可執(zhí)行文件是由他下面的4個(gè)連接而成的。Main.r43是由main.c生成的目標(biāo)文件;dl430xsfn.r43就是大名鼎鼎的C運(yùn)行時(shí)庫,大家覺得這個(gè)詞匯熟悉嗎?運(yùn)行時(shí)庫會(huì)根據(jù)工程的設(shè)置不同而不同,IAR中約有20左右個(gè)運(yùn)行時(shí)庫,具體可參考compiler reference;Lnk430f5418a.xcl文件中包含芯片的存儲器組織結(jié)構(gòu),用來指定程序數(shù)據(jù)和代碼的存放位置;mutipiler43_loc2.xcl是因?yàn)?418a內(nèi)部具有硬件乘法器而出現(xiàn),告知編譯器用硬件乘法器來進(jìn)行乘法運(yùn)算。
現(xiàn)在來了解一下一個(gè)耳熟的詞匯:C運(yùn)行時(shí)庫
眾所周知,在單片機(jī)上電瞬間,只有flash中有數(shù)據(jù)和代碼,RAM的內(nèi)容是不確定的。單片機(jī)執(zhí)行的第一條指令絕對不是main函數(shù),而是C運(yùn)行時(shí)庫的初始化函數(shù),為我們寫的C代碼搭建C運(yùn)行時(shí)環(huán)境。首先設(shè)置SP,也就是設(shè)置棧,SP通常設(shè)置為RAM的最高地址。其次就是初始化內(nèi)存,初始化全局變量,靜態(tài)變量,以及在RAM中的函數(shù),這些數(shù)據(jù)都是從flash中拷貝過來的,因此我們的變量不僅僅占用著RAM,還有可能占據(jù)著一份flash(未初始化的全局變量和靜態(tài)變量初始化為0,將未初始化的數(shù)據(jù)放在一個(gè)區(qū)域,只需要將這個(gè)區(qū)域清0即可,不需要從flash拷貝)。數(shù)據(jù)初始化完畢后就開始從main函數(shù)開始了,執(zhí)行我們所寫的代碼。因?yàn)?30的看門狗在復(fù)位之后是開著的,因此需要初始化數(shù)據(jù)量過大的話,就有可能導(dǎo)致看門狗溢出復(fù)位,從而main函數(shù)永遠(yuǎn)得不到執(zhí)行。解決此問題的辦法就是在程序中加入一個(gè)函數(shù):int __low_level_init(void),在此函數(shù)中加入停止看門狗的語句,并返回1即可,__low_level_init函數(shù)將在初始化代碼之前執(zhí)行。
注:初始化代碼并未包含在dl430xsfn.r43中,應(yīng)該是由編譯器單獨(dú)生成的一段代碼,我理解這些代碼應(yīng)該屬于C運(yùn)行時(shí)庫的范疇。這都是我的個(gè)人見解。
C運(yùn)行時(shí)庫還包含著所有的C標(biāo)準(zhǔn)庫,如strlen、memcpy等函數(shù);還有乘除法的實(shí)現(xiàn)等等。


關(guān)鍵詞: IARMSP430C編程基礎(chǔ)知

評論


技術(shù)專區(qū)

關(guān)閉