STM32的中断与事件、SysTick时钟滴答器及assert_param()

STM32的中断与事件、SysTick时钟滴答器及assert_param()
STM32的中断与事件、SysTick时钟滴答器及assert_param()

STM32的中断与事件、SysTick时钟滴答器及assert_param()

中断与事件简介:

简单点就是中断一定要有中断服务函数,但是事件却没有对应的函数。但是事件可以触发其他关联操作,比如触发DMA,触发ADC采样等。

事件可以在不需要CPU干预的情况下,执行这些操作。中断则必须要CPU介入。

中断和事件的产生源都可以是一样的,之所以分成2个部分,由于中断是需要CPU参与的,需要软件的中断服务函数才能完成中断后产生的结果; 但是事件,是靠脉冲发生器产生一个脉冲,进而由硬件自动完成这个事件产生的结果,当然相应的联动部件需要先设置好,比如引起DMA操作,AD转换等。

简单举例:外部I/O触发AD转换,来测量外部物品的重量;

如果使用传统的中断通道,需要I/O触发产生外部中断,外部中断服务程序启动AD转换,AD 转换完成中断服务程序提交最后结果;

要是使用事件通道,I/O触发产生事件,然后联动触发AD转换,AD转换完成中断服务程序提交最后结果;

相比之下,后者不要软件参与AD触发,并且响应速度也更块;

要是使用事件触发DMA操作,就完全不用软件参与就可以完成某些联动任务了。可以这样简单的认为,事件机制提供了一个完全有硬件自动完成的触发到产生结果的通道,不要软件的参与,降低了CPU的负荷,节省了中断资源,提高了响应速度(硬件总快于软件),是利用硬件来提升CPU芯片处理事件能力的一个有效方法。

1 对NVIC的理解

CM3支持硬件中断嵌套,分为抢占式优先级和亚优先级,使用规则主要有,抢占优先级高级别的可以打断低级别的,同一级别的抢占优先级同时发生时,亚当优先级高的先发生中断,若是相同,则按硬件排列顺序发生。若是有一个亚优先级正在执行中断,同一级别的其它亚优先级发生时,则先挂起,等此中断执行完再执行!

从库函数中找到优先级分组模式:

#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /* 0 bits for pre-emption priority

4 bits for subpriority */

#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /* 1 bits for pre-emption priority

3 bits for subpriority */

#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /* 2 bits for pre-emption priority

2 bits for subpriority */

#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /* 3 bits for pre-emption priority

1 bits for subpriority */

#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /* 4 bits for pre-emption priority

0 bits for subpriority */

从中可以看出第一组只有一个级别,16个亚优先级,我可以这样理解,若是分配成这个组里,不能发生嵌套中断,同时发生中断时,亚优先级高的先发生,若有中断执行时,必须等中断执行完才能执行下一个中断。最后一组正好相反,有15个级别,若是执行一个中断,可以最多嵌套15个中断执行一个中断。看下面的例子:

NVIC_InitTypeDef NVIC_InitStructure; //定义中断初始化类型结构体变量

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //配置优先级分组1 2个两个抢占优先级8个亚优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //开口外部中断0

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置0号抢占式优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//亚优先级配置为0号

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道

NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //开口外部中断5到9

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//配置1号抢占式优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//亚优先级配置为1号

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道

NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置

NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; //ADC1中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//配置1号抢占式优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//亚优先级配置为1号

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道

NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置

从上面的配置来看,外部中断0的优先级最高,可以打断ADC和外部5到9的中断,也就说可以嵌套发生,当ADC中断和外部5到9中断同时发生时,它们的抢占优先级别相同,亚优先级别也相同,因为ADC1硬件排在更靠前,则先发生ADC中断,若是两者任何一个中断正在执行,则等此中断执行完,再去执行另一个中断。

2 事件与中断

事件:是表示检测到某一动作(电平边沿)触发事件发生了。

中断:有某个事件发生并产生中断,并跳转到对应的中断处理程序中。

事件可以触发中断,也可以不触发

中断有可能被更优先的中断屏蔽,事件不会

事件本质上就是一个触发信号,是用来触发特定的外设模块或核心本身(唤醒).

事件只是一个触发信号(脉冲),而中断则是一个固定的电平信号

通过上图的表示,可以明显看出,蓝色是中断发生,红色是事件发生,从 1 到3两者线路是相同的,然后两者分开,上升沿和下降沿用来选择电平方式,中断和事件屏蔽寄存器起到相应的开关作用,软件中断/事件寄存器只要为1对后面的线路都有作用,挂起请求寄存器主要记录电平变化!

3 SysTick时钟滴答器

刚开始使用SysTick这个滴答时,也没有仔细想它是怎么来的,只是照葫芦画瓢,若是做项目的话,用它来分配时间片最好,设定每个时间片用来干什么,轮询查看,这样才不耽误系统的时间。

3 SysTick仔细探究

首先看STM官方芯片资料,上面真正涉及到得很少,其中在系统时钟树有个简单的说明如下:

手册如下说明:RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。通过这句话,可以看出SysTick时钟的来源,从图上也可以详细的看出SysTick是经过8分频得来的,这样好理解了,我们在手册上再仔细找,很能找到一句话:系统嘀嗒校准值固定为9000,当系统嘀嗒时钟设定为9MHz(HCLK/8的最大值),产生1ms时间基准。简单的说,我们把SysTick设置为9000时,就能产生1ms时间基准,说的明白点就是一个中断信号。计算一下:

系统的晶振是8MHZ,PLL9倍频以后为8MHZ*9=72MHz,然后经过8分频为9MHZ,即给systick分配的时钟9MHz,接下来我们再计算,一个计数周期的时间为1/9000000S, 这样写更容易明白点,我要计时1ms 的话,即1/1000s的时间,(1/1000)/(1/9000000)=9000,可以看出我们要计时1ms的话设置为9000是这样得来的。其实上面的公式自己可以推导一下,设系统的时钟频率为SystemFrequency,我们要给滴答定时器设置的值为SystemFrequency / (1/时间基准)。例如1ms的设置72000000 / (1/0.001S)=9000.通过这里我们可以很容易的分配时间。注意设置的时候不要超过24位的最大值0xffffff.

其中在库中有专门的配置函数如下:

static __INLINE uint32_t SysTick_Config(uint32_t ticks)

{

if (ticks > SYSTICK_MAXCOUNT) return (1); /* Reload value impossible */

SysTick->LOAD = (ticks & SYSTICK_MAXCOUNT) - 1; /* set reload register */

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ SysTick->VAL = (0x00); /* Load the SysTick Counter Value */

SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<

/* Enable SysTick IRQ and SysTick Timer */ return (0); /* Function successful */

} 看这个函数就很好理解,配置好要基准的时间,就等中断发生吧。

void SysTick_Handler(void)

{

}

在中断函数,我们可以划分时间片,不要使CPU空等待.也就是到达你想要的那个时间就执行你想做的动作,主要不超出时间片得时间就行。今晚就先总结到这里,简单的知识写出来容易理解一些,反复来回进度有点慢了。

4 assert_param

我们在学STM32的时候函数assert_param出现的几率非常大,上网搜索一下,网上一般解释断言机制,做为程序开发调试阶段时使用。下面我就谈一下我对这些应用的看法,学习东西抱着知其然也要知其所以然。

断言机制函数assert_param

我们在分析库函数的时候,几乎每一个函数的原型有这个函数assert_param();下面以assert_param(IS_GPIO_ALL_PERIPH(GPIOx));为例说一下我的理解,函数的参数IS_GPIO_ALL_PERIPH(GPIOx),我们可以寻找到原型

#define IS_GPIO_ALL_PERIPH(PERIPH) (((*(uint32_t*)&(PERIPH)) == GPIOA_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOB_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOC_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOD_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOE_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOF_BASE) || \

((*(uint32_t*)&(PERIPH)) == GPIOG_BASE))

这个宏定义的作用就是检查参数PERIPH,判断参数PERIPH是否为GPIOX(A...G)基址中的一个,只要有一个为真则其值为真,否则为假,不用多说,这是C语言中基本的逻辑运算。当然这个库函数也用的很有意思,看:首先对PERIPH进行取址,也就是求地址,&PERIPH,然后对这个地址强制转化为32位的指针,即前面加(uint32_t *),然后通过*进行访问这个地址(指针)中的内容。不多说了,看几遍就能明白。

下面我们再回到assert_param这个函数,这个函数是哪里的呢?在stm32f10x_conf.h寻找到原型如下:#ifdef USE_FULL_ASSERT

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

void assert_failed(uint8_t* file, uint32_t line);

#else

#define assert_param(expr) ((void)0)

#endif

这是一个预编译文件,若是定义了USE_FULL_ASSERT这个文件,则执行后面的文件,我们在程序中一般都没什么定义,即执行后面这个语句((void)0),这个语句不用多想,没有定义USE_FULL_ASSERT就是什么也不执行。说的明白点,对上面的那个语句IS_GPIO_ALL_PERIPH(GPIOx)不执行任何操作。

若是定义了USE_FULL_ASSERT它,我们调用这个函数assert_param时,及对参数IS_GPIO_ALL_PERIPH(GPIOx)的正确性进行检查,通过一个C语言中的双目运算符来判断,若是返回1,执行语句(void)0,跟上面一样,若是返回0,则执行后面的函数assert_failed((uint8_t *)__FILE__, __LINE__),函数的作用在库函数中有解释,用来指示出错的行数和文件。注意:__FILE__, __LINE__是标准库函数中的宏定义!切记

void assert_failed(uint8_t* file, uint32_t line);刚开始没看明白为什么加在这里,仔细一想是在头文件的函数声

明。至于函数实体呢?我们从官方文件的模板中main.c中可以找到。如下:

void assert_failed(u8* file, u32 line)

{ /* User can add his own implementation to report the file name and line number,

ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */

while (1) { }

} 英文注释也说明了怎么应用,通过输入参数来确定位置,最简单的方法就是串口打印了,这个函数的主要思想是在输入参数有问题的时候,但是有编译不出来,它可以帮你检查参数的有效性,好处不必多言,自己领悟就行。

继续说明如下:assert_param是怎样包含进去的呢?我们在stm32f10x_conf.h这个头文件中定义的函数声明还是宏定义,怎么在其它文件中都能应用呢?也很多网上朋友在刚开始学习的时候都遇到编译不过去的问题出现,最后通过在文件中添加USE_STDPERIPH_DRIVER来解决的:

我们可以在整个工程中进行搜索USE_STDPERIPH_DRIVER,通过头文件可以看出,是使用标准外设文件。在stm32f10x.h文件中我们可以搜索到如下情况:

#if !defined USE_STDPERIPH_DRIVER

/**

* @brief Comment the line below if you will not use the peripherals drivers.

In this case, these drivers will not be included and the application code will

be based on direct access to peripherals registers

*/

#define USE_STDPERIPH_DRIVER

#endif

#ifdef USE_STDPERIPH_DRIVER

#include "stm32f10x_conf.h"

#endif

可以很容易看出来,我们不在那里添加,这个头文件中也给我们设置了开关,只要把第一个的注释去掉,就不用在配置中添加USE_STDPERIPH_DRIVER了,在第二个文件中我们可以知道怎样包含这个控制开关文件了,呵呵。我们也明白为什么我们在写程序的时候只要包含stm32f10x.h就能很容易的包含所有的文件文件了吧,我们只要在stm32f10x_conf.h配置一下就能包含所需要的库文件了。

通过以上可以看出,通过头文件的相互包含,来控制外设以及调试文件的调用,这样我们理清思路,理解起来就好多了。当然在学习中可能有些C语言问题还没有理解透彻,多上网搜一下,或者多看书,很快就搞明白的。

stm32:系统时钟

实验4 系统时钟实验 上一章,我们介绍了STM32 内部系统滴答定时器,该滴答定时器产生的延时非常精确。在本章中,我们将自定义RCC系统时钟,通过改变其倍频与分频实现延时时间变化,实现LED灯闪烁效果。通过本章的学习,你将了解 RCC系统时钟的使用。本章分为以下学习目标: 1、了解 STM32 的系统构架。 2、了解 STM32 的时钟构架。 3、了解 RCC 时钟的操作步骤。 1.1 STM32 的系统构架 STM32 的时钟比较复杂,它可以选择多种时钟源,也可以选择不一样的时钟频率,而且在系统总线上面,每条系统的时钟选择都是有差异的。所以想要清楚的了解 STM32 的时钟分配,我们先来了解一下 STM32 的系统构架是什么样的。 从上图我们知道,RCC 时钟输出时钟出来,然后经过 AHB 系统总线,分别

分配给其他外设时钟,而不一样的外设,是先挂在不一样的桥上的。比如: ADC1、ADC2、 SPI1、GPIO 等都是挂在 APB2 上面,而有些是挂在 APB1上面,所以,虽然它们都是从 RCC 获取的时钟,但是它们的频率有时候是不一样的。 1.2 STM32 的时钟树 STM32 单片机上电之后,系统默认是用的时钟是单片机内部的高速晶振时钟,而这个晶振容易受到温度的影响,所以晶振跳动的时候不是有一定的影响,所以一般开发使用的时候都是使用外部晶振,而且单片机刚启动的时候,它的时钟频率是 8MHZ,而 STM32 时钟的最高频率是 72MHZ,所以单片机一般开机之后运行的程序是切换时钟来源,并设置时钟频率。大家可能有点疑惑,在第一章到第三章之中,我们并没有看到单片机开机之后设置时钟来源和时钟频率的。其实在使用库函数的时候,其实在库函数启动文件里面,是帮助我们把时钟频率设置到 72MHZ 了。大家可以打开一个库函数工程,在 system_stm32f10x.c 的第 106行,它定义了一个 SYSCLK_FREQ_72MHz: #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else #define SYSCLK_FREQ_72MHz 72000000 然后在下面的程序中,根据这个 SYSCLK_FREQ_72MHz 定义,它默认设置成 72MHZ。接下来我们来看一下具体的 RCC 时钟树:

STM32复位和时钟控制(RCC)

复位 STM32F10xxx支持三种复位形式,分别为系统复位、电源复位和备份区域复位。 1、系统复位 系统复位将所有寄存器设置成复位值,除了RCC_CSR(控制状态寄存器)中的相关复位标志位,通过查看RCC_CSR寄存器,可以识别复位源。 系统复位可由以下5种方式产生: 1)外部引脚NRST复位(低电平触发); 2)窗口看门狗(WWDG)计数终止 3)独立看门狗(IDOG)计数终止 4)软件复位(SW RESET),通过将中断应用和复位控制寄存器 (Application Interrupt and Reset Control Register )中SYSRESETREQ位置1。具体参考Cortex-M3 programming manual。 5)低功耗管理复位: ①通过进入等待模式(StandBy)产生复位: 通过User Option Bytes中设置nRST_STDBY位使能这种复 位模式。这时,即使执行了进入待机模式的过程,系统将 被复位而不是进入待机模式。 ②通过进入停止模式(STOP)产生复位: 通过User Option Bytes中设置nRST_STOP位使能这种复

位模式。这时,即使执行了进入停止模式的过程,系统将 被复位而不是进入停止模式。 2、电源复位 电源复位设置所有寄存器置初始值,除了备份区域。 电源复位可由以下2种方式产生: 1)上电复位和掉电复位(POR/PDR reset) 2)退出等待(StandBy)模式 这些复位源都作用在NRST引脚上,并且在复位延迟期间保持低电平。 提供给设备的系统复位信号都由NRST引脚输出,对每一个内部/外部复位源,脉冲发生器都将保证一个20us最小复位周期。对于外部复位,当NRST位置低时,将产生复位信号。 3、备份区复位 备份区复位仅仅影响被分区域,有以下两种产生方式: 1)软件复位,设置备份区域控制寄存器RCC_BDCR BDRST= 1; 2)在V DD和V BAT两者掉电的前提下,V DD或V BAT上电。

stm32时钟详细说明

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。其实是四个时钟源,如下图所示(灰蓝色),PLL是由锁相环电路倍频得到PLL时钟。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、 4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。 ⑤、送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。

STM32时钟初始化函数SysInit详解

花了一天的时间,总算是了解了SystemInit()函数实现了哪些功能,初学STM32,,现记录如下(有理解错误的地方还请大侠指出):使用的是3.5的库,用的是STM32F107VC,开发环境RVMDK4.23 我已经定义了STM32F10X_CL,SYSCLK_FREQ_72MHz 函数调用顺序: startup_stm32f10x_cl.s(启动文件)→SystemInit() → SetSysClock () →SetSysClockTo72() 初始化时钟用到的RCC寄存器复位值: RCC_CR = 0x0000 xx83; RCC_CFGR = 0x0000 0000;RCC_CIR = 0x0000 0000; RCC_CFGR2 = 0x0000 0000; SystemInit() 在调用SetSysClock()之前RCC寄存器的值如下(都是一些与运算,或运算,在此就不赘述了): RCC->CR = 0x0000 0083; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;至于这些寄存器都代表着什么意思,详见芯片资料RCC寄存器,该文重点不在此处;SetSysClock()函数如下: static void SetSysClock(void) { #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz//我的定义的是SYSCLK_FREQ_72MHz,所以调用SetSysClockTo72() SetSysClockTo72(); #endif } SetSysClockTo72()函数如下: 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

设置stm32系统各部分时钟

设置stm32系统各部分时钟 函数如下: /******************************************************************** ****** * 函数名: RccInitialisation* 函数描述: 设置系统各部分时钟* 输入参数: 无* 输出结果: 无* 返回值: 无 ******************************************************************** ******/void RccInitialisation(void){/* 定义枚举类型变量HSEStartUpStatus */ErrorStatus HSEStartUpStatus;/* 复位系统时钟设置*/RCC_DeInit();/* 开启HSE*/RCC_HSEConfig(RCC_HSE_ON);/* 等待HSE 起振并稳定*/HSEStartUpStatus = RCC_WaitForHSEStartUp();/* 判断HSE 起是否振成功,是则进入if()内部*/if(HSEStartUpStatus == SUCCESS){/* 选择HCLK(AHB)时钟源为SYSCLK 1 分频*/RCC_HCLKConfig(RCC_SYSCLK_Div1);/* 选择PCLK2 时钟源为HCLK(AHB) 1 分频 */RCC_PCLK2Config(RCC_HCLK_Div1);/* 选择PCLK1 时钟源为HCLK(AHB) 2 分频*/RCC_PCLK1Config(RCC_HCLK_Div2);/* 设置FLASH 延时周期数为2 */FLASH_SetLatency(FLASH_Latency_2);/* 使能FLASH 预取缓存*/FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* 选择锁相环(PLL)时钟源为HSE 1 分频,倍频数为9,则PLL 输出频率为 8MHz * 9 = 72MHz*/RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/* 使能PLL */RCC_PLLCmd(ENABLE);/* 等待PLL 输出稳 定*/while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);/* 选择

stm32如何配置时钟

学习STM32笔记2 如何配置时钟 学习STM32笔记2 如何配置时钟 /************************************************************* 该程序目的是用于测试核心板回来后是否能正常工作。包括 两个按键、两个LED现实。按键为PC4、PC5,LED为PA0\PA1。LED为 低电平时点亮。按键为低电平时触发。 ************************************************************/ #i nclude "stm32f10x_lib.h" void RCC_Configuration(void);//设置系统主时钟 void GPIO_Configuration(void);//设置邋邋IO参数 void NVIC_Configuration(void);//设置中断表地址 void delay(void);//延时函数 int main(void) { #ifdef DEBUG debug(); #endifRCC_Configuration(); NVIC_Configuration(); GPIO_Configuration(); while (1) { delay(); //设置指定的数据端口位 GPIO_SetBits(GPIOA,GPIO_Pin_0); //设置指定的数据端口位 delay(); GPIO_ResetBits(GPIOA,GPIO_Pin_0); //清除指定的数据端口位 GPIO_SetBits(GPIOA,GPIO_Pin_1); delay(); GPIO_ResetBits(GPIOA,GPIO_Pin_1); delay(); /********************************************* 使用setbits 与resetbits 是比较简单,其实还是可以使用 其它函数。例如可以使用GPIO_WriteBit GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET); GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);对于好像流水灯呀这些一个整段IO,可以使用GPIO_Write(GPIOA, 0x1101); *********************************************/

stm32系统时钟配置问题

stm32系统时钟配置问题 系统从上电复位到72mz 配置好之前,提供时钟的是内如高速rc 振荡器提 供8MZ 的频率,这个由下面void SystemInit (void)函数的前面的一部分代码来 完成的和保证的:RCC->CR |= (uint32_t)0x00000001; #ifndef STM32F10X_CLRCC->CFGR &= (uint32_t)0xF8FF0000;#elseRCC- >CFGR &= (uint32_t)0xF0FF0000;#endif RCC->CR &= (uint32_t)0xFEF6FFFF; RCC->CR &= (uint32_t)0xFFFBFFFF; RCC->CFGR &= (uint32_t)0xFF80FFFF; #ifdef STM32F10X_CLRCC->CR &= (uint32_t)0xEBFFFFFF; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)RCC->CIR = 0x009F0000; RCC->CFGR2 = 0x00000000;#elseRCC->CIR = 0x009F0000;#endif#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl();#endif#endif 接着void SystemInit (void)调用SetSysClock();函数,将系统时钟配置到 72m,将AHB,APB1,APB2 等外设之前的时钟都配置好,然后切换到72mz 下 运行。所以在使用哪个外设的时候,只需要使能相应的外设时钟就可以了 tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

Finder自学stm32笔记之电源时钟

电源 STM32的工作电压(VDD)为2.0~3.6V。通过内置的电压调节器提供所需的1.8V电源。当主电源VDD掉电后,通过VBA T脚为实时时钟(RTC)和备份寄存器提供电源。 由上图可知VDDA.VSSA分别是独立给ADC的电源盒电源地。ADC需要准确的精度因此需要独立的电源供电。 使用电池或其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。以便于RTC、后备区域、一些寄存器工作当然也需要外部振荡器提供时钟,所以也为LSE振荡器供电。 stm32中有上电复位掉电复位电路,可以设置通过设置PVDE位设置PVD阀值,当VDD 电压异常的时候就会复位,可以设置中断。 低功耗模式 三种低功耗模式 睡眠模式(Cortex?-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行) 停止模式(所有的时钟都已停止而电压还在供给) :是深睡眠模式基础上结合了外设的时钟控制机制,在停止模式下电压调节器可运行在正常或低功耗模式。此时在1.8V供电区域的的所有时钟都被停止,PLL、HSI和HSE RC振荡器的功能被禁止,SRAM和寄存器内

容被保留下来。在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。 待机模式(1.8V电源关闭):待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。 前面是三者的详细介绍,初一看看不出有什么区别,我当时都看的晕呼呼地,做笔记时候才发现他们真正的不同。现在讲解一下。 睡眠模式只是关掉了CM3的内核,外设都在运行包过内部外部时钟、IO口、中断NVIC 等等。停止模式是进一步的睡眠模式它是关掉了所有的外设时钟,但是仍旧在供电。待机模式是最低功耗的模式,它连时钟供电全部禁止除了备份的寄存器和待机电路维持供电。(有待进一步的深入研究并修正) Stm32降低功耗的三种方法: 1.低功耗模式 2.降低系统时钟 3.关掉外设 如题降低系统时钟通过对预分频寄存器进行编程,可以降低任意一个系统时钟(SYSCLK、HCLK、PCLK1、PCLK2)的速度。从而降低功耗。 但是我有疑问就是:如何在系统运行的情况下切换系统时钟的时钟源?是否可以随时改变预分频系数? RCC_SYSCLKConfig 设置系统时钟(SYSCLK) RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);/* Wait till HSI is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x00) 这个函数只是配置好系统时钟不是随时改变系统时钟的函数。所以有待做实验研究此处 关闭外设:在运行模式下,任何时候都可以通过停止为外设和内存提供时钟(HCLK和PCLKx)来减少功耗。通过设置AHB外设时钟使能寄存器(RCC_AHBENR)、APB2外设时钟使能寄存器 (RCC_APB2ENR)和APB1外设时钟使能寄存器(RCC_APB1ENR)来开关各个外设模块的时钟。

05_STM32F4通用定时器详细讲解

STM32F4系列共有14个定时器,功能很强大。14个定时器分别为: 2个高级定时器:Timer1和Timer8 10个通用定时器:Timer2~timer5 和 timer9~timer14 2个基本定时器: timer6和timer7 本篇欲以通用定时器timer3为例,详细介绍定时器的各个方面,并对其PWM 功能做彻底的探讨。 Timer3是一个16位的定时器,有四个独立通道,分别对应着PA6 PA7 PB0 PB1 主要功能是:1输入捕获——测量脉冲长度。 2 输出波形——PWM 输出和单脉冲输出。 Timer3有4个时钟源: 1:内部时钟(CK_INT ),来自RCC 的TIMxCLK 2:外部时钟模式1:外部输入TI1FP1与TI2FP2 3:外部时钟模式2:外部触发输入TIMx_ETR ,仅适用于TIM2、TIM3、TIM4,TIM3,对应 着PD2引脚 4:内部触发输入:一个定时器触发另一个定时器。 时钟源可以通过TIMx_SMCR 相关位进行设置。这里我们使用内部时钟。 定时器挂在高速外设时钟APB1或低速外设时钟APB2上,时钟不超过内部高速时钟HCLK ,故当APBx_Prescaler 不为1时,定时器时钟为其2倍,当为1时,为了不超过HCLK ,定时器时钟等于HCLK 。 例如:我们一般配置系统时钟SYSCLK 为168MHz ,内部高速时钟 AHB=168Mhz ,APB1欲分频为4,(因为APB1最高时钟为42Mhz ),那么挂在APB1总线上的timer3时钟为84Mhz 。 《STM32F4xx 中文参考手册》的424~443页列出与通用定时器相关的寄存器一共20个, 以下列出与Timer3相关的寄存器及重要寄存器的简单介绍。 1 TIM3 控制寄存器 1 (TIM3_CR1) 作用:1使能自动重载TIM3_ARR 2定时器的计数器递增或递减计数。 3 事件更新。 4 计数器使能 2 TIM 3 控制寄存器 2 (TIM3_CR2) 3 TIM3 从模式控制寄存器 (TIM3_SMCR) 4 TIM3 DMA/中断使能寄存器 (TIM3_DIER) SYSCLK(最高 AHB_Prescaler APBx_Prescaler

STM32学习笔记(3):系统时钟和SysTick定时器

STM32学习笔记(3):系统时钟和SysTick定时器 1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但 是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为 48MHz的时钟源。该时钟源只能从PLL端获取,可以选择为1.5分频或者1分频,也就是,当需使用到USB模块时,PLL必须使能,并且时钟配置为48MHz 或72MHz。 另外STM32还可以选择一个时钟信号输出到MCO脚(PA.8)上,可以选择为PLL输出的2分频、HSI、HSE或者系统时钟。 系统时钟SYSCLK,它是提供STM32中绝大部分部件工作的时钟源。系统时钟可以选择为PLL输出、HSI、HSE。系系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各个模块使用,AHB分频器可以选择1、2、4、8、16、64、128、256、512分频,其分频器输出的时钟送给5大模块使用: (1)送给AHB总线、内核、内存和DMA使用的HCLK时钟; (2)通过8分频后送给Cortex的系统定时器时钟; (3)直接送给Cortex的空闲运行时钟FCLK; (4)送给APB1分频器。APB1分频器可以选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一

STM32时钟系统与软件配置

STM32时钟系统与软件配置 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法 如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理: 1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。 2)对于少于100脚的产品,有2种接法: 2.1)OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。 2.2)分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面2.1)节省2个外部电阻。 使用HSE时钟,程序设置时钟参数流程: 1、将RCC寄存器重新设置为默认值RCC_DeInit; 2、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON); 3、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp(); 4、设置AHB时钟RCC_HCLKConfig; 5、设置高速AHB时钟RCC_PCLK2Config; 6、设置低速速AHB时钟RCC_PCLK1Config;

STM32定时时间的计算

STM32 定时器定时时间的计算 假设系统时钟是72Mhz,TIM1 是由PCLK2 (72MHz)得到,TIM2-7是由 PCLK1 得到关键是设定时钟预分频数,自动重装载寄存器周期的值/*每1秒发生一次更新事件(进入中断服务程序)。RCC_Configuration()的SystemInit()的 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2表明TIM3CLK为72MHz。因此,每次进入中断服务程序间隔时间为: ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒。定时器的基本设置如下: 1、TIM_TimeBaseStructure.TIM_Prescaler = 7199;//时钟预分频数例如:时钟频率=72/(时钟预分频+1)。 2、TIM_TimeBaseStructure.TIM_Period = 9999; // 自动重装载寄存器周期的值(定时时间)累计 0xFFFF个频率后产生个更新或者中断(也是说定时时间到)。 3、TIM_TimeBaseStructure.TIM_CounterMode=TIM1_CounterMode_Up; //定时器模式向上计数。 4、 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时间分割值。 5、 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//初始化定时器2。 6、 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //打开中断溢出中断。 7、 TIM_Cmd(TIM2, ENABLE);//打开定时器或者: TIM_TimeBaseStructure.TIM_Prescaler = 35999;//分频35999,72M/ (35999+1)/2=1Hz 1秒中断溢出一次。 8、 TIM_TimeBaseStructure.TIM_Period = 2000; //计数值2000 ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+35999)/72M)*(1+2000)=1秒。 9、注意使用不同定时器时,要注意对应的时钟频率。例如TIM2对应的是APB1,而TIM1对应的是APB2 通用定时器实现简单定时功能 以TIME3为例作为说明,简单定时器的配置如下: void TIM3_Config(void) { TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; TIM_DeInit(TIM3); //复位TIM2定时器 /* TIM2 clock enable [TIM2定时器允许]*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* TIM2 configuration */ TIM_TimeBaseStructure.TIM_Period = 49; // 0.05s定时 TIM_TimeBaseStructure.TIM_Prescaler = 35999; // 分频36000 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数方向向上计数 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* Clear TIM2 update pending flag[清除TIM2溢出中断标志] */

STM32滴答时钟

关于STM32 滴答时钟 相信不论是初学者还是高手,都会被STM32的滴答时钟所吸引。STM32有很多计数器,也有很多计数器中断。当别人还在用计数器做定时扫描的时候,我们就默默的开始了滴答时钟做扫描了。让他们去任意的浪费资源吧,我们节约资源,把计数器发挥更大的作用。 Systick定时器属于cortex内核部件,在芯片介绍的datasheet中没有提到过,可以参考 《CortexM3权威指南》或《STM32xxx-Cortex编程手册》。 首先来看Systick的时钟来源,如图一。可以看出在STM32中Systick以HCLK(AHB 时钟)或HCLK/8作为运行时钟。 图1 另外要注意Systick是一个24位的定时器,即一次最多可以计数224个时钟脉冲,这个脉冲计数值被保存到当前计数值寄存器STK_VAL中,这个计数器只能向下计数,每接收到一个时钟脉冲STK_VAL的值就向下减1,直至0,当STK_VAL的值被减至0时,由硬件自动把重载寄存器STK_LOAD中保存的数据加载到STK_VAL,意思就是它会自动重装。当STK_VAL 的值被倒计至0时,触发中断,就可以在中断服务函数中处理定时事件了。 要让Systick正常工作,必须要对Systick进行配置。它的配置很简单,只有三个控制位和一个标志位,都位于寄存器STK_CRL中,见图二。

图二 ENABLE: 为Systick timer的使能位,此位为1的时候开始计数,为0则关闭Systick timer。 TICKINT: 为中断触发使能位,此位为1的时候并且STK_VAL倒计至0的时候会触发Systick 中断,此位为0的时候不触发中断。 CLKSOURCE: 为Systick的时钟选择位,此位为1的时候Systick的时钟为AHB时钟,此位为0 的时候Systick的时钟为AHB/8(AHB的8分频)。 COUNTFLAG: 为Systick的标志位,当STK_VAL倒计至0,此标志位会被置1。 现在我们不会再为滴答时钟而感到迷惑了吧! 下面将详细描述如何去设置计数器,我们在很多地方看到这样一个函数: SysTick_Config(SystemCoreClock / 1000) 配置为1ms中断一次 SysTick_Config(SystemCoreClock / 100000) 配置为10us中断一次 SysTick_Config(SystemCoreClock / 1000000) 配置为10us中断一次 我们将细说一下,SystemCoreClock/100000 为什么是10us 我们从图1时钟数可以看出Systick的时钟和AHB有关,从图2中了解到滴答时钟可设置,结合两处就能看明白。若不去设置,系统默认为AHB时钟,即72MHz。 系统文件中可查找出以下描述: /************************************************************************** ***** * Clock Definitions *************************************************************************** ****/ #ifdef SYSCLK_FREQ_HSE uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */ #elif defined SYSCLK_FREQ_24MHz uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */ #elif defined SYSCLK_FREQ_36MHz uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System

stm32学习之系统时钟

stm32学习之系统时钟 STM32入门学习心得 — 系统时钟 STM32的时钟与单片机相比要复杂的多,它能够对每一个外设以及IO口进行时钟的设置,这是单片机是无法和它比拟的,所以正确的理解和灵活的运用stm32的时 钟是很重要的。 STM32有3个不同的时钟源可以用于驱动系统时钟(SYSCLK),分别为: HSI振荡器时钟(内部高速时钟)。 HSE振荡器时钟(外部高速时钟)。 PLL时钟。 STM32还有两个二级时钟用来驱动独立的看门狗和选择性的驱动RTC。分别为:32KHZ低速内部RC振荡器(LSI RC)用来驱动独立的开门狗和选择性的驱动用于从停止/ 待机模式自动唤醒的RTC。 32.768kHz低速外部晶体振荡器(LSE 晶体振荡器)用来选择性的驱动实时时钟。 注:每个时钟源在使用时都可以独立的打开/关掉,以节省功耗。 在这里我们可以通过框图来直观的理解STM32的系统时钟。系统时钟框图如图1所示。 图一系统框图

通过图一不妨来详细分析下系统各个部分的时钟。 HSI时钟 HSI时钟通过一个8MHz的内部RC振荡器产生,并且可以被直接用作系统时钟,或者经过2倍频后作为PLL的输出作为SYSCLKS时钟。在系统复位时,HSI振荡器被选择默认的系统SYSCLKS时钟。内部时钟的缺点是频率的精确度没有外部晶体振荡器的高。 程序实现(所有程序都是基于固件库): 直接作为SYSCLKS时钟:RCC_DeInit();系统默认 经过PLL输出作为SYSCLKS时钟: RCC_DeInit(); SystemInit (); 可以在固件库中的stm32f10x_rcc.c文件中通过开放宏定义来选择系统时 钟经过倍频后的频率,固件库默认为72MHZ。如图2所示: 如图2所示 HSE时钟 高速外部时钟信号可以通过2个可能的时钟源产生。分别为: HSE 外部晶体/陶瓷共振器。 HSE 外部时钟。 外部时钟源 在该种模式下,必须提高外部时钟源,外部时钟源可以达到25MHz,用户可以通过设置时钟控制寄存器(RCC_CR)中的HSEBYP和HSEON 位选择该模式。占空必50%的外部时钟信号(方波,正弦波,三角波)必须用来驱动OSC_IN引脚,同时OSC_OUT引脚置于高 阻态。 外部晶体振荡器/陶瓷共振器(HSE晶体) 4~16MHz的外部振荡器具有能够在主时钟上产生一个非常精确地速率的优 点。 时钟控制寄存器(RCC_CR)中的HSERDY标志指示了高速外部振荡器是否是稳定的,在启动时,时钟直到硬件设置了该标志位才释放,如果在时钟中断寄存器(RCC_CR)中打开了, 就会产生一个中断。 HSE晶体振荡器可以通过时钟控制寄存器(RCC_CR)中的HSEON位来打开或 禁止。 程序实现(所有程序都是基于固件库): 1.直接作为SYSCLKS时钟: RCC_DeInit(); /*************************外部时钟设置 *****************************/

stm32时钟树分析

void RCC_Configuration(void) { /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON);

/* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* PLLCLK = 8MHz * 9 = 72 MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08) { } } }

关于STM32开发板晶振相关的问题汇总

关于STM32开发板晶振相关的问题汇总 1自己做了个STM32的板子,,但是手里没有8M的晶振,所以就用了,12M的,,但是不正常,上电之后PA15和PA14接的是两个led,PA15接的led常亮,PA14接的的led 不亮,,而且芯片下载程序又能下载,应该不是芯片坏的问题吧,,而且不管我些什么程序进去,两个脚的状态都不变,,我怀疑是电路有问题,,可是我仔细检查了电路和板子,都没问题,,JTAG正常使用。我用的是12M的晶振,这会有影响吗?感觉不管下什么程序进去感觉芯片好像没有运行。 答:如果使用12M的晶振,那么要修改启动文档中的关于RCC的语句。 因为如果你使用库文件的话,ST的库,默认外部晶振是8M,所以如果你不修改RCC部分 的语句,会造成CPU不启动,或者启动不成功。 现象是,在MDK环境下,能够通过JTAG识别到芯片,但是无法下载或者debug。 会提示can not attach CPU。 2、突然想到这个问题,外部无源晶振选择大小的区别是什么? 对STM32芯片它都要先分频,再倍频。 我在想,假设,如果它分频都要降到2M,再倍频上去 那我直接2M的晶振1分频再倍频,跟24M先12分频再倍频他们的区别是什么?还是说本身就是任意的,根据自己需要选择? 答:方便各种应用场景。 3、自己做的STM32F103RBT6板子,外接8M晶振,现在程序下载正常,运行正常,在程 序初始化时用到Stm32_Clock_lnit(9)这条语句,我想问下是不是外部晶振如果没起振在执行这条语句时会停止?也就是说我的程序下载和运行都正常说明外部晶振肯定起振了,而且已经倍频到72M 了。 答:默认是用内部8M RC震荡的,你切换为PLL之后,才是使用8M倍频的,如果你注释 掉Stm32_Clock_Init(9),那么代码也会跑,但是是用内部8M RC震荡。 4、外部晶振换成了25MHz,但是想方便的移植以前8MHz板子上程序,应该怎么修改系统时钟?看了system_stm32f10x.c系统时钟设置,但是不知道怎么修改!求指点谢谢下面参数是system_stm32f10x.c系统时钟设置 //默认SYSCLK_FREQ_72MHz 可在system_stm32f10x.c 改变设置 //默认HCLK = SYSCLK; RCC->CFGR |= (ui nt32_t)RCC_CFGR_HPRE_DIV1; 〃默认PCLK2 = HCLK ; RCC->CFGR |= (ui nt32_t)RCC_CFGR_PPRE2_DIV1; 〃默认PCLK1 = HCLK ; RCC->CFGR |= (ui nt32_t)RCC_CFGR_PPRE1_DIV2; 〃默认PLL as system clock source; RCC_CFGR_SW_PLL; 答:25M不用想了,必须是25的整数倍才行。 原子哥要是把它设置成75MHz 具体怎么修改哪些配置参数? 25*3=75 了 设置倍频数为3. 但是库函数这个不懂,寄存器的就很简单 5、S TM32的RTC不能用,想确定是否硬件问题。但不知道测量的是哪2个引脚。希望知道的高手指教一下 答:1,去掉RTC晶振的电容 2,换晶振.

相关文档
最新文档