STM32各个系列时钟调高时出现异常案例

最新更新时间:2023-09-22来源: elecfans关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

STM32用户反馈,使用STM32F103内部时钟,把系统时钟配置成64MHz单片机就不跑了,配置成36MHz程序就正常妥妥的,频率稍高点就容易导致死机。他贴出的代码如下:void RCC_Configuration(void)

{

RCC_DeInit();//将外设 RCC寄存器重设为缺省值

RCC_HSICmd(ENABLE);//使能HSI

while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);//等待HSI使能成功

//FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//FLASH_SetLatency(FLASH_Latency_2);

RCC_HCLKConfig(RCC_SYSCLK_Div1);

RCC_PCLK1Config(RCC_HCLK_Div2);

RCC_PCLK2Config(RCC_HCLK_Div1);

//设置 PLL 时钟源及倍频系数

RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);

。。。。。。

结合他的问题描述及他贴出来的代码,大致可以判断很可能是因为他屏蔽了指令预取和flash读取等待延迟的参数配置而导致的。即上面两条红色标注出来的代码。

后来我明确地提醒他这点后,他似乎并没及时反应过来,还折腾了几下才开启了上述配置,问题最终得以解决。

其实,关于这个问题经常有人遇到,尤其是那些基于STM32标准固件库进行开发或自行创建工程的新手更容易碰到这个问题。主要原因是因为他们对上述两行代码的功能不了解,导致有意或无意的将库例程中相关代码屏蔽掉无视掉而不做配置、或者配置不正确。

这里将这个问题再次分享出来,并对那两行代码简单做些解释。希望更多人对此有所知晓,少在这个地方走弯路。

这句 FLASH_PrefetchBufferCmd(); 用来开启或禁用flash指令预取功能。

现有STM32各个系列都是基于ARM cortexM内核的微处理器,它们采用多级流水线的哈佛结构,即一条指令的执行分割为几个阶段,如取指、译码、执行等,使得当前指令的取指操作完成后就可以开始后续指令的取指、译码等操作,程序指令就这样像流水一样执行下去,大大提高了指令的执行效率。

具体到STM32各系列单片机,这个指令预取功能的开启或关闭可以软件配置,一般配置为开启。要注意的是,复位后不同的系列该功能有的默认为开启有的则默认为关闭。比方STM32F1系列的flash指令预取功能就是默认打开的,当然你也可以关闭。其中,明确要求打开的情景就是当那个AHB时钟预分频系数不等于1时。

再比如STM32F4系列,它的指令预取功能在芯片复位后是默认关闭的,你可以自行打开。但明确要求关闭的场景就是芯片的供电电压低于2.1V时。

其实,STM32F4的预取功能与STM32F1不尽一样,STM32F4、STM32F2、STM32L4、STM32F7等系列芯片使用了ST的专利技术ART存储加速器【Adaptive real-time memory accelerator】。该加速器使用指令预取队列和分支跳转缓存技术,从而提高 Flash 程序代码执行速度,使得CPU即使在其最高主频下也能完美实现0 等待执行flash程序指令。

上面大致介绍了指令预取功能,预取主要是为了实现指令读取和执行的高效性。具体细节请参考STM32和ARM cortex内核的相关技术手册。

我们知道CPU的运行速度可调、可以很快,通常使用高速总线访问FLASH接口控制器,FLASH控制器收到来自CPU的取指指令后然后去读取相应地址的指令或数据。Flash控制器自身的读取速度相比CPU的高速请求来说可能会出现滞后,往往需要CPU做相应的延时等待。为了让CPU准确及时读取Flash 数据,我们须根据 CPU 时钟频率以及器件供电情况在Flash存取控制寄存器 (FLASH_ACR)中正确地编程等待周期数(LATENCY),类似上面提到另外一句代码:

FLASH_SetLatency(FLASH_Latency_n);

这里的等待周期数视不同的STM32系列也各有差异,不妨以STM32F4为例:

下面是STM32F4系列部分产品线的LATENCY设置的表格。从表格中可以看出LATENCY参数的设置与CPU的时钟、电源电压都有关系。另外,当电源电压在2.1V以下时要关闭预取。

在设置上面的等待周期参数时,选择合适的就好。不难理解,设置太大了影响CPU性能的充分发挥,太小了容易导致异常。

具体回到开头所提案例,它出现死机问题极可能是因为没有合理配置等待周期参数导致异常,因为它屏蔽了例程中那两句配置代码,即使用其默认功能,对于STM32F1,指令预取功能默认为开启。而STM32F1系列芯片的latency默认值即为0,无等待。这样的话,当他把时钟调高到一定程度时出现死机就不难理解了。

另外,当他反馈时钟调高产生异常时,我还给他提醒了注意检查VDDA的电源情况。我碰到有人遇到因VDDA没接好使得PLL不正常的情况。我们知道,对于STM32芯片,调高其工作时钟,往往借助于锁相环。而PLL的供电来自VDDA,如果PLL没有被正常供电,也是个非常隐蔽的麻烦。曾经有个客户为此折腾好久,才愿沉下心来检查其“坏品”的电源脚,结果发现有个VDDA脚虚焊。一直以芯片低频没问题,频率高了就异常为由怀疑芯片品质问题而耽误时间。

最后给点建议,做STM32开发的话,尤其是新手,如果参照ST的官方例程的话,有些配置在没看懂的情况下不要轻易屏蔽或修改。我碰到多个类似本案随意屏蔽例程中的初始化配置代码或断言代码出现异常,自己又找不到方向的。另外,尽可能使用ST官方的stm32cubeMx图形配置工具做基本的配置,通过它来生成初始化配置文件,这样方便省事很多。当然,即使使用STM32CUBEMX配置也不是万能的。比方:曾经有人使用STM32F0开发产品,用CUBEMX配置初始化文件,刚开始配置时时钟选择得比较低, STM32CubeMx自然根据他选择的时钟做了相关参数配置。后来他自己在用户代码里手动调高了时钟,而不知相应调整跟FLASH读取等待有关的参数,也是发生跟本案同样的情况。


关键字:STM32 编辑:什么鱼 引用地址:STM32各个系列时钟调高时出现异常案例

上一篇:为什么STM32单片机编程时需要使能时钟
下一篇:使用STM32WB设计BLE应用时影响功耗的内容

推荐阅读最新更新时间:2023-12-04 13:38

STM32通过GPRS与服务器建立TCP连接
u16 USART3_CGREG_Cnt; u8 USART3_Task_Cnt; //task_GPRS为GPRS处理任务,每50ms~200ms调用一次 void task_GPRS() { switch(USART3_Task_Cnt) { case 0: // SendUartStr( case0 ,1); if(GprsState.bits.Timeout == true) { GprsState.Flag =0x00000000; { GPIO_InitTyp
[单片机]
STM32基础实验4(按键中断)
按键中断实验,实验2是按键查询 一、实验原理 1、按键使用查询和中断模式的 对于按键使用查询和中断模式,查询模式是自己采用一段代码放在一个循环中,例如main函数中实时查询发现变位就去处理,而中断模式采用硬件方式查询变化状态然后做出相应。两者的区别一个是需要自己编写查询软件代码,一个是初始化时配置好中断模式,然后在中断中直接写你的处理代码即可。 2、实现步骤 ①初始化 IO 口为输入(key.c中!) void KEY_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB
[单片机]
STM32中USART 串口简单使用
  使用查询方式的USART:   设置时钟:   RCC_APB2Periph_AFIO 功能复用IO时钟   RCC_APB2Periph_GPIOA GPIOA时钟   RCC_APB2Periph_USART1 USART1时钟   你可以用   //使能串口1,PA,AFIO总线 RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_USART1 ,ENABLE);   或直接   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL,ENABLE); //全部APB
[单片机]
STM32学习——高级定时器
高级定时器简介 1.输入捕获模式,可用来测频率或脉宽(原理:捕获到信号的跳变沿的时候,把计数器CNT的值锁存到捕获寄存器CCR中,把前后两次捕获到的CCR寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,需要进行额外的处理) 2.输出比较应用,主要应用为PWM输出 配置PWM输出,代码实现 (1)高级定时器TIM1的工作方式配置以及初始化 1.时基结构体TIM_TimeBaseInitTypeDef,配置预分频PSC,计数方式,定时器周期ARR,时钟分频(与死区时间相关),重复计数器(用不上) 2.输出比较结构体TIM_OCInitTypeDef,配置比较输出模式(P
[单片机]
<font color='red'>STM32</font>学习——高级定时器
STM32读写24C02遇到的问题
这几天在弄I2C,读取24C02的数据。我默默的敲完了代码,然后仿真。 代码就下面两行,就是写一个字节,然后读取。 I2C_EE_BufferWrite( &write,100, 1); I2C_EE_BufferRead(&read,100, 1); 然后就是各种不对,经过跟踪发现程序挂在了读上面。 具体的发现读数据的时候,刚发送了起始信号后就死掉了。 百思不得其解。 然后用历程上的测试代码来试又正常。 和正常的程序对比了,也没问题。各种参数完全正确。 昨天搞了一天,总觉得是哪个地方我拼错了或是参数设错了。然鹅一直到晚上也没找到原因。 今天早上一想,是不是这写和读之间要加点延迟啊(24C0
[单片机]
<font color='red'>STM32</font>读写24C02遇到的问题
STM32的GPIO在实际开发设计的使用配置和技巧
一、前言 本篇开始对STM32的GPIO在实际开发设计中的使用配置和技巧进行探讨,可以先去回顾下之前介绍的GPIO的相关理论基础知识包括基本结构,工作模式和寄存器原理。 了解过STM32的GPIO相关的理论知识,这样在应用GPIO开发过程中,能更好的理解GPIO的特点,应用起来会更加的得心应手。 后续将从以下图1中所示的几个方面对GPIO应用设计中的步骤展开介绍。本篇先介绍GPIO的基本API函数定义,配置初始化的流程,以及使用技巧;针对将GPIO的引脚用于外部中断的功能将作为单独的一篇进行详细的讨论介绍。 图1 GPIO应用设计 二、API函数 STM32有多种类型的库,本节所介绍的STM32的GPIO函数接口是ST
[单片机]
<font color='red'>STM32</font>的GPIO在实际开发设计的使用配置和技巧
STM32单片机SPI极性和相位的设置方法
SPI分主设备和从设备,两者通过SPI协议通讯。而设置SPI的模式,是从设备的模式,决定了主设备的模式。所以要先去搞懂从设备的SPI是何种模式,然后再将主设备的SPI的模式,设置和从设备相同的模式,即可正常通讯。对于从设备的SPI是什么模式,有两种:(1)固定的,有SPI从设备硬件决定的SPI从设备,具体是什么模式,相关的datasheet中会有描述,需要自己去datasheet中找到相关的描述,即:关于SPI从设备,在空闲的时候,是高电平还是低电平,即决定了CPOL是0还是1;然后再找到关于设备是在上升沿还是下降沿去采样数据,这样就是,在定了CPOL的值的前提下,对应着可以推算出CPHA是0还是1了。举例1:CC2500-Low
[单片机]
<font color='red'>STM32</font>单片机SPI极性和相位的设置方法
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved