这两天碰到关于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所以当时的时钟是错的,但是程序还是能跑所以在当时没检查出来,所以通过这件事就可以看出,有时候不是问题有多难,而是你的方法有没有效果,解决问题的能力就是这样一步一步的成长起来的。