话不多说 先上代码!代码里面带有备注。
#include "rcc.h"
/*
函数功能:配置时钟
函数参数:无
函数返回值:无
函数描述:时钟源为HSE,系统时钟为168MHZ,其它时钟为最大值
*/
void Config_SystemClock(uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
{
RCC_DeInit(); //让所有RCC时钟为缺省值等待我们配置
RCC_HSEConfig(RCC_HSE_ON); //让HSE作为时钟源
RCC_HSICmd(DISABLE); //让HSI不使能 有HSE就够了 一个时钟源
if(RCC_WaitForHSEStartUp() == SUCCESS) //等待HSE起振
{
RCC_ClockSecuritySystemCmd(ENABLE); //时钟安全系统使能 时钟监测器将在 HSE 振荡器就绪时由硬件使能,并在检出振荡器故障时由硬件禁止
RCC_PLLConfig(RCC_PLLSource_HSE,PLLM,PLLN,PLLP,PLLQ); //配置PLL系统时钟 让HSE作为系统时钟源
RCC_PLLCmd(ENABLE); //使能
RCC_HCLKConfig(RCC_SYSCLK_Div1); //高速总线不分频
RCC_PCLK1Config(RCC_HCLK_Div4); //APB1总线 48MHZ 最大频率
RCC_PCLK2Config(RCC_HCLK_Div2); //APB2总线 84HZ; 最大频率
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //这一步是关键等待PLL就绪 等于SET时就是锁住了 可以用PLL作为系统时钟了
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //确定PLL作为系统时钟
}
}
代码里面APB1和APB2设定为最大频率了,如下图网上找到的。
第一张图里面的while语句是为了等待HSE振荡器就绪,就绪了才能工作。 不就绪设定的频率就不生效了或者说有毛病了。
图上红色部分是修改过的寄存器,红色打勾的是使用的, ×的是禁止使用的,HSI时钟源 我禁止了,其它的未配置用到的时候再配置。
位带操作的思想 记住一条公式:(外设和SRAM都适用)
*(volatile uint32_t *)((0x40021414 & 0xf0000000) + 0x2000000 + ((0x40021414 &0xfffff) << 5) + (9 << 2)) = 0;
更新一下:
#define BITBAND(addr,bit) ((addr & 0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bit<<2); 这一条公式更好理解更好记住。
更新完毕
这里是把PF9 置 0 ;
右望左看 volatile 易变的,在这里要不要都可以,使用位操作时通常都是使用频率高的变量,需要快速反应。volatile说明不让编译器优化,多线程中该类型常用。
0x40021414是 GPIOF中ODR寄存器的地址。
0xf0000000 、 0x2000000 、 0xfffff 、5 、 2是公式上固定的值不需要改变。
9 是代表 寄存器地址对应的哪个位。
等号右边的0 是 把该位置零
下图便于理解
以上内容为博主学习的笔记,很多都是个人理解加网上摘录,主要是以后用到了这些内容能快速找到。