①hsi是高速内部时钟,rc振荡器,频率为8mhz。
②hse是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4mhz~16mhz。
③lsi是低速内部时钟,rc振荡器,频率为40khz。
④lse是低速外部时钟,接频率为32.768khz的石英晶体。
⑤pll为锁相环倍频输出,其时钟输入源可选择为hsi/2、hse或者hse/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72mhz。
用户可通过多个预分频器配置ahb总线、高速apb2总线和低速apb1总线的频率。ahb和apb2域的最大频率是72mhz。apb1域的最大允许频率是36mhz。sdio接口的时钟频率固定为hclk/2。
40khz的lsi供独立看门狗iwdg使用,另外它还可以被选择为实时时钟rtc的时钟源。另外,实时时钟rtc的时钟源还可以选择lse,或者是hse的128分频。rtc的时钟源通过rtcsel[1:0]来选择。
stm32中有一个全速功能的usb模块,其串行接口引擎需要一个频率为48mhz的时钟源。该时钟源只能从pll输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用usb模块时,pll必须使能,并且时钟频率配置为48mhz或72mhz。
另外,stm32还可以选择一个pll输出的2分频、hsi、hse、或者系统时钟sysclk输出到mco脚(pa8)上。系统时钟sysclk,是供stm32中绝大部分部件工作的时钟源,它可选择为pll输出、hsi或者hse,(一般程序中采用pll倍频到72mhz)在选择时钟源前注意要判断目标时钟源是否已经稳定振荡。max=72mhz,它分为2路,1路送给i2s2、i2s3使用的i2s2clk,i2s3clk;另外1路通过ahb分频器分频(1/2/4/8/16/64/128/256/512)分频后送给以下8大模块使用:
① 送给sdio使用的sdioclk时钟。
② 送给fsmc使用的fsmcclk时钟。
③ 送给ahb总线、内核、内存和dma使用的hclk时钟。
④ 通过8分频后送给cortex的系统定时器时钟(systick)。
⑤ 直接送给cortex的空闲运行时钟fclk。
⑥ 送给apb1分频器。apb1分频器可选择1、2、4、8、16分频,其输出一路供apb1外设使用(pclk1,最大频率36mhz),另一路送给定时器(timer2-7)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4、5、6、7使用。
⑦ 送给apb2分频器。apb2分频器可选择1、2、4、8、16分频,其输出一路供apb2外设使用(pclk2,最大频率72mhz),另一路送给定时器(timer1、timer8)1、2倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1和定时器8使用。另外,apb2分频器还有一路输出供adc分频器使用,分频后得到adcclk时钟送给adc模块使用。adc分频器可选择为2、4、6、8分频。
⑧ 2分频后送给sdio ahb接口使用(hclk/2)。
在以上的时钟输出中有很多是带使能控制的,如ahb总线时钟、内核时钟、各种apb1外设、apb2外设等。当需要使用某模块时,必需先使能对应的时钟。需要注意的是定时器的倍频器,当apb的分频为1时,它的倍频值为1,否则它的倍频值就为2。
连接在apb1(低速外设)上的设备有:电源接口、备份接口、can、usb、i2c1、i2c2、uart2、uart3、spi2、窗口看门狗、 timer2、timer3、timer4。注意usb模块虽然需要一个单独的48mhz时钟信号,但它应该不是供usb模块工作的时钟,而只是提供给串行接口引擎(sie)使用的时钟。usb模块工作的时钟应该是由apb1提供的。
连接在apb2(高速外设)上的设备有:gpio_a-e、usart1、adc1、adc2、adc3、tim1、tim8、spi1、afio
使用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;
7、设置pll rcc_pllconfig;
8、打开pll rcc_pllcmd(enable);
9、等待pll工作 while(rcc_getflagstatus(rcc_flag_pllrdy) == reset)
10、设置系统时钟 rcc_sysclkconfig;
11、判断是否pll是系统时钟 while(rcc_getsysclksource() != 0x08)
12、打开要使用的外设时钟 rcc_apb2periphclockcmd()/rcc_apb1periphclockcmd()
下面是stm32软件固件库的程序中对rcc的配置函数(使用外部8mhz晶振)
void rcc_configuration(void)
{
rcc_deinit();
rcc_hseconfig(rcc_hse_on); //rcc_hse_on——hse晶振打开(on)
hsestartupstatus = rcc_waitforhsestartup();
if(hsestartupstatus == success) //success:hse晶振稳定且就绪
{
rcc_hclkconfig(rcc_sysclk_div1); //rcc_sysclk_div1——ahb时钟 = 系统时钟
rcc_pclk2config(rcc_hclk_div1); //rcc_hclk_div1——apb2时钟 = hclk
rcc_pclk1config(rcc_hclk_div2); //rcc_hclk_div2——apb1时钟 = hclk / 2
flash_setlatency(flash_latency_2); //flash_latency_2 2延时周期
flash_prefetchbuffercmd(flash_prefetchbuffer_enable); // 预取指缓存使能
rcc_pllconfig(rcc_pllsource_hse_div1, rcc_pllmul_9);
// pll的输入时钟 = hse时钟频率;rcc_pllmul_9——pll输入时钟x 9
rcc_pllcmd(enable);
while(rcc_getflagstatus(rcc_flag_pllrdy) == reset) ;
rcc_sysclkconfig(rcc_sysclksource_pllclk);
//rcc_sysclksource_pllclk——选择pll作为系统时钟
while(rcc_getsysclksource() != 0x08); //0x08:pll作为系统时钟
}
rcc_apb2periphclockcmd(rcc_apb2periph_gpioa | rcc_apb2periph_gpiob |
rcc_apb2periph_gpioc , enable);
//rcc_apb2periph_gpioa gpioa时钟
//rcc_apb2periph_gpiob gpiob时钟
//rcc_apb2periph_gpioc gpioc时钟
//rcc_apb2periph_gpiod gpiod时钟
}
下面是用mdk仿真gpio的截图: