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),另一路送给守时器(Timer)2、3、4倍频器运用。该倍频器能够挑选1或许2倍频,时钟输出供守时器2、3、4运用。
(5)送给APB2分频器。APB2分频器能够挑选1、2、4、8、16分频,其输出一路供APB2外设运用(PCLK2,最大频率72MHz),别的一路送给守时器(Timer)1倍频运用。该倍频器能够挑选1或2倍频,时钟输出供守时器1运用。别的APB2分频器还有一路输出供ADC分频器运用,分频后送给ADC模块运用。ADC分频器可挑选为2、4、6、8分频。
需求留意的是守时器的倍频器,当APB的分频为1时,它的倍频值为1,不然它的倍频值就为2。
连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。留意USB模块尽管需求一个独自的48MHz的时钟信号,可是它应该不是供USB模块作业的时钟,而仅仅供给给串行接口引擎(SIE)运用的时钟。USB模块的作业时钟应该是由APB1供给的。
连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、GPIOx(PA~PE)、第二功用IO口。
2.STM32时钟的初始化
由于我现在所用的开发板现已外接了一个8MHz的晶振,因而将选用HSE时钟,在MDK编译平台中,程序的时钟设置参数流程如下:
(1)将RCC寄存器从头设置为默认值:RCC_DeInit;
(2)翻开外部高速时钟晶振HSE:RCC_HSEConfig(RCC_HSE_ON);
(3)等候外部高速时钟晶振作业:HSEStartUpStatus = RCC_WaitForHSEStartUp();
(4)设置AHB时钟(HCLK):RCC_HCLKConfig;
(5)设置高速AHB时钟(APB2):RCC_PCLK2Config;
(6)设置低速AHB时钟(APB1):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_APB2PerphClockCmd()….
某些函数的详细的运用方法,能够参阅ST公司出书的《STM32F10xxx_Library_Manual》
3.SysTick守时器
NVIC中,捆绑着一个SysTick守时器,它是一个24位的倒数计数守时器,当计到0时,将从RELOAD寄存器中主动重装载守时初值并持续计数,一起内部的COUNTFLAG标志会置位,触发中止(假如中止使能情况下)。只需不把它在SysTick操控及状况寄存器中的使能位铲除,就用不停息。Cortex-M3答应为SysTick供给2个时钟源以供挑选,第一个是内核的“自在运转时钟”FCLK,“自在”表现在它不是来自体系时钟HCLK,因而在体系时钟中止时,FCLK也能持续运转。第2个是一个外部的参阅时钟,可是运用外部时钟时,由于它在内部是经过FCLK来采样的,因而其周期有必要至少是FCLK的两倍(采样定理)。
下面介绍一下STM32中的SysTick,它归于NVIC操控部分,一共有4个寄存器:
STK_CSR,0xE000E010:操控寄存器
STK_LOAD,0xE000E014:重载寄存器
STK_VAL,0xE000E018:当时值寄存器
STK_CALRB,0xE000E01C:校准值寄存器
首先看STK_CSR操控寄存器,有4个bit具有含义:
第0位:ENABLE,SysTick使能位(0:封闭SysTick功用,1:敞开SysTick功用);
第1位:TICKINT,SysTick中止使能位(0:封闭SysTick中止,1:敞开SysTick中止);
第2位:CLKSOURCE,SysTick时钟挑选(0:运用HCLK/8作为时钟源,1:运用HCLK);
第3为:COUNTFLAG,SysTick计数比较标志,假如在前次读取本寄存器后,SysTick现已数到0了,则该位为1,假如读取该位,该位主动清零。
STK_LOAD重载寄存器:
Systick是一个递减的守时器,当守时器递减至0时,重载寄存器中的值就会被重装载,持续开端递减。STK_LOAD重载寄存器是个24位的寄存器最大计数0xFFFFFF。
STK_VAL当时值寄存器:
也是个24位的寄存器,读取时回来当时倒计数的值,写它则使之清零,一起还会铲除在SysTick操控及状况寄存器中的COUNTFLAG标志。
STK_CALRB校准值寄存器:
其间包含着一个TENMS位段,详细信息不详。暂时用不到。
在MDK开发环境中,咱们不必要非得去操作每一个寄存器,能够经过调用ST函数库中的函数来进行相关的操作,其过程如下:
(1)调用SysTick_CounterCmd()失能SysTick计数器
(2)调用SysTick_ITConfig()失能SysTick中止
(3)调用SysTick_CLKSourceConfig()设置SysTick时钟源
(4)调用SysTick_SetReload()设置SysTick重装载值
(5)调用NVIC_SystemHandlerPriorityConfig()设置SysTick守时器中止优先级
(6)调用SysTick_ITConfig()使能SysTick中止
(7)在stm32f10x_it.c中SysTickHandler()下写中止服务函数。
(8)在需求的时分调用SysTick_CounterCmd()敞开SysTick计数器
4.工程完成
依据以上描绘,预备运用开发板上的LED灯做一个小试验,将第一个跑马灯的试验略微改善一下,以1s准确延时的状况来次序点亮LED灯,选用的守时器便是SysTick。
规划思路是先装备好体系的各个参数,然后设置SysTick守时器每1ms就进入一次中止,再界说一个全局变量作为守时长短的参数,然后将从延时函数中得到的参数赋值给这个全局变量,每进入一次中止,这个全局变量就减一次,直到减为0,才跳出延时函数。
1.装备体系时钟
void RCC_cfg()
{
//界说过错状况变量
ErrorStatus HSEStartUpStatus;
//将RCC寄存器从头设置为默认值
RCC_DeInit();
//翻开外部高速时钟晶振
RCC_HSEConfig(RCC_HSE_ON);
//等候外部高速时钟晶振作业
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
//设置AHB时钟(HCLK)为体系时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//设置高速AHB时钟(APB2)为HCLK时钟
RCC_PCLK2Config(RCC_HCLK_Div1);
//设置低速AHB时钟(APB1)为HCLK的2分频
RCC_PCLK1Config(RCC_HCLK_Div2);
//设置FLASH代码延时
FLASH_SetLatency(FLASH_Latency_2);
//使能预取指缓存
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//设置PLL时钟,为HSE的9倍频8MHz * 9 = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
//使能PLL
RCC_PLLCmd(ENABLE);
//等候PLL预备就绪
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//设置PLL为体系时钟源
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//判别PLL是否是体系时钟
while(RCC_GetSYSCLKSource() != 0x08);
}
//翻开PB和PD用于点亮LED灯
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD, ENABLE);
}
其间运用到了NVIC的函数,需求将stm32f10xR.lib加入到工程中。