嵌入式 > 嵌入式开发 > 详情

LPC1114时钟配置

发布时间:2020-09-09 发布时间:
|
要让LPC1114正常工作,首先要对它的时钟源进行配置。LPC1114的最高工作频率为50MHz,因此给它的主时钟频率最大不能超过50MHz。实际上,通常都是使用频率较低的晶振,以降低外部电磁干扰,然后再通过内部倍频的方式把主时钟频率提高。根据管方手册给出的数据,外部晶振的频率范围是1MHz~25MHz,一般情况下使用12MHz晶振,然后内部进行4倍频,主时钟工作频率为48MHz。

要对LPC1114的时钟进行配置,必须要了解它的时钟结构,先来看一下它的时钟结构图,如下图所示。

首先来看主时钟,给主时钟(main clock)提供选择有4个源,分别是:内部RC振荡器、未倍频之前的PLL时钟、内部看门狗时钟、经过PLL倍频之后的时钟。由对主时钟源选择寄存器(MAINCLKSEL)的操作来进行选择,同一时刻只能选择一种时钟做为主时钟。下面就给出MAINCLKSEL寄存器的位结构(要注意,因为LPC1114是32位的,所以所有的寄存器都是32位的),如下表所示。

符号

描述

复位值

1∶0

SEL

00

内部RC振荡器

0x00

01

PLL倍频之前的时钟

10

内部看门狗时钟

11

PLL倍频之后的时钟

31∶2

-

-

保留

0x00

前面说过,一般情况下CPU内部都是要进行倍频的,因此大多数时候该寄存器的值都会选择11(0x03),执行语句“SYSCON->MAINCLKSEL=0x00000003”就可以了。

接下来看系统PLL时钟,PLL即是频率锁相环的意思,PLL的功能很多,有兴趣的可自行参考其它资料,这里主要利用它来实现倍频的功能。从上图中可以看出,供给PLL选择的有2个源,一个是片内RC振荡器,另一个是晶体振荡器。由对系统PLL时钟选择寄存器(SYSPLLCLKSEL)的操作来进行选择,同一时刻只能选择一种时钟做为输入时钟。下面给出SYSPLLCLKSEL寄存器的位结构,如下表所示。

符号

描述

复位值

1∶0

SEL

00

内部RC振荡器

0x00

01

晶体振荡器

10

保留

11

保留

31∶2

-

-

保留

0x00

一般情况下,为了提高时钟精度都会选择01(0x01),以选择外部晶体振荡器做为时钟输入。执行语句“SYSCON->SYSPLLCLKSEL=0x00000001”就可以了。

在时钟结构图中还可以看出,主时钟分成6路供给不同的模块。其中一路主时钟经过系统时钟分频器(SYSAHBCLKDIV)后做为系统时钟,提供给AHB。在LPC1114中,只有通用输入输出端口(GPIO)需要AHB。为了给不同速度的模块(如内核、存储器、APB等)提供时钟,需要对SYSAHBCLKDIV寄存器进行操作,以对主时钟进行分频。下面给出SYSAHBCLKDIV寄存器的位结构,如下表所示。

符号

描述

复位值

7∶0

DIV

00000000

关闭系统时钟

0x01

00000001

1

00000010

2

……

……

11111111

255

31∶8

-

-

保留

0x00

从表中可以看出,分频的最大值是255分频。一般情况下,系统的默认值是1,即为AHB提供不分频的主时钟,也可执行语句“SYSCON->SYSAHBCLKDIV=0x00000001”来实现。剩余5个模块(SPI0、UART、SPI1、WDT、CLKOUT)的时钟也像系统时钟一样由主时钟来分频,只不过它们默认的分频值为0,即默认不提供时钟,也就是说剩余的5个模块默认状态下不工作,需要的时候再通过程序来打开,以降低功耗

由上述可见,居于Cotex-M0内核的CPU由于强化了时钟配置,所以在一般情况下要使用该类型的CPU,首要的任务就是为其配置正确的时钟。下面就来讨论一下如何通过程序来配置LPC1114的时钟。

先给出一个时钟初始化的函数,如下:

void SysCLK_config(void)

{

uint8_t i;

LPC_SYSCON->PDRUNCFG &= ~(1 << 5); //给系统振荡器上电

LPC_SYSCON->SYSOSCCTRL = 0x00000000; //系统振荡器未旁路,1~12MHz输入

for (i = 0; i < 200; i++) __nop(); //延时等待振荡器稳定

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的外部晶振,该函数执行完后,LPC1114的时钟被设置成为主时钟48MHz,AHB时钟48MHz,输入输出端口(GPIO)时钟使能的状态。

在上述程序中,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

(系统振荡器掉电)

1

掉电

1

0

上电

6

WDTOSC_PD

(看门狗振荡器掉电)

1

掉电

1

0

上电

7

SYSPLL_PD

(系统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

-

-

保留

从表中可以看出,系统振荡器和系统PLL在默认情况下是掉电的,也就是说默认它们不处于工作状态,要让它们工作就必须给它们置0上电。所以要通过执行语句“SYSCON->PDRUNCFG &= ~(1 << 5)”和“SYSCON->PDRUNCFG &= ~(1 << 7)”来把SYSOSC和SYSPLL置0。

接下来看“系统振荡器控制寄存器(SYSOSCCTRL)”,下表是它的位结构。

符号

描述

复位值

0

BYPASS

(旁路系统振荡器)

0

未被旁路

0

1

被旁路

1

FREQRANGE

(低功耗振荡器确定频率范围)

0

1~20MHz

0

1

15~25MHz

31∶2

-

-

保留

0

从表中可以看出,如果要让系统振荡器工作,则其第0位就应该选择0,即不被旁路,只有在从外部直接输入振荡信号的情况下才会选择旁路(比如使用有源晶振)。第1位用于选择外部晶振的频率范围,使用12MHz时该位选择0。执行语句“SYSCON->SYSOSCCTRL = 0x00000000”就可以实现上述配置,但实际上复位后的值就是该配置,也可不执行该语句。

从上述程序中还可以看出,在配置了时钟后(无论是PLL时钟还是主时钟),都需要更新一下才能正常工作。而更新的操作则根据管方手册,必须要给相应的允许寄存器“toggle”一下(即先向其写0再紧接着写1)。“系统PLL时钟源更新允许寄存器(SYSPLLCLKUEN)”和“主时钟源更新允许寄存器(MAINCLKUEN)”的位结构是一样的,下表是MAINCLKUEN寄存器的位结构。

符号

描述

复位值

0

ENA

(允许主时钟源更新)

0

无变化

0

1

更新时钟源

31∶1

-

-

保留

0

在主时钟源及PLL时钟源更改后,要紧接着及时更新相应的允许寄存器才能让其正常工作。此外还要注意一点,“toggle”后需要查询相应的允许寄存器是否已更新,若没有就需要等待直到其更新为止(例如在更新PLL时钟源更新允许寄存器SYSPLLCLKUEN后要执行语句“while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01));”,以等待其更新完成)。

接下来看一下PLL的配置,要让PLL对输入时钟进行倍频或分频,就要配置“系统倍频控制寄存器(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的输出频率,Fclkin为外部晶振的频率,FCCO的值必须在156MHz ~320MHz之间,M为倍频的倍数,P值要符合要求。若以12MHz的晶振做为输入,系统主时钟要为48MHz,则M=4(MSEL=0011),P的值只能取2(PSEL=01)才能满足公式要求。因此寄存器SYSPLLCTRL的值应该为10011(0x13),所以要配置此项只需要执行语句“SYSCON->SYSPLLCTRL = 0x00000013”就可以了。

在改变了PLL的倍频之后,需要查询“倍频状态寄存器(SYSPLLSTAT)”,看PLL锁定了没有,若没有就需要等待直到其锁定为止(执行语句“while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));”)。下面是“倍频状态寄存器(SYSPLLSTAT)”的位结构。

符号

描述

复位值

0

LOCK

(PLL锁定状态)

0

未锁定

0

1

已锁定

31∶1

-

-

保留

0

CPU要对GPIO进行操作,就必须给GPIO时钟信号,即需要使能GPIO的时钟。在默认情况下GPIO时钟是允许的,也可以对“系统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位计数/定时器0时钟)

0

禁止

0

1

允许

8

CT16B1

(允许16位计数/定时器1时钟)

0

禁止

0

1

允许

9

CT32B0

(允许32位计数/定时器0时钟)

0

禁止

0

1

允许

10

CT32B1

(允许32位计数/定时器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

从表中可以看出,第6项就是“通用输入输出端口”的时钟配置项,执行语句“SYSCON->SYSAHBCLKCTRL |= (1<<6)”就可以开启GPIO的时钟。在打开了GPIO的时钟后,就可以使用P0~P3端口了。

上述的时钟配置程序是最基本的,也是必须的,因此在任何程序开始前,都应该先调用该时钟配置函数,以对LPC1114进行基本的时钟配置,为后续程序提供保障。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
定时器CTC模式的测试