初级会员

- 积分
- 113
- 金钱
- 113
- 注册时间
- 2014-2-4
- 在线时间
- 22 小时
|
//时钟设置函数,对于版本V的芯片来说
//晶振频率先n分频(2-63),分频后的频率1-16M。按实际频率还需要PLL设置
//然后m倍频(4-512).倍频后的频率为190-960M,实际上只能是960M
//p分频固定为2,得到系统频率480M
//q分频固定为4,得到总线频率240M
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllreg)
{
u16 retry=0;
u8 status=0;
PWR->CR3&=~(1<<2); //SCUEN=0,锁定LDOEN和BYPASS位的设置
PWR->D3CR|=3<<14; //VOS=3,Scale1,1.15~1.26V内核电压,FLASH访问可以得到最高性能
while((PWR->D3CR&(1<<13))==0); //等待电压稳定
RCC->CR|=1<<16; //HSEON=1,开启HSE
while(((RCC->CR&(1<<17))==0)&&(retry<0X7FFF))retry++;//等待HSE RDY
if(retry==0X7FFF)status=1; //HSE无法就绪
else
{
RCC->PLLCKSELR|=2<<0; //PLLSRC[1:0]=2,选择HSE作为PLL的输入时钟源
RCC->PLLCKSELR|=plln<<4; //DIVM1[5:0]=pllm,设置PLL1的预分频系数
RCC->PLL1DIVR|=(pllm-1)<<0; //DIVN1[8:0]=plln-1,设置PLL1的倍频系数,设置值需减1
RCC->PLL1DIVR|=(2-1)<<9; //DIVP1[6:0]=pllp-1,设置PLL1的p分频系数,设置值需减1
RCC->PLL1DIVR|=(4-1)<<16;//DIVQ1[6:0]=pllq-1,设置PLL1的q分频系数,设置值需减1
RCC->PLL1DIVR|=1<<24; //DIVR1[6:0]=pllr-1,设置PLL1的r分频系数,设置值需减1,r分频出来的时钟没用到
RCC->PLLCFGR|=pllreg<<2; //PLL1RGE[1:0]=2,PLL1输入时钟频率在4~8Mhz之间(25/5=5Mhz),如修改pllm,请确认此参数
RCC->PLLCFGR|=0<<1; //PLL1VCOSEL=0,PLL1宽的VCO范围,192~836Mhz
RCC->PLLCFGR|=3<<16; //DIVP1EN=1,DIVQ1EN=1,使能pll1_p_ck和pll1_q_ck
RCC->CR|=1<<24; //PLL1ON=1,使能PLL1
while((RCC->CR&(1<<25))==0);//PLL1RDY=1?,等待PLL1准备好
//设置PLL2的R分频输出,为200Mhz,后续做SDRAM时钟,可得到100M的SDRAM时钟频率
RCC->PLLCKSELR|=HSE_FREQ<<12; //DIVM2[5:0]=25,设置PLL2的预分频系数
RCC->PLL2DIVR|=(400-1)<<0; //DIVN2[8:0]=440-1,设置PLL2的倍频系数,设置值需减1
RCC->PLL2DIVR|=(2-1)<<9; //DIVP2[6:0]=2-1,设置PLL2的p分频系数,设置值需减1
RCC->PLL2DIVR|=(2-1)<<24; //DIVR2[6:0]=2-1,设置PLL2的r分频系数,设置值需减1
RCC->PLLCFGR|=0<<6; //PLL2RGE[1:0]=0,PLL2输入时钟频率在1~2Mhz之间(25/25=1Mhz)
RCC->PLLCFGR|=0<<5; //PLL2VCOSEL=0,PLL2宽的VCO范围,192~836Mhz
RCC->PLLCFGR|=1<<19; //DIVP2EN=1,使能pll2_p_ck
RCC->PLLCFGR|=1<<21; //DIVR2EN=1,使能pll2_r_ck
RCC->D1CCIPR&=~(3<<0); //清除FMCSEL[1:0]原来的设置
RCC->D1CCIPR|=2<<0; //FMCSEL[1:0]=2,FMC时钟来自于pll2_r_ck
RCC->CR|=1<<26; //PLL2ON=1,使能PLL2
while((RCC->CR&(1<<27))==0);//PLL2RDY=1?,等待PLL2准备好
RCC->D1CFGR|=8<<0; //HREF[3:0]=8,rcc_hclk1/2/3/4=sys_d1cpre_ck/2=400/2=200Mhz,即AHB1/2/3/4=200Mhz
RCC->D1CFGR|=0<<8; //D1CPRE[2:0]=0,sys_d1cpre_ck=sys_clk/1=400/1=400Mhz,即CPU时钟=400Mhz
RCC->CFGR|=3<<0; //SW[2:0]=3,系统时钟(sys_clk)选择来自pll1_p_ck,即400Mhz
while(1)
{
retry=(RCC->CFGR&(7<<3))>>3; //获取SWS[2:0]的状态,判断是否切换成功
if(retry==3)break; //成功将系统时钟源切换为pll1_p_ck
}
FLASH->ACR|=2<<0; //LATENCY[2:0]=2,2个CPU等待周期(@VOS1 Level,maxclock=210Mhz)
FLASH->ACR|=2<<4; //WRHIGHFREQ[1:0]=2,flash访问频率<285Mhz
RCC->D1CFGR|=4<<4; //D1PPRE[2:0]=4,rcc_pclk3=rcc_hclk3/2=100Mhz,即APB3=100Mhz
RCC->D2CFGR|=4<<4; //D2PPRE1[2:0]=4,rcc_pclk1=rcc_hclk1/2=100Mhz,即APB1=100Mhz
RCC->D2CFGR|=4<<8; //D2PPRE2[2:0]=4,rcc_pclk2=rcc_hclk1/2=100Mhz,即APB2=100Mhz
RCC->D3CFGR|=4<<4; //D3PPRE[2:0]=4,rcc_pclk4=rcc_hclk4/2=100Mhz,即APB4=100Mhz
RCC->CR|=1<<7; //CSION=1,使能CSI,为IO补偿单元提供时钟
RCC->APB4ENR|=1<<1; //SYSCFGEN=1,使能SYSCFG时钟
SYSCFG->CCCSR|=1<<0; //EN=1,使能IO补偿单元
}
return status;
}
//计算频率配置
//fr为需要的频率,例如480,xtal为晶振,例如8
int Sys_Clock_Calc(u32 fr,u32 xtal){
u32 vv; //输入范围
u32 mm;//倍频
u32 hz;
u32 pp;//预分频
for(pp=2;pp<=63;pp++){
hz=xtal*65536/pp;//VCO输入频率,晶振频率按系数pp分频
if(hz<1*65536)continue;//判断输入范围是否合理
else if(hz<2*65536)vv=0;
else if(hz<4*65536)vv=1;
else if(hz<8*65536)vv=2;
else if(hz<=16*65536)vv=3;
else continue;
mm=fr*2*pp/(xtal); //倍频计算
if(mm<4||mm>512)continue;//倍频不合理
hz=xtal*mm/(pp*2); //实际输出频率
if(hz==fr){ //频率正确
Sys_Clock_Set(pp,mm,vv);//设置时钟
return 1;
}
}
return 0;//此晶振无法得到需要的频率
}
对寄存器版的程序做了一些修改,可以根据晶振和CPU主频自动配置寄存器。
|
|