时钟体系

时钟概念:
★时钟脉冲:一个按一定电压幅度,一定时间间隔连续发出的脉冲信号;
★时钟频率:在单位时间(如:1秒)内产生的时钟秒冲数;
作用:
时钟信号是时序逻辑的基础
时钟的产生-晶振
晶振:晶体振荡器,是用石英晶体精密切割做成。
时钟产生-PLL
PLL:(锁相环)合成器=外部晶体+PLL电路。
S3C2440的主时钟晶振来自外部晶振(XTIPLL),或者是外部时钟(EXTCLK)。时钟生成器包含了一个振荡器(振荡放大器),其连接外部晶振,可以产生需要的高频,通过引脚OM[3:2]来决定时钟源时Crystal还是EXTCLK.
S3C2440有两个PLL:(1)MPLL和(2)UPLL,
UPLL专用于USB设备。
MPLL 用于CPU及其他外围器件。
通过MPLL会产生三个部分的时钟频率:
FCLK:用于CPU核;
HCLK:用于AHB(常用于高速外设)总线的设备,比如:SDRAM;
PCLK:用于APB(常用于低速外设)总线的设备,比如:UART.

 时钟启动流程:

      1.上电几毫秒后,外部晶振输出稳定,FCLK=外部晶振频率(12MHZ,nRESET

信号恢复高电平后,CPU开始执行命令。

      2.在设置MPLL的几个寄存器后,需要等待一段时间(Lock Time,MPLL的输出才稳定。在这段时间(Lock Time)内,FCLK停振,CPU停止工作。

Lock Time的长短由寄存器LOCKTIME设定。

     3.Lock Time之后,MPLL输出正常,CPU工作在新的FCLK(如:400MHZ)下。

设置S3C2440的时钟频率就是设置相关的几个寄存器:

 

 CLKDIVN

寄存器用于设置FCLK、HCLK、PCLK三者的比例
★  HDIVN:位[2:1],用来设置HCLK与FCLK比例关系
★  PDIVN:位[0],用来设置PCLK与HCLK比例关系
例如:
FCLK:HCLK:PCLK=4:2:1
FCLK=400MHZ(主频)
HCLK=200M
PCLK=100M

 

 void Set_Clk(void)    

{    
       int i;    
       U8 key;    
       U32 mpll_val = 0 ;  
       i = 2 ;                  
                              
       switch ( i ) {  
  
       case 0:    //200   
              key = 12;    
              mpll_val = (92<<12)|(4<<4)|(1);    
              break;   
       case 1:    //300    
              key = 13;  
              mpll_val = (67<<12)|(1<<4)|(1);   
              break;    
       case 2:    //400    
              key = 14;    
              mpll_val = (92<<12)|(1<<4)|(1);  
              break;  //FCLK=2*(92+8)*(12000000)/(3+2^1)=400000000=400MHz
  
       case 3:    //440!!!    
              key = 14;   
              mpll_val = (102<<12)|(1<<4)|(1);   
              break;    
       default:    
              key = 14;   
              mpll_val = (92<<12)|(1<<4)|(1);    
              break;    
       }               
       ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //设置rMPLLCON得到FCLK
       ChangeClockDivider(key, 12);    //经过CLKDIVE设置,确定FCLK、HCLK、PCLK三者之间的关系       
}  
void ChangeClockDivider(int hdivn_val,int pdivn_val)
{
    int hdivn=2, pdivn=0;
    
     // hdivn_val (FCLK:HCLK)ratio hdivn
     
// 11           1:1       (0)
     
// 12           2:1       (1)
     
// 13           3:1       (3) 
     
// 14           4:1       (2)
     
// pdivn_val (HCLK:PCLK)ratio pdivn
     
// 11           1:1       (0)
     
// 12           2:1       (1)
    switch(hdivn_val) {
        case 11: hdivn=0break;
        case 12: hdivn=1break;
        case 13:
        case 16: hdivn=3break;
        case 14
        case 18: hdivn=2break;
    }
    
    switch(pdivn_val) {
        case 11: pdivn=0break;
        case 12: pdivn=1break;
    }
    
    //Uart_Printf("Clock division change [hdiv:%x, pdiv:%x] ", hdivn, pdivn);
    rCLKDIVN = (hdivn<<1) | pdivn;  PCLK HCLK 分频

    switch(hdivn_val) {   //摄像头时钟分频
        case 16:        // when 1, HCLK=FCLK/8.
            rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8); 
        break
        case 18:     // when 1, HCLK=FCLK/6.
            rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9); 
        break;
    }
    
    if(hdivn!=0)
        MMU_SetAsyncBusMode();
    else 
        MMU_SetFastBusMode();   

}

 ARM920T有三种时钟模式:FastBus(快总线模式),synchronous(同步模式), asynchronous(异步模式)

FastBus(快总线模式)
  该模式将时钟BCLK作为时钟GCLK的源,时钟FCLK被忽略。主要用于带有高速存储器的系统。
synchronous(同步模式)
  该模式主要用于带有低速存储器的系统。时钟BCLK和时钟FCLK作为时钟GCLK的源,BCLK用于控制AMBA存储接口,FCLK用于控制内部的ARM9TDMI处理器核和任何cache缓存的操作。 FCLK的频率必须比BCLK高且是其整数陪,且在FCLK是高电平时BCLK才跳变。
asynchronous(异步模式)
  该模式主要用于带有低速存储器的系统。时钟BCLK和时钟FCLK作为时钟GCLK的源,BCLK用于控制AMBA存储接口,FCLK用于控制内部的ARM9TDMI处理器核和任何cache缓存的操作。FCLK的频率只需比BCLK高。
static void cal_cpu_bus_clk(void)   //cal“calculator”,计算器的简写
{                                   //这个函数用来计算cpu总线时钟
 static U32 cpu_freq;
    static U32 UPLL;
 
 U32 val;
 U8 m, p, s;
 
 val = rMPLLCON;      //将rMPLLCON拆开
 m = (val>>12)&0xff;
 p = (val>>4)&0x3f;
 s = val&3;
 //(m+8)*FIN*2 不要超出32位数!
 FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000
 
 val = rCLKDIVN;     //将rCLKDIVN拆开
 m = (val>>1)&3;
 p = val&1
 val = rCAMDIVN;
 s = val>>8;
 
 switch (m) {
 case 0:
  HCLK = FCLK;
  break;
 case 1:
  HCLK = FCLK>>1;
  break;
 case 2:
  if(s&2)
   HCLK = FCLK>>3;
  else
   HCLK = FCLK>>2;
  break;
 case 3:
  if(s&1)
   HCLK = FCLK/6;
  else
   HCLK = FCLK/3;
  break;
 }
 
 if(p)
  PCLK = HCLK>>1;
 else
  PCLK = HCLK;
 
 if(s&0x10)
  cpu_freq = HCLK;
 else
  cpu_freq = FCLK;
  
 val = rUPLLCON;//rUPLLCON内存的值为0x00038022求出UPLL的值为48MHz;时钟分频控制寄存器CLKDIVN[3]=0时UCLK=UPLL
 m = (val>>12)&0xff;
 p = (val>>4)&0x3f;
 s = val&3;
 UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
 UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;  USBCLK的值必须是48MHz
 Uart_Printf(" FCLK:%dMHz,HCLK:%dMHz,PCLK=%dMHZ ",FCLK/1000/1000,HCLK/1000/1000,PCLK/1000/1000);
}
/

定时器

频率 

 

 

 

 计数值

 

 

 

 


void Timer0_init(void)  
  
{     
  rTCFG0 = 49;              //pclk/(49+1)  
  rTCFG1 = 0x03;            //16分频=62500HZ  
                 
//定时器频率= 1M /(49+1)/16=62500HZ
  rTCNTB0 = 62500/2;          //TCNTB0[15:0]=计数值      
  rTCMPB0 = 0;               //比较值
  
  rTCON |=(1<<1);           //计数值装入TCNTB0、TCMPB0    
  
  rTCON =0x09;               //1001 自动重载,启动。
 
ClearPending(BIT_TIMER0);  //清除SRCPND、INTPND 此处课省略
  
/*当达到0.5秒时,执行中断函数IRQ_Timer0_Handle */  
  
  pISR_TIMER0 = (U32)IRQ_Timer0_Handle;       //中断向量 = 中断函数
  
  EnableIrq(BIT_TIMER0);   //手动打开屏蔽 INTMSK  
}  
  
static void __irq IRQ_Timer0_Handle(void)    
{    
    ClearPending(BIT_TIMER0);  //清中断   
    Led1_run();   

 

原文地址:https://www.cnblogs.com/liuchengchuxiao/p/4179080.html