OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2941|回复: 0

H7XX芯片PLL自动配置函数的实现

[复制链接]

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2014-2-4
在线时间
22 小时
发表于 2020-6-17 09:31:01 | 显示全部楼层 |阅读模式
//时钟设置函数,对于版本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主频自动配置寄存器。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-1 09:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表