新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 32位单片机LPC11C14学习

32位单片机LPC11C14学习

作者: 时间:2016-11-29 来源:网络 收藏
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函数里直接调用函数名就可以了。

上一页 1 2 下一页

关键词: 32位单片机LPC11C1

评论


技术专区

关闭
站长统计
×

TI直播中...
汽车电气化背景下的TI音频解决方案和技术线上研讨会直播中,早鸟报名礼、myTI 专属礼、活动参与礼等着您(已经报名用户可以凭报名邮箱直接登录),速入>>