day13:设置系统时钟固件库编程

固件库编程方式:

在main.c同级目录下新建目录:rcc

在rcc目录下新建两个文件:bsp_clkconfig.c和bsp_clkconfig.h

bsp_clkconfig.h:

#ifndef __BSP_CLKCONFIG_H__
#define __BSP_CLKCONFIG_H__

#include "stm32f10x.h"

/* 使用HSE配置系统时钟 */
void HSE_SetSysClk(uint32_t RCC_PLLMul);

#endif	/* __BSP_CLKCONFIG_H__ */

 bsp_clkconfig.c:

#include "./rcc/bsp_clkconfig.h"

/* 使用HSE配置系统时钟:RCC_PLLMul是倍频因子 */
void HSE_SetSysClk(uint32_t RCC_PLLMul)
{
	/* HSEStatus:状态,成功或失败 */
	__IO uint32_t HSEStatus = 0;
	
	/* 1.复位RCC寄存器到默认值 */
	RCC_DeInit();
	
	/* 2.使能HSE */
	RCC_HSEConfig(RCC_HSE_ON);
	
	/* 3.等待HSE稳定 */
	HSEStatus = RCC_WaitForHSEStartUp();
	if(HSEStatus == SUCCESS)	/* 启动成功 */
	{
		/* 4.使能预取值 */
		FLASH->ACR |= FLASH_ACR_PRFTBE;
		
		/* 5.FLASH的等待时间 */
		FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
		FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;   
		
		/* 6.配置三条总线(AHB、APB1、APB2)的分频因子 */
		RCC_HCLKConfig(RCC_SYSCLK_Div1);	/* AHB:1分频,72MHZ/1=72MHZ */
		RCC_PCLK1Config(RCC_HCLK_Div2);		/* APB1:2分频,72MHZ/2=36MHZ */
		RCC_PCLK2Config(RCC_HCLK_Div1);		/* APB2:1分频,72MHZ/1=72MHZ */
		
		/* 7.配置锁相环PLL:第一个参数:时钟源(这里使用HSE的不分频),第二个参数:倍频因子 */
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul);
		
		/* 8.使能PLL */
		RCC_PLLCmd(ENABLE);
		
		/* 9.等待PLL稳定,如果是RESET,则不稳定,就会一直等下去 */
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
		
		/* 10.把锁相环时钟设置成系统时钟:参数是时钟源 */
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		
		/* 11.判断锁相环PLL是否已经设置成了系统时钟,如果不是,那么一直等下去 */
		while(RCC_GetSYSCLKSource() != 0x08);
	}
	else
	{
		/* HSE启动失败,在这里添加错误的处理代码 */
		/* 启动失败的原因:1.晶振坏了;2.电容坏了;3.器件不匹配;一般是硬件的原因 */
	}
	
}

 LED相关的:

bsp_led.h:

/* 和LED功能模块相关的程序 */

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

#include "stm32f10x.h"

/*宏定义*/
#define GPIO_CLK_D4			RCC_APB2Periph_GPIOC		// 时钟
#define GPIO_PORT_D4		GPIOC						// C端口
#define GPIO_PIN_D4			GPIO_Pin_2					// PC2引脚

#define GPIO_CLK_D5			RCC_APB2Periph_GPIOC		// 时钟
#define GPIO_PORT_D5		GPIOC						// C端口
#define GPIO_PIN_D5			GPIO_Pin_3					// PC2引脚

/*参数宏定义*/
/*
digitalTOGGLE(p,i)是参数宏定义,p表示LED的端口号,ODR是数据输出寄存器,
查stm32f10x的官方中文手册的第8.2章的ODR寄存器,要点亮LED,根据原理图,要输出低电平0,
C语言中,^表示异或,即a^b表示a和b不同时输出为1,相同时输出为0,比如0^1=1,1^1=0,0^0=0,
这里为什么操作ODR,p是什么?查看stm32f10x.h文件,搜索GPIO_TypeDef就会明白,
i是LED的引脚对应的位电平,经过digitalTOGGLE(p,i)	{p->ODR ^= i;}之后,
第一次p为0,i一直为1,第一次异或结果输出1,第二次输出0,第三次输出1,这样间断输出010101,灯不断亮灭
*/
#define digitalTOGGLE(p,i)	{p->ODR ^= i;}
#define LED1_TOGGLE			digitalTOGGLE(GPIO_PORT_D4,GPIO_PIN_D4)
#define LED2_TOGGLE			digitalTOGGLE(GPIO_PORT_D5,GPIO_PIN_D5)

/*配置GPIO*/
void LED_GPIO_Config(void);

#endif	/*__BSP_LED_H__*/

 bsp_led.c:

/* 和LED功能模块相关的程序头文件 */

#include "./led/bsp_led.h"	/*绝对路径,也可在Options for target中设置头文件*/

/*GPIO初始化*/
void LED_GPIO_Config(void)
{
	/*外设结构体*/
	GPIO_InitTypeDef GPIO_InitStruct_D4, GPIO_InitStruct_D5;	
	
	/*第一步:打开外设的时钟,看stm32f10x_rcc.c这个文件的RCC_APB2PeriphClockCmd函数介绍*/
	RCC_APB2PeriphClockCmd(GPIO_CLK_D4, ENABLE);
	
	/*第二步:配置外设的初始化结构体*/
	GPIO_InitStruct_D4.GPIO_Pin = GPIO_PIN_D4;			// PC2的那盏LED灯(D4)的引脚
	GPIO_InitStruct_D4.GPIO_Mode = GPIO_Mode_Out_PP;	// 推挽输出模式
	GPIO_InitStruct_D4.GPIO_Speed = GPIO_Speed_10MHz;	// 引脚速率
	
	GPIO_InitStruct_D5.GPIO_Pin = GPIO_PIN_D5;			// PC3的那盏LED灯(D5)的引脚
	GPIO_InitStruct_D5.GPIO_Mode = GPIO_Mode_Out_PP;	// 推挽输出模式
	GPIO_InitStruct_D5.GPIO_Speed = GPIO_Speed_10MHz;	// 引脚速率
	
	/*第三步:调用外设初始化函数,把配置好的结构体成员写到寄存器里面*/
	GPIO_Init(GPIO_PORT_D4, &GPIO_InitStruct_D4);
	GPIO_Init(GPIO_PORT_D5, &GPIO_InitStruct_D5);
}

 main.c:

/* 使用HSE配置系统时钟的案例 */

#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./rcc/bsp_clkconfig.h"

/* 延迟函数 */
void delay(unsigned int i)
{
    for(; i!=0; i--);
}

/* 在程序来到main函数的时候,系统时钟已经配置成72MHz */
int main(void)
{
	/* 如果不设置系统时钟,则会默认使用72MHZ频率晶振的系统时钟 
	*  这里设置了系统时钟,参数是倍频因子,一开始系统时钟为8MHZ,比如倍频因子为2,则最后为16MHZ
	*/
	HSE_SetSysClk(RCC_PLLMul_2);
	
	// LED初始化
	LED_GPIO_Config();		
	
	/* 点亮LED */
	while(1)
	{
		/* 配置ODR寄存器 */
		GPIO_ResetBits(GPIO_PORT_D4, GPIO_PIN_D4);		// 调用自定义库函数进行清零
		delay(0XFFFFF);		
		GPIO_SetBits(GPIO_PORT_D4, GPIO_PIN_D4);		// 调用自定义库函数进行置1
		
		/* 配置ODR寄存器 */
		GPIO_ResetBits(GPIO_PORT_D4, GPIO_PIN_D5);		// 调用自定义库函数进行清零
		delay(0XFFFFF);		
		GPIO_SetBits(GPIO_PORT_D4, GPIO_PIN_D5);		// 调用自定义库函数进行置1	
	}
}

实验现象:

如果不配置系统时钟:HSE_SetSysClk(RCC_PLLMul_2);

则系统时钟默认为72MHZ,LED灯闪烁速度很快,

如果设置了系统时钟,但倍频因子RCC_PLLMul_2越小,LED灯闪烁的速度越慢,其中RCC_PLLMul_2可以取值1-9,对应的系统

时钟频率为:[1-9]*8MHZ,频率越大,LED灯闪烁的速度越快!

 

更多的关于系统时钟的文章:http://www.cnblogs.com/josephcnblog/articles/9017412.html

 

posted @ 2018-05-11 23:48  半生戎马,共话桑麻、  阅读(347)  评论(0)    收藏  举报
levels of contents