小言_互联网的博客

STM32时钟和中断

251人阅读  评论(0)

一、STM32F427IIH6基本信息

芯片官网信息戳我

二、STM32F427IIH6外设时钟

1、时钟树

时钟树的讲解可以参考野火或者原子的书籍,下图展示了STM32F427IIH6的时钟的分频倍频关系。正确理解时钟树有助于我们从一个整体的角度把握芯片的工作时钟,对代码的编写是十分有用的。

对于 SYSCLK、 HCLK(AHB总线时钟)、 PCLK2(APB2总线时钟)、 PCLK1(APB1总线时钟) 这四个时钟的配置一般是: HCLK=SYSCLK=PLLCLK = 180M,PCLK2=HCLK/2 = 90M, PCLK1=HCLK/4 = 45M。这个时钟配置也是库函数的标准配置,我们用的最多的就是这。

大疆A板使用HSE振荡器时钟(12MHz)来驱动系统时钟,在下图中,

M:PLL时钟分频因子,6分频
N:VOC倍频因子, 180倍频
P:PLLCLK分频因子,2分频
Q和R分频因子这里不讨论,详细情况参考其他文档

通过合理的分频倍频就可以得到180MHz的系统时钟。

2、外设时钟

总线时钟决定了外设时钟,根据上图的总线时钟,可以得到挂载在总线上各个外设的时钟,总结如下表所示:

3、内核外设

内核里也有外设,如MPU(Memory protection unit )、NVIC(Nested vectored interrupt controller )、SCB(System control block )、STK(SysTick timer )、FPU(Floating point unit )。详细说明参考《STM32F4xx-Cortex_-M4内核参考手册》,找不到的可以在评论区留言索要。

常用的SysTick—系统定时器是属于 CM4 内核中的一个外设,可以通过寄存器配置选择时钟源(AHB或AHB/8)。

(图片来源于野火参考书籍)

三、中断相关理解

我认为STM32的核心内容就是定时器和中断,而要把STM32玩得好,还是需要扎实的C语言功底。(我就比较菜了)

初学中断时,不是能很快地理解中断的概念及如何使用中断,下面是我认为理解好中断需要明白的几个关键概念。

中断挂起
如果一个中断发生了,却无法立即处理(比如处理器正在处理更高优先级的中断),这个中断请求将会被挂起。挂起状态保存在一个寄存器中,如果处理器的当前优先级还没有降低到可以处理挂起的请求,并且没有手动清除挂起状态,该状态将会一直保持合法。

清除挂起
可以通过操作外设相关寄存器位达到清除中断挂起的目的,在库函数中可以调用XXX_ClearITPendingBit();来实现清除中断挂起。

中断标志
当进入中断后,中断标志位会自动被置1,代表着"正在执行中断服务函数中"。当我们结束终端服务函数之前,一定要在函数中清除中断标志位。我们可以这样理解:中断标志位是满足中断条件的象征,当我们配置好中断发生的条件,一旦遇到中断标志位有效,就说明该执行中断服务函数了。如果我们不手动的清除中断标志位,那么系统会默认中断条件一直满足那就会一直执行中断服务函数跳不出来了。

那么清除中断挂起位和清除中断标志位有什么区别呢?
一个意思,中断挂起位就是中断标志位

以定时器为例,从库函数中截取
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
两个函数对比:


/**
  * @brief  Clears the TIMx's pending flags.
  * @param  TIMx: where x can be 1 to 14 to select the TIM peripheral.
  * @param  TIM_FLAG: specifies the flag bit to clear.
  *          This parameter can be any combination of the following values:
  *            @arg TIM_FLAG_Update: TIM update Flag
  *            @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag
  *            @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag
  *            @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag
  *            @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag
  *            @arg TIM_FLAG_COM: TIM Commutation Flag
  *            @arg TIM_FLAG_Trigger: TIM Trigger Flag
  *            @arg TIM_FLAG_Break: TIM Break Flag
  *            @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 over capture Flag
  *            @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 over capture Flag
  *            @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 over capture Flag
  *            @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 over capture Flag
  *
  * @note   TIM6 and TIM7 can have only one update flag. 
  * @note   TIM_FLAG_COM and TIM_FLAG_Break are used only with TIM1 and TIM8.
  *    
  * @retval None
  */
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{
     
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
   
  /* Clear the flags */
  TIMx->SR = (uint16_t)~TIM_FLAG;
}
/**
  * @brief  Clears the TIMx's interrupt pending bits.
  * @param  TIMx: where x can be 1 to 14 to select the TIM peripheral.
  * @param  TIM_IT: specifies the pending bit to clear.
  *          This parameter can be any combination of the following values:
  *            @arg TIM_IT_Update: TIM1 update Interrupt source
  *            @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  *            @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  *            @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  *            @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  *            @arg TIM_IT_COM: TIM Commutation Interrupt source
  *            @arg TIM_IT_Trigger: TIM Trigger Interrupt source
  *            @arg TIM_IT_Break: TIM Break Interrupt source
  *
  * @note   TIM6 and TIM7 can generate only an update interrupt.
  * @note   TIM_IT_COM and TIM_IT_Break are used only with TIM1 and TIM8.
  *      
  * @retval None
  */
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{
   
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));

  /* Clear the IT pending Bit */
  TIMx->SR = (uint16_t)~TIM_IT;
}

通过观察不难发现,两个函数实现的功能是一模一样的,不同的是TIM_ClearFlag的第二个参数的可选项多了一些,但实际上都是对SR寄存器的某个位进行取反操作。

可以这么理解,在定时器SR寄存器并不是所有位都用来存放中断标志位(事实的确如此),TIM_ClearFlag();的使命是用来清除SR寄存器的任何一位,TIM_ClearITPendingBit();则是专门用于清除中断标志位。

其他外设可自行分析。若文章有用,不要白嫖!


转载:https://blog.csdn.net/qq_38972634/article/details/117071704
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场