Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2293937
  • 博文数量: 187
  • 博客积分: 1457
  • 博客等级: 上尉
  • 技术积分: 2423
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-13 09:41
个人简介

如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.

文章分类

全部博文(187)

文章存档

2017年(2)

2016年(2)

2015年(7)

2014年(13)

2013年(80)

2012年(83)

分类: LINUX

2012-04-16 11:01:12

今天大致解释一下上一篇中使用到的程序。

main函数里,第一句就是TargetResetInit();从函数名可以看出它的主要功能是初始化。

它在target.c中被定义,代码如下:


点击(此处)折叠或打开

  1. void TargetResetInit(void)

  2. {

  3.   /* Set memory accelerater module*/

  4.   MAMCR = 0;

  5. #if Fcclk < 20000000

  6.   MAMTIM = 1;

  7. #else

  8. #if Fcclk < 40000000

  9.   MAMTIM = 2;

  10. #else

  11.   MAMTIM = 3;

  12. #endif

  13. #endif

  14.   MAMCR = 2;



  15. #if USE_USB

  16.   PCONP |= 0x80000000; /* Turn On USB PCLK */

  17. #endif



  18.   /* Set system timers for each component */

  19. #if (Fpclk / (Fcclk / 4)) == 1

  20.   PCLKSEL0 = 0x00000000; /* PCLK is 1/4 CCLK */

  21.   PCLKSEL1 = 0x00000000;

  22. #endif

  23. #if (Fpclk / (Fcclk / 4)) == 2

  24.   PCLKSEL0 = 0xAAAAAAAA; /* PCLK is 1/2 CCLK */

  25.   PCLKSEL1 = 0xAAAAAAAA;

  26. #endif

  27. #if (Fpclk / (Fcclk / 4)) == 4

  28.   PCLKSEL0 = 0x55555555; /* PCLK is the same as CCLK */

  29.   PCLKSEL1 = 0x55555555;

  30. #endif



  31.   /* Configure PLL, switch from IRC to Main OSC */

  32.   ConfigurePLL();



  33.   GPIOResetInit();



  34.   init_VIC();



  35.   return;

  36. }

MAMCR = 0;设置MAM寄存器的功能

 

MAMTIM = 1;下面英文说得很明白了,我不想翻译。

 

PCONP |= 0x80000000;    /* Turn On USB PCLK */打开USB外设时钟

 

#if (Fpclk / (Fcclk / 4)) == 1

  PCLKSEL0 = 0x00000000;  /* PCLK is 1/4 CCLK */

  PCLKSEL1 = 0x00000000;

#endif

#if (Fpclk / (Fcclk / 4)) == 2

  PCLKSEL0 = 0xAAAAAAAA;  /* PCLK is 1/2 CCLK */

  PCLKSEL1 = 0xAAAAAAAA;

#endif

#if (Fpclk / (Fcclk / 4)) == 4

  PCLKSEL0 = 0x55555555;  /* PCLK is the same as CCLK */

  PCLKSEL1 = 0x55555555;

看上面的程序结合下面的图片,就明白了,我不想给大家翻译英文,我相信大家英文水平。

 

 

接下来就是ConfigurePLL();  /* Configure PLL, switch from IRC to Main OSC */,注释说得很明白配置PLL

这个demo程序关于PLL的配置和周立功的例子程序有点不一样,我会一一标注一下的。这里讲的是LPC2378的时钟配置,内容比较多,比较繁琐,但是只要细心耐心的去看程序,我们就会明白LPC2378的时钟工作流程和一些模式。

其实我个人认为学习一个芯片的使用方法,首先就是搞懂它的时钟,这样,你才可以知道各个外设的时钟,才可以计算定时器定时时间,还有UARTIICSPIUSB等等接口的时钟,和相关的分频器的设置,只有时钟设置正确了,我们才可以正常的使用它们,设置好时钟是第一步。

我们就看看这个函数的具体内容是什么。它也定义在target.c中。


点击(此处)折叠或打开

  1. void ConfigurePLL ( void )

  2. {

  3. DWORD MValue, NValue;

  4.        if ( PLLSTAT & (1 << 25) )

  5.        {

  6.          PLLCON = 1; /* Enable PLL, disconnected */

  7.              PLLFEED = 0xaa;

  8.              PLLFEED = 0x55;

  9.     }

  10.   PLLCON = 0; /* Disable PLL, disconnected */

  11.   PLLFEED = 0xaa;

  12.   PLLFEED = 0x55;

  13.   SCS |= 0x20; /* Enable main OSC */

  14.   while( !(SCS & 0x40) ); /* Wait until main OSC is usable */

  15.   CLKSRCSEL = 0x1; /* select main OSC, 12MHz, as the PLL clock source */

  16.   PLLCFG = PLL_MValue | (PLL_NValue << 16);

  17.   PLLFEED = 0xaa;

  18.   PLLFEED = 0x55;

  19.   PLLCON = 1; /* Enable PLL, disconnected */

  20.   PLLFEED = 0xaa;

  21.   PLLFEED = 0x55;

  22.   CCLKCFG = CCLKDivValue; /* Set clock divider */

  23.   #if USE_USB

  24.     USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */

  25.   #endif

  26.   while ( ((PLLSTAT & (1 << 26)) == 0) ); /* Check lock bit status */

  27.   MValue = PLLSTAT & 0x00007FFF;

  28.   NValue = (PLLSTAT & 0x00FF0000) >> 16;

  29.   while ((MValue != PLL_MValue) && ( NValue != PLL_NValue) );

  30.   PLLCON = 3; /* enable and connect */

  31.   PLLFEED = 0xaa;

  32.   PLLFEED = 0x55;

  33.   while ( ((PLLSTAT & (1 << 25)) == 0) ); /* Check connect bit status */

  34.   return;

  35. }

 

 

 

if ( PLLSTAT & (1 << 25) )

       {

         PLLCON = 1;     /* Enable PLL, disconnected */

             PLLFEED = 0xaa;

             PLLFEED = 0x55;

    }

首先看看PLLSTAT这个状态寄存器所代表的意思。

PLLCON寄存器代表的意思

PLLCON = 1;就是PLLE=1;

 

PLLFEED = 0xaa;

PLLFEED = 0x55;

这两句,很简单,但是不可以少。呵呵。

 

到这里我们就是知道这个IF语句的功能了就是说,如果芯片上电以后,PLL有效并且供给CPU时钟的话,那么使得PLL有效,但是不给CPU供给时钟,bypass,呵呵。

 

PLLCON = 0;       /* Disable PLL, disconnected */

  PLLFEED = 0xaa;

  PLLFEED = 0x55;

使得PLL无效,当然了也不供给cpu时钟。

 

SCS |= 0x20;      /* Enable main OSC */

while( !(SCS & 0x40) ); /* Wait until main OSC is usable */

CLKSRCSEL = 0x1;    /* select main OSC, 12MHz, as the PLL clock source */

注释说得很明白了,但是我还是要重复一下,先看SCS寄存器。

 

  PLLCFG = PLL_MValue | (PLL_NValue << 16);

  PLLFEED = 0xaa;

  PLLFEED = 0x55;

 

 

PLLCFG寄存器说明中提到MN的这个2个变量,我们具体看一下它们代表什么意思。

 

 

target.h中的一些宏定义。

CCLKCFG = CCLKDivValue; /* Set clock divider */

从上面宏定义中的MN的值我们可以计算出Fcco=2X12X(24+1)/(1+1)=300,单位MHZ.

Fcclk=Fcco/(5+1)=50MHZ.和上面宏定义的一样。接下来就是检测当前设定的MN的值是否已经被PLL采用,开始工作了。否则,就是PC指针就一直在while处等待。

while ( ((PLLSTAT & (1 << 26)) == 0) ); /* Check lock bit status */

  MValue = PLLSTAT & 0x00007FFF;

  NValue = (PLLSTAT & 0x00FF0000) >> 16;

如果正常,保持实际的MN值,然后和预设的MN值对比,相同,就使能PLL并连接PLLcpu。否则就等待。

while ((MValue != PLL_MValue) && ( NValue != PLL_NValue) );

  PLLCON = 3;       /* enable and connect */

  PLLFEED = 0xaa;

  PLLFEED = 0x55;

查询PLL是否连接,没有,就等待。

  while ( ((PLLSTAT & (1 << 25)) == 0) ); /* Check connect bit status */

  return;

 

到这里PLL配置讲完了,下面补充一些PLL的东西。

这是LPC2378时钟示意图,中间涉及了各个时钟之间的关系,想明白时钟系统,必须知道这个示意图。

还有就是我一直没有找到相关信息,就是在这个demo程序里提到cpu时钟不可以超过80MHZ,周立功的程序也提到了这个80MHZ,我在lpc2378datasheet没有找到相关的东西,只是找到了这个

难道写程序的人是为了凑个整数?

对了还有,就是周立功程序中间还提到了使用中断方式设置PLL,这里就不多说了,自己可以去参考一下,周立功的程序中Fin=12M,M=12N=1Fcco=2X12X12/1=288M,Fcclk=72M.

这里的MN在使用的时候,我没有加1,原因是,周立功程序,在把M,N赋值给寄存器的时候减去1,也就是把M-1N-1赋值给了寄存器,所以这里计算频率就是MN的值了,

这个demo程序直接把MN赋值给了寄存器,所以计算频率的时候就需要加1了。

 

 


阅读(2278) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

我是一粒糖2012-04-16 21:46:37

瓦,这么详细,博主给力啊!