LPC1114時鐘配置
要對LPC1114的時鐘進行配置,必須要了解它的時鐘結構,先來看一下它的時鐘結構圖,如下圖所示。
本文引用地址:http://m.butianyuan.cn/article/201611/316320.htm首先來看主時鐘,給主時鐘(main clock)提供選擇有4個源,分別是:內部RC振蕩器、未倍頻之前的PLL時鐘、內部看門狗時鐘、經(jīng)過PLL倍頻之后的時鐘。由對主時鐘源選擇寄存器(MAINCLKSEL)的操作來進行選擇,同一時刻只能選擇一種時鐘做為主時鐘。下面就給出MAINCLKSEL寄存器的位結構(要注意,因為LPC1114是32位的,所以所有的寄存器都是32位的),如下表所示。
位 | 符號 | 值 | 描述 | 復位值 |
1∶0 | SEL | 00 | 內部RC振蕩器 | 0x00 |
01 | PLL倍頻之前的時鐘 | |||
10 | 內部看門狗時鐘 | |||
11 | PLL倍頻之后的時鐘 | |||
31∶2 | - | - | 保留 | 0x00 |
前面說過,一般情況下CPU內部都是要進行倍頻的,因此大多數(shù)時候該寄存器的值都會選擇11(0x03),執(zhí)行語句“SYSCON->MAINCLKSEL=0x00000003”就可以了。
接下來看系統(tǒng)PLL時鐘,PLL即是頻率鎖相環(huán)的意思,PLL的功能很多,有興趣的可自行參考其它資料,這里主要利用它來實現(xiàn)倍頻的功能。從上圖中可以看出,供給PLL選擇的有2個源,一個是片內RC振蕩器,另一個是晶體振蕩器。由對系統(tǒng)PLL時鐘選擇寄存器(SYSPLLCLKSEL)的操作來進行選擇,同一時刻只能選擇一種時鐘做為輸入時鐘。下面給出SYSPLLCLKSEL寄存器的位結構,如下表所示。
位 | 符號 | 值 | 描述 | 復位值 |
1∶0 | SEL | 00 | 內部RC振蕩器 | 0x00 |
01 | 晶體振蕩器 | |||
10 | 保留 | |||
11 | 保留 | |||
31∶2 | - | - | 保留 | 0x00 |
一般情況下,為了提高時鐘精度都會選擇01(0x01),以選擇外部晶體振蕩器做為時鐘輸入。執(zhí)行語句“SYSCON->SYSPLLCLKSEL=0x00000001”就可以了。
在時鐘結構圖中還可以看出,主時鐘分成6路供給不同的模塊。其中一路主時鐘經(jīng)過系統(tǒng)時鐘分頻器(SYSAHBCLKDIV)后做為系統(tǒng)時鐘,提供給AHB。在LPC1114中,只有通用輸入輸出端口(GPIO)需要AHB。為了給不同速度的模塊(如內核、存儲器、APB等)提供時鐘,需要對SYSAHBCLKDIV寄存器進行操作,以對主時鐘進行分頻。下面給出SYSAHBCLKDIV寄存器的位結構,如下表所示。
位 | 符號 | 值 | 描述 | 復位值 |
7∶0 | DIV | 00000000 | 關閉系統(tǒng)時鐘 | 0x01 |
00000001 | 1 | |||
00000010 | 2 | |||
…… | …… | |||
11111111 | 255 | |||
31∶8 | - | - | 保留 | 0x00 |
由上述可見,居于Cotex-M0內核的CPU由于強化了時鐘配置,所以在一般情況下要使用該類型的CPU,首要的任務就是為其配置正確的時鐘。下面就來討論一下如何通過程序來配置LPC1114的時鐘。
先給出一個時鐘初始化的函數(shù),如下:
void SysCLK_config(void)
{
uint8_t i;
LPC_SYSCON->PDRUNCFG &= ~(1 << 5); //給系統(tǒng)振蕩器上電
LPC_SYSCON->SYSOSCCTRL = 0x00000000; //系統(tǒng)振蕩器未旁路,1~12MHz輸入
for (i = 0; i < 200; i++) __nop(); //延時等待振蕩器穩(wěn)定
LPC_SYSCON->SYSPLLCLKSEL = 0x00000001; //PLL輸入選擇外部晶體振蕩
LPC_SYSCON->SYSPLLCLKUEN = 0x00;
LPC_SYSCON->SYSPLLCLKUEN = 0x01; //先寫0后寫1更新時鐘源
while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); //等待更新完成
LPC_SYSCON->SYSPLLCTRL = 0x00000013; //M=4、P=2,倍頻后的時鐘為48MHz
LPC_SYSCON->PDRUNCFG &= ~(1 << 7); //給PLL上電
while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); //等待PLL鎖定
LPC_SYSCON->MAINCLKSEL = 0x00000003; //主時鐘選擇PLL倍頻后的時鐘
LPC_SYSCON->MAINCLKUEN = 0x00;
LPC_SYSCON->MAINCLKUEN = 0x01; //先寫0后寫1更新時鐘源
while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); //等待更新完成
LPC_SYSCON->SYSAHBCLKDIV = 0x00000001; //AHB為1分頻,AHB時鐘為48MHz
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); //使能GPIO時鐘
}
如果使用的是12MHz的外部晶振,該函數(shù)執(zhí)行完后,LPC1114的時鐘被設置成為主時鐘48MHz,AHB時鐘48MHz,輸入輸出端口(GPIO)時鐘使能的狀態(tài)。
在上述程序中,PLL輸入選擇寄存器(SYSPLLCLKSEL),主時鐘選擇寄存器(MAINCLKSEL),AHB分頻選擇寄存器(SYSAHBCLKDIV)均在前面討論過,下面來看一下沒討論過的寄存器。先看“掉電配置寄存器(PDRUNCFG)”,下表是它的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
0 | IRCOUT_PD (IRC振蕩器輸出掉電) | 1 | 掉電 | 0 |
0 | 上電 | |||
1 | IRC_PD (IRC振蕩器掉電) | 1 | 掉電 | 0 |
0 | 上電 | |||
2 | FLASH_PD (Flash掉電) | 1 | 掉電 | 0 |
0 | 上電 | |||
3 | BOD_PD (BOD掉電) | 1 | 掉電 | 0 |
0 | 上電 | |||
4 | ADC_PD (ADC掉電) | 1 | 掉電 | 1 |
0 | 上電 | |||
5 | SYSOSC_PD (系統(tǒng)振蕩器掉電) | 1 | 掉電 | 1 |
0 | 上電 | |||
6 | WDTOSC_PD (看門狗振蕩器掉電) | 1 | 掉電 | 1 |
0 | 上電 | |||
7 | SYSPLL_PD (系統(tǒng)PLL掉電) | 1 | 掉電 | 1 |
0 | 上電 | |||
8 | - | - | 保留 | 1 |
9 | - | 0 | 保留,置0 | 0 |
10 | - | - | 保留 | 1 |
11 | - | 1 | 保留,置1 | 1 |
12 | - | 0 | 保留,置0 | 0 |
15∶13 | - | - | 保留 | 1 |
31∶16 | - | - | 保留 |
從表中可以看出,系統(tǒng)振蕩器和系統(tǒng)PLL在默認情況下是掉電的,也就是說默認它們不處于工作狀態(tài),要讓它們工作就必須給它們置0上電。所以要通過執(zhí)行語句“SYSCON->PDRUNCFG &= ~(1 << 5)”和“SYSCON->PDRUNCFG &= ~(1 << 7)”來把SYSOSC和SYSPLL置0。
接下來看“系統(tǒng)振蕩器控制寄存器(SYSOSCCTRL)”,下表是它的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
0 | BYPASS (旁路系統(tǒng)振蕩器) | 0 | 未被旁路 | 0 |
1 | 被旁路 | |||
1 | FREQRANGE (低功耗振蕩器確定頻率范圍) | 0 | 1~20MHz | 0 |
1 | 15~25MHz | |||
31∶2 | - | - | 保留 | 0 |
從表中可以看出,如果要讓系統(tǒng)振蕩器工作,則其第0位就應該選擇0,即不被旁路,只有在從外部直接輸入振蕩信號的情況下才會選擇旁路(比如使用有源晶振)。第1位用于選擇外部晶振的頻率范圍,使用12MHz時該位選擇0。執(zhí)行語句“SYSCON->SYSOSCCTRL = 0x00000000”就可以實現(xiàn)上述配置,但實際上復位后的值就是該配置,也可不執(zhí)行該語句。
從上述程序中還可以看出,在配置了時鐘后(無論是PLL時鐘還是主時鐘),都需要更新一下才能正常工作。而更新的操作則根據(jù)管方手冊,必須要給相應的允許寄存器“toggle”一下(即先向其寫0再緊接著寫1)。“系統(tǒng)PLL時鐘源更新允許寄存器(SYSPLLCLKUEN)”和“主時鐘源更新允許寄存器(MAINCLKUEN)”的位結構是一樣的,下表是MAINCLKUEN寄存器的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
0 | ENA (允許主時鐘源更新) | 0 | 無變化 | 0 |
1 | 更新時鐘源 | |||
31∶1 | - | - | 保留 | 0 |
在主時鐘源及PLL時鐘源更改后,要緊接著及時更新相應的允許寄存器才能讓其正常工作。此外還要注意一點,“toggle”后需要查詢相應的允許寄存器是否已更新,若沒有就需要等待直到其更新為止(例如在更新PLL時鐘源更新允許寄存器SYSPLLCLKUEN后要執(zhí)行語句“while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01));”,以等待其更新完成)。
接下來看一下PLL的配置,要讓PLL對輸入時鐘進行倍頻或分頻,就要配置“系統(tǒng)倍頻控制寄存器(SYSPLLCTRL)”,下表是該寄存器的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
4∶0 | MSEL (反饋分頻器的值, 分頻器的值M是MSEL+1) | 00000 | M=1 | 0x00 |
…… | …… | |||
11111 | M=32 | |||
6∶5 | PSEL (后分頻器的值, 分頻器的值為2×P) | 00 | P=1 | 0x00 |
01 | P=2 | |||
10 | P=4 | |||
11 | P=8 | |||
31∶7 | - | - | 保留,不能寫1 | 0x00 |
PLL的輸出頻率要符合下面的公式。
Fclkout為PLL的輸出頻率,F(xiàn)clkin為外部晶振的頻率,F(xiàn)CCO的值必須在156MHz ~320MHz之間,M為倍頻的倍數(shù),P值要符合要求。若以12MHz的晶振做為輸入,系統(tǒng)主時鐘要為48MHz,則M=4(MSEL=0011),P的值只能取2(PSEL=01)才能滿足公式要求。因此寄存器SYSPLLCTRL的值應該為10011(0x13),所以要配置此項只需要執(zhí)行語句“SYSCON->SYSPLLCTRL = 0x00000013”就可以了。
在改變了PLL的倍頻之后,需要查詢“倍頻狀態(tài)寄存器(SYSPLLSTAT)”,看PLL鎖定了沒有,若沒有就需要等待直到其鎖定為止(執(zhí)行語句“while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));”)。下面是“倍頻狀態(tài)寄存器(SYSPLLSTAT)”的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
0 | LOCK (PLL鎖定狀態(tài)) | 0 | 未鎖定 | 0 |
1 | 已鎖定 | |||
31∶1 | - | - | 保留 | 0 |
CPU要對GPIO進行操作,就必須給GPIO時鐘信號,即需要使能GPIO的時鐘。在默認情況下GPIO時鐘是允許的,也可以對“系統(tǒng)AHB時鐘控制寄存器(SYSAHBCLKCTRL)”中相應的位進行操作來選擇允許時鐘,下面是該寄存器的位結構。
位 | 符號 | 值 | 描述 | 復位值 |
0 | SYS (允許AHB時鐘,只讀) | 0 | 保留 | 1 |
1 | 允許 | |||
1 | ROM (允許ROM時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
2 | RAM (允許RAM時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
3 | FLASHREG (允許flash寄存器接口時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
4 | FLASHARRAY (允許flash陣列存取時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
5 | I2C (允許I2C時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
6 | GPIO (允許GPIO時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
7 | CT16B0 (允許16位計數(shù)/定時器0時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
8 | CT16B1 (允許16位計數(shù)/定時器1時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
9 | CT32B0 (允許32位計數(shù)/定時器0時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
10 | CT32B1 (允許32位計數(shù)/定時器1時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
11 | SSP0 (允許SPI0時鐘) | 0 | 禁止 | 1 |
1 | 允許 | |||
12 | UART (允許UART時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
13 | ADC (允許ADC時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
14 | - | - | 保留 | 0 |
15 | WDT (允許WDT時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
16 | IOCON (允許IO配置模塊時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
17 | - | - | 保留 | 0 |
18 | SSP1 (允許SPI1時鐘) | 0 | 禁止 | 0 |
1 | 允許 | |||
31∶19 | - | - | 保留 | 0x00 |
上述的時鐘配置程序是最基本的,也是必須的,因此在任何程序開始前,都應該先調用該時鐘配置函數(shù),以對LPC1114進行基本的時鐘配置,為后續(xù)程序提供保障。
評論