STM32RBT6時鐘問題總結

這兩天碰到關於CAN總線的問題,當檢查配置與CAN分析儀都沒問題的時候,陷入了迷茫期,之後在程序中找到對於CAN總線時鐘的理解,想到了APB1的時鐘可能有問題,對於在這裏就對時鐘再一次的進行總結。
關於時鐘的文件主要有兩個:1.system_stm32f10x.c ,2.stm32f10x.h

1.首先在啓動文件中我們找到SystemInit()函數

在這裏插入圖片描述
我們可以看到關於時鐘的配置是在main函數之前的,接下來就看system_stm32f10x.c文件內:

void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* 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;

#ifdef STM32F10X_CL
  /* 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;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

然後我們回憶一下在STM32中外設主要用到的時鐘是APB1:

  • 	 RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
    
  •      RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
    
  •      RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
    
  •      RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, 
    
  •      RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2,
    
  •      RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
    
  •      RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
    
  •      RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
    
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB1ENR |= RCC_APB1Periph;
  }
  else
  {
    RCC->APB1ENR &= ~RCC_APB1Periph;
  }
}

以及APB2:

  • 	 RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
    
  •      RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
    
  •      RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
    
  •      RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
    
  •      RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
    
  •      RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
    
  •      RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11     
    
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}

AHB:

  • @arg RCC_AHBPeriph_DMA1
    
  • @arg RCC_AHBPeriph_DMA2
    
  • @arg RCC_AHBPeriph_SRAM
    
  • @arg RCC_AHBPeriph_FLITF
    
  • @arg RCC_AHBPeriph_CRC
    
  • @arg RCC_AHBPeriph_OTG_FS    
    
  • @arg RCC_AHBPeriph_ETH_MAC   
    
  • @arg RCC_AHBPeriph_ETH_MAC_Tx
    
  • @arg RCC_AHBPeriph_ETH_MAC_Rx
    
  • @arg RCC_AHBPeriph_DMA1
    
  • @arg RCC_AHBPeriph_DMA2
    
  • @arg RCC_AHBPeriph_SRAM
    
  • @arg RCC_AHBPeriph_FLITF
    
  • @arg RCC_AHBPeriph_CRC
    
  • @arg RCC_AHBPeriph_FSMC
    
  • @arg RCC_AHBPeriph_SDIO
    
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    RCC->AHBENR |= RCC_AHBPeriph;
  }
  else
  {
    RCC->AHBENR &= ~RCC_AHBPeriph;
  }
}

STM32F103主要就是這兩大時鐘,高速和低速,很明顯我們可以看到CAN1屬於APB1的低速時鐘,但是是多少呢?我們在每換一個板的時候都應該檢查一下。因爲我們有一個不確定的外部時鐘。

2.接下來就看stm32f10x.h文件的了

關於外部時鐘配置的很重要的一個參數是HSE_VALUE了,所以外部時鐘晶振我們選用12M的
在這裏插入圖片描述
接下來我們就可以返回SystemInit()函數看看APB1的配置過程了:
1.找到SetSysClock()函數,跟着進入:SetSysClockTo72()函數。
在這裏插入圖片描述
之後我們就來到了這裏,一個充滿期待的地方"#else"之後我們配置的外部晶振是12M要得到72M的PLL所以我們要給的倍頻係數是6而之前我給的是9所以當時的時鐘是錯的,但是程序還是能跑所以在當時沒檢查出來,所以通過這件事就可以看出,有時候不是問題有多難,而是你的方法有沒有效果,解決問題的能力就是這樣一步一步的成長起來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章