将stm32f103的工程模板改为stm32f105vc,修改为8MHz时钟

news/2024/11/24 16:50:45/

103的工程模板改105的大体步骤和上一篇ZET6改C8T6的相差不大,只是改成105之后,问题就来了,发现它的 HSE_VALUE 默认定义为25MHz,WTF,板子都做回来了,晶振买的也是8MHz,搞个锤子

#if !defined  HSE_VALUE#ifdef STM32F10X_CL   #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */#else #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* STM32F10X_CL */
#endif /* HSE_VALUE */

看了一下105的时钟树:那些主要的外设都是挂在SYSCLK上面,也就是来源于PLLCLK的时钟。
在这里插入图片描述
首先看一下官方的对于系统时钟的配置:为了方便起见,我把多余的代码删掉了

void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit 确保内部8MHz振荡器开启。*/RCC->CR |= (uint32_t)0x00000001;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */RCC->CFGR &= (uint32_t)0xF0FF0000;/* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= (uint32_t)0xFF80FFFF;/* Reset PLL2ON and PLL3ON bits */RCC->CR &= (uint32_t)0xEBFFFFFF;/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x00FF0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers *//* Configure the Flash Latency cycles and enable prefetch buffer */SetSysClock();SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}

首先对 RCC->CR、RCC->CFGR、RCC->CIR三个寄存器进行复位或者设置,之后调用SetSysClock(); 正式对系统时钟进行设置。由于我们要将系统时钟设置为 72MHz,所以在 SetSysClock() 中后面调用的就是 SetSysClockTo72(void) 这个函数。函数原型如下:为了方便阅读,将部分无关代码删除。

static void SetSysClockTo72(void)
{__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    /* Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON);/* Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));if ((RCC->CR & RCC_CR_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  if (HSEStatus == (uint32_t)0x01){/* Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/* Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    /* HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK/2 */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;#ifdef STM32F10X_CL/* Configure PLLs ------------------------------------------------------*//* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz *//* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);/* Enable PLL2 */RCC->CR |= RCC_CR_PLL2ON;/* Wait till PLL2 is ready */while((RCC->CR & RCC_CR_PLL2RDY) == 0){}/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); 
#else    #endif /* STM32F10X_CL *//* Enable PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}}else{ /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */}
}

以下对程序进行分析。

  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    /* Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON);/* Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));if ((RCC->CR & RCC_CR_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  

以上代码主要是为了对使能外部时钟并等待HSE稳定,当HSE时钟稳定之后,HSEStatus = (uint32_t)0x01;之后执行以下代码

/* Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/* Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    /* HCLK = SYSCLK 设置HPRE[3:0]位,即0xxx: SYSCLK不分频*/RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK 设置PPRE2[2:0]位,即高速APB预分频(APB2)不分频*/RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK 设置PPRE1[2:0]位,即低速APB预分频(APB1)二分频*/RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

之后最重要的配置来了,代码分析在注释中给出:

/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz *//* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz *//*PLL2作为PREDIV1的时钟源,PLL2 8倍频输出,PREDIV2对输入时钟5分频,PREDIV1对输入时钟5分频*/    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);/*这一步需要改,这一步做到的事为将PREDIV2设置为/5;然后将PLL2MUL设置为*8;将PREDIV1SRC设置为PLL2作为PREDIV1的时钟源;将PREDIV1设置为/5,此时到达PLLSCR的时钟为8MHz*//*-----------------以下代码为 HSE_VALUE == 25000000 时使用-----------------*/RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);/*--------------------------------------------------------------------------*/

标记1:以上这一步的配置为:将PREDIV2配置为5分频,PLL2MUL配置为8倍频,PREDIV1SCR的输入源配置来源于PLL2(PLL2CLK),PREDIV1配置为5分频。当外部输入时钟为25MHz时,经过PREDIV2分频之后,输出5MHz,再经过PLL2MUL倍频之后输出40MHz,也就是PLL2CLK=40MHz,之后经过PREDIV分频之后,输入PLLSCR的时钟为8MHz,之后只需经过PLLMUL倍频之后就可以得到72MHz的时钟(PLLMUL倍频在后续代码。)
在这里插入图片描述

/*--------------------------------------------------------------------------*//* Enable PLL2 */RCC->CR |= RCC_CR_PLL2ON;/* Wait till PLL2 is ready */while((RCC->CR & RCC_CR_PLL2RDY) == 0){}/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ /**/RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);/*RCC_CFGR_PLLXTPRE_PREDIV1 :PREDIV1分频因子的低位,不对输入时钟分频(PLLXPRE=0);RCC_CFGR_PLLSRC_PREDIV1 :PREDIV1输出作为PLL输入时钟RCC_CFGR_PLLMULL9:PLLMULL设置为*9*/RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9);

上面代码就是把PLL2CLK时钟使能,刚开始默认是关闭的,之后RCC_CFGR_PLLXTPRE_PREDIV1 参数表示RCC->CFGR寄存器不对PREDIV1分频器进行设置,表示默认使用RCC->CFGR2对PREDIV1分频器的设置,之后PLLSRC选择PREDIV1的输出作为时钟源,之后再将PLLMUL的倍频设置为9倍频,这样就得到了PLLCLK的时钟为72MHz。

/* Enable PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}

后面的这一些就只是使能PLLCLK时钟,然后等待PLLCLK时钟就绪,之后SW选择PLLCLK时钟作为SYSCLK时钟源,再确保PLLCLK已经作为SYSCLK的时钟源。
官方时钟配置代码讲解到这里,回到先前那个话题,如果外部时钟源是8MHz怎么办?如果继续按照官方的代码,回到标记1此时时钟配置明显错误。
以下给出两种配置为8MHz的方法。
方法一:对官方代码修改最少。当外部时钟HSE变为8MHz时,我们只需将PREDIV2设置为2分频,在将PLL2MUL配置为10倍频,此时我们就能得到PLL2CLK为40MHz,如下图所示:
在这里插入图片描述
即将代码:

RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);

修改为:

RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV2 | RCC_CFGR2_PLL2MUL10 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5)

其他不变。
方法二:PREDIV1SCR不选择PLL2CLK作为时钟源输入,直接使用外部时钟HSE作为时钟源输入,之后PREDIV1配置为1分频,此时进入PLLSCR的时钟源为8MHz,之后PLLMUL配置9倍频,照样可以得到PLLCLK==72MHz,如下图所示:
在这里插入图片描述

static void SetSysClockTo72(void)
{__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/*!< SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    /*!< Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON); //使能HSE/*!< Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));if ((RCC->CR & RCC_CR_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  //当外部HSE时钟准备就绪之后HSEStatus == 0x01if (HSEStatus == (uint32_t)0x01){/*!< Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/*!< Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    /*!< HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;  //AHB预分频器/*!< PCLK2 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/*!< PCLK1 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;/*!< PLLCLK = 8MHz * 9 = 72 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));//设置PLLSCR的时钟来源于PREDIV1,PLLMUL配置为9倍频//为什么上面看不到 PREDIV1SCR 和 PREDIV1 的配置,因为 PREDIV1SCR 默认配置来源为HSE时钟, PREDIV1 默认不分频RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9);/*!< Enable PLL */RCC->CR |= RCC_CR_PLLON;/*!< Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/*!< Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /*!< Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}}else{ /*!< If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */   }
}

至此,stm32f105的时钟修改完毕。最后别忘了修改HSE_VALUE的值

#if !defined  HSE_VALUE#ifdef STM32F10X_CL   #define HSE_VALUE    ((uint32_t)8000000) /*!<25000000 Value of the External oscillator in Hz */#else #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* STM32F10X_CL */
#endif /* HSE_VALUE */
————————————————
版权声明:本文为CSDN博主「大文梅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40831436/article/details/114702068

http://www.ppmy.cn/news/789721.html

相关文章

go-micro介绍及环境搭建和使用

go-micro介绍及环境搭建 一、micro框架介绍 1.1、背景 在本课程的前面的内容中&#xff0c;已经学习了微服务之间通信采用的通信协议&#xff0c;如何实现服务的注册和发现&#xff0c;搭建服务管理集群&#xff0c;以及服务与服务之间的RPC通信方式。具体的内容包括&#x…

Tablet vs. eReader: Which Is Better for Ebooks? 平板电脑与电子阅读器:哪个更适合电子书?

eReaders are best if all you want to do is have something as close to a paper book as possible. However, if you need anything more than that, a tablet makes more sense as a general-purpose device that can also read ebooks. 如果您只想拥有尽可能接近纸质书的东…

有状态服务和无状态服务

概念 服务一般分为有状态服务&#xff08;Stateful Service&#xff09;和无状态服务&#xff08;Stateless Service&#xff09;。它们的区别是&#xff0c;当请求发起后&#xff0c;服务在服务端运行时是否需要关联上下文。 有状态服务&#xff0c;服务端需要保存请求的信息&…

C# byte[] 、int 和 string 互转

1、int整形转为byte[]数组&#xff1a;高位存储在前&#xff0c;低位存储在后 public static byte[] IntToByte(this int source, int fromebase 4) {List<byte> buff new List<byte>();for (int i fromebase - 1; i > 0; i--){buff.Add((byte)(source&…

MySQL数据库介绍流程(最新mysql)

版本介绍 第一步&#xff1a;下载MySQL数据库 1、下载地址&#xff1a;http://dev,mysql.com/downloads/windows/installer/8.0html 2、就是直接搜索&#xff1a;mysql官方 msyql官方网站 这里就安装成功 第二步&#xff1a;这么启动和停止mysql 第三步&#xff1a;这么快捷停…

如何共享OneNote笔记本

发起方&#xff1a; 1、打开OneNote&#xff0c;选择准备共享的笔记本&#xff0c;右键选择“共享次笔记本&#xff1b; 2、选择“与人共享”&#xff0c;在右侧输入接收方的电子右键地址&#xff0c;选择可编辑还是可查看&#xff0c;最后点击下方共享按钮&#xff1b; 3、…

微软笔记本

碰到一个问题 有登录密码 跟pin 一般是输入pin 刚重置后提示要输入密码 一时拿不到打算用pe工具填账号进去 没成功 https://www.52pojie.cn/thread-520647-1-1.html进去提示要认证码 跳过 进不到c盘 当前盘是x上面方法就用不了然后进入网络模式 看到用PIN码登录 就进去…

鸭梨笔记本上市!!!超越苹果和微软!!

由MunanSoft科技公司开发的全新一代笔记本电脑&#xff01;&#xff01;鸭梨笔记本上市&#xff01;&#xff01;日前&#xff0c;MunanSoft在联合国全球科技博览会发布了最新一代的鸭梨笔记本&#xff0c; 应其高性能高性价和艺术感十足的设计在博览会上完败微软&#xff0c;苹…