32位單片機LPC11C14學習
void SysCLK_config(void)
{
uint8 i;
SYSCON->PDRUNCFG &= ~(1<< 5);//系統振蕩器上電
SYSCON->SYSOSCCTRL = 0x00000000;//振蕩器未被旁路,1~20Mhz頻率輸入
for (i = 0; i < 200; i++) __nop();//等待振蕩器穩定
SYSCON->SYSPLLCLKSEL = 0x00000001;//PLL時鐘源選擇“系統振蕩器”
SYSCON->SYSPLLCLKUEN = 0x01;//更新PLL選擇時鐘源
SYSCON->SYSPLLCLKUEN = 0x00;//先寫0,再寫1達到更新時鐘源的目的
SYSCON->SYSPLLCLKUEN = 0x01;
while (!(SYSCON->SYSPLLCLKUEN &0x01)); //確定時鐘源更新后向下執行
SYSCON->SYSPLLCTRL = 0x00000023; //設置M=4;P=2;FCLKOUT=12*4=48Mhz
SYSCON->PDRUNCFG &= ~(1<< 7); //PLL上電
while (!(SYSCON->SYSPLLSTAT &0x01)); //確定PLL鎖定以后向下執行
SYSCON->MAINCLKSEL = 0x00000003;//主時鐘源選擇PLL后的時鐘
SYSCON->MAINCLKUEN = 0x01; //更新主時鐘源
SYSCON->MAINCLKUEN = 0x00;//先寫0,再寫1達到更新時鐘源的目的
SYSCON->MAINCLKUEN = 0x01;
while (!(SYSCON->MAINCLKUEN &0x01)); //確定主時鐘鎖定以后向下執行
SYSCON->SYSAHBCLKDIV = 0x01;//AHB時鐘分頻值為1,使AHB時鐘設置為48Mhz
}
程序詳解:
在看程序詳解之前,你最好先看一遍程序。
(如果你是一位剛剛從51單片機接觸ARM單片機的朋友,你會發現這個函數里面的語句書寫方式完全和以前寫51程序不一樣啊,以前給51的寄存器寫值,是用這么一種形式:
SBUF = 0X88;
而現在是用這么一種形式:
SYSCON->MAINCLKSEL=0X00000001;
這里為什么不直接寫成:
MAINCLKSEL=0X00000001;
這其實是因為在NXPLPC11XX.H文件中對系統寄存器的定義采用了結構體(Struct)的形式。現在,你可以在打開51單片機寄存器的定義文件REG51.H文件看一下,它對寄存器的地址定義是這樣的:
sfr SBUF = 0x99;
現在你再打開一下LPC1114對寄存器地址定義的NXPLPC11XX.H文件!全都是結構體的定義,而且是純C語言寫的,再也找不到“sfr”這樣的C51語言了。關于NXPLPC11XX.H文件請看瑞嵌制作的《NXPLPC11XX.H文件詳解》。)
(在以后的程序中,我們會經常看到&=~(1<<3)和|=(1<<3);這樣的句子,這些句子是對位操作用的。因為我們經常要對32位寄存器的某一位操作,還同時不影響其它位的值,所以才有了上面這樣的形式。比如我們說我們要對某個寄存器的bit5(注意:可不是第5位,位是從0開始的)寫0,這樣寫:
寄存器&=~(1<<5);
對寄存器的bit5寫1,這樣寫:
寄存器|=(1<<5);
現在運用你的C語言知識分析一下,把十進制的1寫成二進制32位數就是:
00000000000000000000000000000001
(1<<5)就是把1右移5下,左面補零,執行完這句話以后數就變成:
00000000000000000000000000100000
~(1<<5)就是再把這個數反相:
11111111111111111111111111011111
最后呢!再把這個數&給寄存器,&的操作即是遇到0與1等于0,1與0或1都還是1,所以執行完以后,除了bit5被改成了0,其它的位都沒有變。按照相同的方法,你可以分析一下對bit5寫1的操作。)
現在,我們首先來看一下函數里的第一個語句是對PDRUNCFG寄存器操作,如果你的英語好的話,一眼就看出來這個寄存器是干嘛的了,就是“掉電配置寄存器”,之所以不叫“上電配置寄存器”是因為它是對某位寫“1”掉電,寫“0”上電。這個寄存器的描述請看官方數據手冊第三章。看這個寄存器的bit5,該位控制著系統振蕩器的上電與掉電,默認是1,就是掉電狀態,我們既然已經決定了要用外部晶振作為時鐘源,那么現在就該把它上電了,于是就有了這條語句。
接下來這條語句是對SYSOSCCTRL寄存器操作,這個寄存器叫做“系統振蕩器控制寄存器”。(在后面的學習中,你會經常看到,系統內部的模塊需要好幾道門檻配置以后才能用,除了上電,還得控制,有的還需要再允許一下。這樣做看似麻煩,其實靈活!)系統控制寄存器只用了2個bit,bit0控制著系統振蕩器有沒有被旁路,bit1要根據外部晶振的值是多少來寫1或0。先說bit0,“被旁路”的意思就是“讓它不起作用”;“未被旁路”的意思就是“沒有讓它不起作用”。寫0表示“未被旁路”,寫1表示“被旁路”。那么什么時候被旁路呢?答:在有外部的“直接時鐘源”的時候。如果你51單片機學的很棒的話,你現在就應該明白了,不明白的那就聽我給你解釋吧。其實51單片機也有不利用外部晶振而是利用“直接時鐘源”的時候,電路圖是這個樣子的:
這里我們不需要旁路晶振,所以對該位寫0。bit1是根據外部晶振的值來定的,對該位寫0表示外部晶振頻率值在1~20MHz范圍內,寫1表示外部晶振頻率值在15~50MHz范圍內。在我們的開發板上用的晶振為12MHz,所以對該位寫0。
再往下是一條短暫延時程序,利用__nop();實現。給它一點時間完成任務。
再接下來的5條語句你可以把它看成一個整體,對PLL時鐘源的更新都是這個樣子的。關于SYSPLLCLKSEL寄存器,前面已經講過了。 SYSPLLCLKUEN是PLL時鐘源更新允許寄存器,根據官方數據手冊上的規定,要想實現更新,需要對該寄存器toggle一下,也就是對該寄存器先寫0,再寫1。while語句等待我們剛才寫的1運輸到SYSPLLCLKUEN里面。時鐘源的更新往往是需要一定時間的。
接下來,就該把選擇的時鐘源翻倍了。SYSPLLCTRL是系統倍頻控制寄存器,通過它可以確定倍頻的倍數。倍頻器是一個很有特點的東西。它除了可以用在單片機當中,還可以用在好多需要它的地方,比如射頻無線芯片當中可以用它來提高發射功率。倍頻器運用了模擬電子技術和數字電子技術。有時集成到芯片當中,有時單獨做成一塊芯片!關于LPC1114的倍頻器(PLL)的詳細描述,請看官方數據手冊第三章第九節。SYSPLLCTRL的bit0~bit4確定M 值,bit5和bit6確定P值,bit7是DIRECT位,bit8是BYPASS位。其它位保留。bit7和bit8我們現在還不深究(要深究的話,還需要好好學習倍頻器的結構),只需要知道它倆是來控制PLL的工作模式的,我們一般讓PLL工作在“普通模式”下,保持這倆位的默認值就可以。那么現在只剩M和P了。在普通模式下,PLL輸出頻率的計算公式如下所示:
看到上式,你可能會產生一個疑問:直接用M乘以PLL的輸入頻率Fclkin不行嗎?答案當然不行!為什么要確定P值呢?這個是PLL的機構決定的,在普通模式下,輸出頻率實際上是由FCCO產生的,而為了能讓PLL正常工作,FCCO需要在156~320MHz之間。現在,我們知道PLL的輸入頻率 Fclkin的值為12MHz,LPC1114的允許最大工作頻率為50MHz,現在我們只能把它倍頻四倍到48MHz了,所以M值定位4。根據數據手冊上的規定,P可以定為四個值,即1,2,4,8。這里只有當P=2的時候,FCCO的值為48*2*2=192,在156~320之間。所以,我們一般情況下,就選M=4,P=2了。SYSPLLSTAT是倍頻狀態寄存器,專門用來看PLL有沒有鎖定的,它是一個只讀寄存器。
再往下的5條語句是更新主時鐘用的。和上面提到的更新PLL時鐘的語句如出一轍,我就不多講了,相信大家現在已經能看懂了!
該函數的最后一句話,就是給SYSAHBCLKDIV寫1,確定分頻值為1。這個寄存器在前面已經很詳細的講過了,這里就不啰嗦了!
主站蜘蛛池模板:
眉山市|
满洲里市|
云和县|
英吉沙县|
双柏县|
云梦县|
松桃|
武义县|
克什克腾旗|
靖安县|
策勒县|
桦南县|
濮阳市|
都匀市|
阜平县|
虎林市|
龙游县|
淮南市|
阿拉善盟|
凤城市|
康保县|
墨玉县|
三穗县|
儋州市|
监利县|
虞城县|
克什克腾旗|
新绛县|
龙陵县|
分宜县|
西乌珠穆沁旗|
邢台县|
六盘水市|
启东市|
伽师县|
章丘市|
鹤庆县|
前郭尔|
康平县|
色达县|
吉木萨尔县|
到此!這個函數就都講完了。很好理解吧!這個函數就是每個工程里main函數里都會出現的初始化函數了。而且是必須的!為了使用方便,我已經把這個函數放到了NXPLPC11XX.C文件里面,在你寫的main函數里直接調用函數名就可以了。
關鍵詞:
32位單片機LPC11C1
評論