时钟讲解

1. 时钟晶振

image

  • 32.768RTC时钟源
  • 24主频及其他时钟源

2. 系统时钟详解

(不想详解了,都能查到)

2.1 7路PLL

image
为了方便生成时钟,生成了7路PLL

2.2 各路时钟分出来的PLD
2.3 时钟树

设置PLL和分频即可

3. 系统配置

3.1 系统主频配置
  • 要设置ARM内核主频为528Mhz,设置CACRR寄存器的ARM_PODF作为二分频,然后设置PLL1为1056MHz即可,CACRR的ARM_PODF为bit2-bit0 (001)
  • 设置PLL1为1056MHz PLL1 = pll1_sw_clk,他是有一个多路选择器image
  • pll1_sw_clk通过CCSR寄存器的pll1_sw_clk_sel选择,在修改PLL1时钟的时候,需要给它一个固定的备用的时钟step_clock, 首选使用24M,由CCSR的STEP_SEL
  • 切换之后,就可以修改PLL1的值,CCM_ANALOG_PLL_ARM寄存器的DIV_SELECT的bit6-0,公式是PLL1 = 24 * 倍数/2,倍数等于88
  • 在切换回PLL1之前,要设置CCARR寄存器为二分频,切记,要不超级溢出
    代码:
/* 初始化时钟 */
void clk_init()
{
	/* 设置主频位528MHz */
	if(((CCM->CCSR >> 2) & 0x1) == 0) //判断是不是使用main的PLL
	{
		// 如果是,就换成备用时钟
		CCM->CCSR &= ~(1 << 8); //step_clock = osc = 24M
		CCM->CCSR |= (1<<2); //这样就使用了备用时钟24M
	}
	/* 设置PLL1等于1056 */
	CCM_ANALOG->PLL_ARM |= (1 << 13);// ENANBLE位使能,使能输出
	CCM_ANALOG->PLL_ARM |= (88 << 0) & 0x7f;//88	

	/* 设置二分频 */
	CCM->CACRR |= 1 << 0;
	/* 设置好了之后需要切换回main_clk */
	CCM->CCSR &= ~(1 << 2);
}

4.PLL初始化

PLL2和PLL3。PLL2固定为528M,PLL3固定为480M

  • 初始化PLL2_PFD0-PFD3 CCM_ANALOG_PFD_528用于设置4路PFD 比如PFD0 = 528*18/PFD0_FRAC, 设置PFD0_FRAC
  • 初始化PLL3_PFD0-PFD3
void clk_init()
{
	/* 设置主频位528MHz */
	if(((CCM->CCSR >> 2) & 0x1) == 0) //判断是不是使用main的PLL
	{
		// 如果是,就换成备用时钟
		CCM->CCSR &= ~(1 << 8); //step_clock = osc = 24M
		CCM->CCSR |= (1<<2); //这样就使用了备用时钟24M
	}
	/* 设置PLL1等于1056 */
	CCM_ANALOG->PLL_ARM |= (1 << 13);// ENANBLE位使能,使能输出
	CCM_ANALOG->PLL_ARM |= (88 << 0) & 0x7f;//88	

	/* 设置二分频 */
	CCM->CACRR |= 1 << 0;
	/* 设置好了之后需要切换回main_clk */
	CCM->CCSR &= ~(1 << 2);


	/* 设置PLL2的四路PFD */
	unsigned int reg = 0; //设置一个变量用于保存寄存器的值
	reg = CCM_ANALOG->PFD_528;
	reg &= ~(0x3f3f3f3f);//全部清零
	reg |= (34<<24);			// PLL2_PFD3 = 297
	reg |= (24<<16);	 		// PLL2_PFD2 = 400(396)
	reg |= (16<<8);				// PLL2_PFD1 = 594
	reg |= (27<<0);				// PLL2_PFD0 = 352
	CCM_ANALOG->PFD_528 = reg;

	/* 设置PLL3的四路PFD */
	//480 * 18 / 倍数
	reg = 0;
	reg = CCM_ANALOG->PFD_480;
	reg |= (19<<24);			// PLL3_PFD3 = 454.7
	reg |= (17<<16);			// PLL3_PFD2 = 508.2
	reg |= (16<<8);				// PLL3_PFD1 = 540
	reg |= (12<<0);				// PLL3_PFD0 = 720
	CCM_ANALOG->PFD_480 = reg;
}

4.其他时钟源外设

AHB PERCLK IPG
因为PERCLK和IPGclk要用到AHB的clk
AHB = 132
PERCLK = IPG = 66

#include "bsp_clk.h"


/*
 * @description	: 使能I.MX6U所有外设时钟
 * @param 		: 无
 * @return 		: 无
 */
void clk_enable(void)
{
	CCM->CCGR0 = 0XFFFFFFFF;
	CCM->CCGR1 = 0XFFFFFFFF;
	CCM->CCGR2 = 0XFFFFFFFF;
	CCM->CCGR3 = 0XFFFFFFFF;
	CCM->CCGR4 = 0XFFFFFFFF;
	CCM->CCGR5 = 0XFFFFFFFF;
	CCM->CCGR6 = 0XFFFFFFFF;
}

/* 初始化时钟 */
void clk_init()
{
	/* 设置主频位528MHz */
	if(((CCM->CCSR >> 2) & 0x1) == 0) //判断是不是使用main的PLL
	{
		// 如果是,就换成备用时钟
		CCM->CCSR &= ~(1 << 8); //step_clock = osc = 24M
		CCM->CCSR |= (1<<2); //这样就使用了备用时钟24M
	}
	/* 设置PLL1等于1056 */
	CCM_ANALOG->PLL_ARM |= (1 << 13);// ENANBLE位使能,使能输出
	CCM_ANALOG->PLL_ARM |= (88 << 0) & 0x7f;//88	

	/* 设置二分频 */
	CCM->CACRR |= 1 << 0;
	/* 设置好了之后需要切换回main_clk */
	CCM->CCSR &= ~(1 << 2);


	/* 设置PLL2的四路PFD */
	unsigned int reg = 0; //设置一个变量用于保存寄存器的值
	reg = CCM_ANALOG->PFD_528;
	reg &= ~(0x3f3f3f3f);//全部清零
	reg |= (34<<24);			// PLL2_PFD3 = 297
	reg |= (24<<16);	 		// PLL2_PFD2 = 400(396)
	reg |= (16<<8);				// PLL2_PFD1 = 594
	reg |= (27<<0);				// PLL2_PFD0 = 352
	CCM_ANALOG->PFD_528 = reg;

	/* 设置PLL3的四路PFD */
	//480 * 18 / 倍数
	reg = 0;
	reg = CCM_ANALOG->PFD_480;
	reg |= (19<<24);			// PLL3_PFD3 = 454.7
	reg |= (17<<16);			// PLL3_PFD2 = 508.2
	reg |= (16<<8);				// PLL3_PFD1 = 540
	reg |= (12<<0);				// PLL3_PFD0 = 720
	CCM_ANALOG->PFD_480 = reg;

	/* 配置AHB时钟 */
	//选择CBCMR的PRE_PERIPH_CLK_SEL配置使用PLL2_PDF2
	CCM->CBCMR &= ~(3 << 18);
	CCM->CBCMR |= (1 << 18); //PRE_PERIPH_CLK_SEL
	//CBCDR寄存器PRE_PERIPH_CLK_SEL外设主时钟为PLL2

	CCM->CBCDR &= ~(1 << 25);
	//注意设置完毕之后一定要等握手信号不忙!
	while(CCM->CDHIPR & (1 << 5)); //·判断遮盖为真
#if 0
	//这里其实不需要设置3分频,bootrom已经设置好啦,强行设置可能时钟卡死
	//最后再设置分频器 396/3
	CCM->CBCDR &= ~(7 << 10); //对3位清楚
	CCM->CBCDR |= (2 << 10);

	//注意设置完毕之后一定要等握手信号不忙!
	while(CCM->CDHIPR & (1 << 1)); //·判断遮盖为真
#endif
	/* IPG = 66 */
	CCM->CBCDR &= ~(3 << 8);
	CCM->CBCDR |= (1 << 8);
	/* PERCLK = 66 选择AHB为时钟源*/
	//CSCMR PERCLK_PODF
	// 看原理图可知,要先设置CBCDR的IPG_PODF,二分频设置好之后再上面那个,等于一举两得
	// PERCLK_CLK_SEL为0表示使用ipg
	CCM->CSCMR1 &= ~(1 << 6);
	CCM->CSCMR1 &= ~(0x3f << 0); //虽然使用了3位,但实际6位
	CCM->CSCMR1 |= (0 << 0); //1分频

}

5. 有时候代码烧不进去可以make clean一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值