公司网站域名主机,dw网页设计代码模板源代码,网络广告营销的典型案例,网站用字体一、STM32时钟设置函数移植
1.时钟模块回顾
一个疑问 前面代码并没有设置时钟为什么可以直接使用。 2.时钟树 3.时钟树分析
1.内部晶振#xff08;HSI#xff09; 内部晶振不稳定#xff0c;当我们上电后#xff0c;会自动产生振动#xff0c;自动产生时钟#xff0c;…一、STM32时钟设置函数移植
1.时钟模块回顾
一个疑问 前面代码并没有设置时钟为什么可以直接使用。 2.时钟树 3.时钟树分析
1.内部晶振HSI 内部晶振不稳定当我们上电后会自动产生振动自动产生时钟但是晶振不稳定。 不经过PPLMUL默认使用8MHZ。所以如果我们想要72MHZ则需要使用外部晶振 2.外部晶振HSE 当接上外部晶振当接通电源之后不用软件操作会自动产生振动。可以进行分频等操作。 从外部接上外部晶振的时候我们需要等待一段时间让其稳定后才开始工作。所以要进行判断 3.PLLMUL 当上电后经过他时要等待一段时间让其稳定后才可以开始工作。所以我们有一个寄存器专门用来判断其是否准备好开始工作当我们去读取到其准备好了才可以进行下一步 二、代码移植
#ifndef __CLOCK_H__
#define __CLOCK_H__#include gpio.h// 寄存器宏定义
// 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))// 函数作用时钟源切换到HSE并且使能PLL将主频设置为72MHz
void Set_SysClockTo72M(void);#endif
1.复位RCC_CR寄存器 #define rRCC_APB2ENR (*((unsigned int *)RCC_APB2ENR)) RCC-CR就相当于rRCC_APB2ENR //复位RCC_CR寄存器rRCC_CR0x00000083;
2.开启外部时钟就是开启外部晶振 将某一些位置0 |将某一些位置1 //开启外部时钟外部晶振//第一步先置0【将bit16清零】rRCC_CR ~(116);//关闭HSEON//第二步在置1rRCC_CR | (116);//打开HSEON让HSE开始工作
3.检测外部时钟开启是否成功HSEREDY do while十分适合检测是否超时 do{//检测HSEREAYbit17是否为11表示准备好Rcc_CR_HSE_ReadyrRCC_CR(117);//取出bit17faultTime;}while((faultTime0x0fffffff) (Rcc_CR_HSE_Ready0))//跳出do-while 1要么超时2要么准好了
4.当准备好进入下一步 5.Flash的设置 rFLASH_ACR | 0x10;rFLASH_ACR (~0x03);rFLASH_ACR | (0x02);
6.对其进行预分频 //HPRE【AHB】:对应bit4-bit7不分频000//PPRE1【APB1】:对应bit8-bit10:进行二分频100)//PPRE2【APB2】:对应bit11-bit13:不分频000//AHB和APB2未分频APB1被2分频//所以最终AHB和APB2都是72MHZAPB1是36MHZ//第一步:先置0rRCC_CFGR(~((0x0f4) | (0x078) | (0x0711)));//等价于:rRCC_CFGR(~(0x3ff4));//第二步置1rRCC_CFGR(((0x04) | (0x048) | (0x011)));
7.设置SHE为输入时钟同时HSE不分频 //设置为输入时钟:bit16//设置为不分频bit17//第一步:先置0rRCC_CFGR (~((116) | (117)));//第二步置1rRCC_CFGR | ((118) | (017));
8.设置PLL倍频系数 因为我们在开发板上接上的外部晶振就是8MHZ如果我们想要在内部使用72MHZ则需要在内部进行分频率9倍 //9分频01110x07rRCC_CFGR (~(0x0f18));//清零bit18-bit21rRCC_CFGR | (0x0718);//设置为9倍频
9.打开使能 //七、打开PLL开关rRCC_CR | (124);
10.等待开启PLL开启成功 //八、等待开启PLL开启成功do{Rcc_CR_PLL_ReadyrRcc_CR (125);//检测第25位是否为1faultTime;}while((faultTime0x0fffffff) (Rcc_CR_PLL_Ready0)) 11.将PLL作为SYSCLK的时钟来源 //到这里说明PLL已经稳定可以用了下面可以切换成外部时钟了rRCC_CFGR (~(0x03)0);rRCC_CFGR |(0x100); 12. 判断切换成PLL是否成功 do{RCC_CF_SWS_PLLrRCC_CFGR (0x032);//读出bit2-bit3faultTime;//0x022:表示此时转换成PLL}while((faultTime0x0fffffff) (Rcc_CR_PLL_Ready!(0x022)))
13.此时PLL转换成功 14.完整代码
#include clock.hvoid Set_SysClockTo72M(void){//检测外部晶振是否准备好unsigned int Rcc_CR_HSE_Ready0;//等待开启PLL开启成功unsigned int Rcc_CR_PLL_Ready0;//判断切换成PLL是否成功unsigned int RCC_CF_SWS_PLL0;unsigned int faultTime0;//判断等待是否超时//一、复位RCC_CR寄存器rRCC_CR 0x00000083;//二、开启外部时钟外部晶振//第一步先置0【将bit16清零】rRCC_CR ~(116);//关闭HSEON//第二步在置1rRCC_CR | (116);//打开HSEON让HSE开始工作//三、检测外部时钟开启是否成功do{//检测HSEREAYbit17是否为11表示准备好Rcc_CR_HSE_ReadyrRCC_CR(117);//取出bit17faultTime;}while((faultTime0x0fffffff) (Rcc_CR_HSE_Ready0));//跳出do-while 1要么超时2要么准好了//判断是超时还是准备好//注意点不能直接使用“Rcc_CR_HSE_Ready”因为rRCC_CR是需要读一次寄存器//但是读出的结果可能还未改变所以一定不能直接使用if((rRCC_CR(117))!0)//rRCC_CR(117)1{//这里HSE就ready下面再去配置PLL并且等待他ready//四、对其进行预分频//HPRE【AHB】:对应bit4-bit7不分频000//PPRE1【APB1】:对应bit8-bit10:进行二分频100)//PPRE2【APB2】:对应bit11-bit13:不分频000//AHB和APB2未分频APB1被2分频//所以最终AHB和APB2都是72MHZAPB1是36MHZ//第一步:先置0rRCC_CFGR(~((0x0f4) | (0x078) | (0x0711)));//等价于:rRCC_CFGR(~(0x3ff4));//第二步置1rRCC_CFGR(((0x04) | (0x048) | (0x011)));//五、设置SHE为输入时钟同时HSE不分频//选择HSE作为PLL输入并且HSE不分频//设置为输入时钟:bit16//设置为不分频bit17//第一步:先置0rRCC_CFGR (~((116) | (117)));//第二步置1,bit16rRCC_CFGR | ((118) | (017));//六、设置PLL倍频系数//9分频01110x07rRCC_CFGR (~(0x0f18));//清零bit18-bit21rRCC_CFGR | (0x0718);//设置为9倍频//七、打开PLL开关rRCC_CR | (124);//八、等待开启PLL开启成功do{Rcc_CR_PLL_ReadyrRCC_CR (125);//检测第25位是否为1faultTime;}while((faultTime0x0fffffff) (Rcc_CR_PLL_Ready0));if((rRCC_CR (125)) (125)){//到这里说明PLL已经稳定可以用了下面可以切换成外部时钟了//九、切换成PLLrRCC_CFGR (~(0x03)0);rRCC_CFGR |(0x100);//十、判断切换成PLL是否成功do{RCC_CF_SWS_PLLrRCC_CFGR (0x032);//读出bit2-bit3faultTime;//0x022:表示此时转换成PLL}while((faultTime0x0fffffff) (Rcc_CR_PLL_Ready!(0x022)));//十一、此时PLL转换成功if((rRCC_CFGR (0x032))(0x022)){//到这里我们的时钟整个就设置好了可以结束了}else{//到这里说明PLL输出作为PLL失败while(1);}}else{//到这里说明PLL启动时出错了PLL不能稳定工作while(1);}}else{//超时或者未准备好此时HSE不可以使用while(1);}}
三、问题解决
1.我们想要让led快速闪3下然后换成72MHZ的频率接着闪
void delay(){unsigned int i0,j0;for(i0;i1000;i){for(j0;j2000;j){}}
}void led_init(){rRCC_APB2ENR 0x00000008;rGPIOB_CRH 0x33333333;rGPIOB_ODR 0x0000ff00;//全灭}
void led_flash(void){unsigned int i0;for(i0;i3;i){rGPIOB_ODR 0x00000000;//全亮delay();rGPIOB_ODR 0x0000ff00;//全灭delay();}
}
void main(void){led_init();led_flash();Set_SysClockTo72M();led_flash();
} 但是实际上并无法实现只能在闪烁完3次后就熄灭。 2.问题解决 led初始化时默认是全亮的 1.degger方法 把点亮led灯的函数加到clock中去看看代码运行到哪里不会亮 2.判断超时变量的初始化 因为我们多次使用到超时变量则每一个进入do-while循环之前要重新置0 3.出错点