• stm32时钟设置


    在做项目时,碰到一个问题被困扰很久,采集交流电均值时会出现结果为零的情况,但是我设计的是采集一个周期数据的均值,因此是不可能为零的。
    随着不断深入寻找错误,发现是因为我采用的模板晶振为8MHZ,而我使用的板子外部晶振为25MHZ。
    出现这个问题的主要原因是,之前一直使用的是F103的板子,手册上明确表示晶振的选型范围是4-16MHZ

    而我现在使用的板子为F107,晶振是可以使用25MHZ的,所以没有想到会是这个的原因。

    问题解决了,但是也证明自己对时钟这边了解不够深入。遂趁周末好好学习了一下,做个记录。
    下面为F103芯片时钟的配置过程:

    // 寄存器宏定义
    // RCC寄存器基地址为0x40021000
    #define RCC_BASE	0x40021000			// RCC部分寄存器的基地址
    #define RCC_CR		(RCC_BASE + 0x00)	// RCC_CR的地址
    #define RCC_CFGR	(RCC_BASE + 0x04)
    
    #define FLASH_ACR	0x40022000
    
    // 用C语言来访问寄存器的宏定义
    #define rRCC_CR		(*((volatile unsigned int *)RCC_CR))
    #define rRCC_CFGR	(*((volatile unsigned int *)RCC_CFGR))
    #define rFLASH_ACR	(*((volatile unsigned int *)FLASH_ACR))
    
    void Set_SysClockTo72M(void)
    {
    	unsigned int rccCrHserdy = 0;
    	unsigned int rccCrPllrdy = 0;
    	unsigned int rccCfrSwsPll = 0;
    	unsigned int faultTime = 0;
        
    	rRCC_CR = 0x00000083;
    	rRCC_CR &= ~(1<<16);	  	// bit16为0,关闭HSEON
    	rRCC_CR |= (1<<16);			// 打开HSEON,让HSE工作,这里的打开关闭主要是指内部振荡电路
    
    	do                      //开始振荡到稳定需要一段时间,所以需要判断
    	{
    		rccCrHserdy = rRCC_CR & (1<<17);	//检测第17位是否为1,第17位为HSERDY
    		faultTime++;//检测时间
    	}
    	while ((faultTime<0x0FFFFFFF) && (rccCrHserdy==0));  //不超时或者HSERDY为0,也就是没准备好,继续循环
    
    	if ((rRCC_CR & (1<<17)) != 0)   //不为零说明是因为HSERDY为1,也就是HSE准备好了
    	{
    		rFLASH_ACR |= 0x10;         //与FLASH相关,暂不深究
    		rFLASH_ACR &= (~0x03);
    		rFLASH_ACR |= (0x02);
    
    		// 到这里HSE就ready了,下面再去配PLL并且等待他ready
    		//HPRE为bit4-7,是AHB预分频器;PPRE1为8-10,APB1;PPRE2为11-13,APB2;
    		rRCC_CFGR &= (~((0x0f<<4) | (0x07<<8) | (0x07<<11))); //全部置0
    		//rRCC_CFGR &= (~(0x3ff<<4));
    		// AHB和APB2未分频,APB1被2分频,所以最终:AHB和APB2都是72M,APB1是36M 
    		rRCC_CFGR |= ((0x0<<4) | (0x04<<8) | (0x0<<11));
    
    		// PLLSRC为bit16,输入时钟源;PLLXTPRE为bit17,HSE分频后作为PLL输入;
    		//选择HSE作为PLL输入并且HSE不分频,所以PLL输入为8M
    		rRCC_CFGR &= (~((1<<16) | (1<<17)));   	// 清零bit17和bit16
    		rRCC_CFGR |= ((1<<16) | (0<<17));		// 置1 bit16
    
    		// 设置PLL倍频系数为9
    		rRCC_CFGR &= (~(0x0f<<18));   			// PLLMUL倍频参数bit18-21 清零
    		rRCC_CFGR |= (0x07<<18);				// 9倍频
    
    		// 打开PLL开关
    		rRCC_CR |= (1<<24);
    
    		// do while 循环等待PLL时钟稳定
    		faultTime = 0;
    		do
    		{
    			rccCrPllrdy = rRCC_CR & (1<<25);	//检测第25位是否为1
    			faultTime++;//检测时间
    		}
    		while ((faultTime<0x0FFFFFFF) && (rccCrPllrdy==0));
    		//while (rccCrPllrdy==0);
    
    		if ((rRCC_CR & (1<<25)) == (1<<25))
    		{
    		  	// 到这里说明PLL已经稳定了,可以用了,下面就可以切了
    			
    			// 切换PLL输出为SYSCLK
    			//SW系统时钟切换bit1:0,10表示PLL作为系统时钟
    			rRCC_CFGR &= (~(0x03<<0));   //低两位置零
    			rRCC_CFGR |= (0x02<<0);	     //bit2置为1
    
    			faultTime = 0;
    			do
    				{                                        //SWS系统时钟转换状态位bit3:2
    				rccCfrSwsPll = rRCC_CFGR & (0x03<<2);	//检测第2、3位
    				faultTime++;//检测时间
    			}
    			while ((faultTime<0x0FFFFFFF) && (rccCfrSwsPll!=(0x02<<2)));
    			
    		   	if ((rRCC_CFGR & (0x03<<2))== (0x02<<2))
    			{
    				// 到这里我们的时钟整个就设置好了,可以结束了
    
    			}
    			else
    			{
    				// 到这里就说明PLL输出作为SYSCLK不成功
    				while (1);
    			}
    
    		}
    		else
    		{
    			// 到这里就说明PLL启动时出错了,PLL不能稳定工作
    			while (1);
    		}
    
    	}
    	else        //HSE没有开启,死循环
    	{
    		// HSE配置超时,说明HSE不可用,一般硬件就有问题要去查
    		while (1);   
    	}
    }
    

    25MHZ的晶振就是通过如下图的方式来倍频成72MHZ的

  • 相关阅读:
    inotifywait 目录或文件的监控
    outlook邮件中样式问题
    IE8兼容问题
    12px以下字体显示问题
    box-shadow
    cropper.js图片裁剪
    利用vcard和qrcode.js生成二维码导入联系人
    使用link rel="shortcut icon"为网页标题加图标
    将input或textarea设置为disabled的样式问题
    img没有src属性时自动出现边框
  • 原文地址:https://www.cnblogs.com/roscangjie/p/14164813.html
Copyright © 2020-2023  润新知