咱们近期在预备海洋飞行器竞赛,正好趁此机会学习一下ARM,看到周围许多同学都在运用32,所以我也买了一块STM32F103ZET6,预备好好地学习一下。
STM32的时钟体系恰当的杂乱,包括了5个时钟源,分别是HSI HSE LSI LSE PLL,HSI是高速内部时钟、RC振荡器,频率为8M,HSE是高速外部时钟,即晶振,我的中心板上晶振为8M。LSI为低速内部时钟、RC振荡器,频率40k,LSE为低速外部时钟,接32.768kHz晶振,作为RTC时钟源。PLL为锁相环倍频输出,最大不超越72M。
我在学习守时器时先看的是TIM3,它挂载在APB1分频器上,APB1上面挂载的是低速外设,APB2上挂载高速外设。
在system_stm32f10x.c文件下,有默许界说SYSCLK_FREQ_72MHz,一起在SystemInit()函数下调用了SetSysClock(),依据宏界说将时钟设为72M。
读取SystemCoreClock变量即可取得体系时钟频率。
在默许情况下,体系的各个时钟频率如下:
SYSCLK:72M
AHB:72M
APB1(PCLK1):36M
APB2(PCLK2):72M
PLL:72M
详细的守时器设定如下:
①首要要搞清楚守时器的计数时钟频率,在预分频系数≠1的时分,TIM2~7的时钟频率为APB1的2倍,即72MHz,预分频系数的默许值不是1,但我并未查到该怎么设置该值。
②守时器的设置首要包括守时器的初始化和中止的初始化。
2.1 守时器初始化:
首要界说TIM_TimeBaseInitTypeDef类型的结构体,它包括了如下的内容:
typedef struct{uint16_t TIM_Prescaler; uint16_t TIM_CounterMode; uint16_t TIM_Period; uint16_t TIM_ClockDivision; uint8_t TIM_RepetitionCounter; } TIM_TimeBaseInitTypeDef;
第一项TIM_Prescaler是预分频值,它与TIM_Period(重载周期值)的乘积即为计数的总值。
第二项TIM_CounterMode为计数模式,它的内容如下:
#define TIM_CounterMode_Up ((uint16_t)0x0000)#define TIM_CounterMode_Down ((uint16_t)0x0010)#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020)#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040)#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
后边三项为中心对齐形式,指的是计数到必定的值,产生溢出事情,再向下计数到0。常用的为向上计数形式,即TIM_CounterMode_Up
第四项TIM_ClockDivision为时钟切割,关于时钟切割没有查到太多的描绘,一般设定为TIM_CKD_DIV1,或许直接填入0x0000。
第五项TIM_RepetitionCounter为PWM形式的一些设定,一般的守时器不必设置。
除此之外还要设置中止的类型,一般的守时器为更新中止,即由溢出事情产生的中止,设置的方法为:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE),其间第一项是守时器代号,第二项为类型,这儿设定为更新方法,第三项为使能。
依据上述内容咱们知道,初始化的进程如下:
3
TIM_TimeBaseInitTypeDef TIM_STR;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3挂载在APB1上//咱们预分频系数默许不是1,所以TIM3的时钟为2*APB1=72MTIM_STR.TIM_Period=arr;TIM_STR.TIM_Prescaler=psc;//(arr+1)*(psc+1)/TIM时钟=守时器溢出中止触发周期TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3,&TIM_STR);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
2.2 中止初始化:
中止初始化为操作NVIC(嵌套向量中止控制器)函数。 设置方法如下:
NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;//设定为TIM3中止NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0级NVIC_STR.NVIC_IRQChannelSubPriority=3;//从优先级3级NVIC_STR.NVIC_IRQChannelCmd=ENABLE;//IRQ通道时能NVIC_Init(&NVIC_STR);//中止初始化TIM_Cmd(TIM3,ENABLE);//TIM3守时器使能
2.3 把这些都封装成一个函数,既可作为TIM3的初始化函数。如下:
void TIM3_Init(u16 arr,u16 psc){//守时时刻=(arr+1)*(psc+1)/72 单位为usTIM_TimeBaseInitTypeDef TIM_STR;NVIC_InitTypeDef NVIC_STR;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//初始化守时器TIM_STR.TIM_Period=arr;TIM_STR.TIM_Prescaler=psc;TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3,&TIM_STR);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//初始化中止NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;NVIC_STR.NVIC_IRQChannelSubPriority=3;NVIC_STR.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_STR);//使能守时器TIM_Cmd(TIM3,ENABLE);}
③中止服务函数:
中止函数的姓名,TIM3的为TIM3_IRQHandler
中止服务函数内包括了:判别是否产生中止、中止产生后碑文的内容、铲除标志位三部分。
首要是判别是否产生了更新中止,使用库函数TIM_GetITStatus(P1,P2),它的参数P1为代号,这儿是TIM3,P2为中止类型,这儿为更新中止TIM_IT_Update,当它为1时即产生了更新中止,这儿为了增强可读性,选用一个RESET代表0,当函数返回值不是RESET的时分,即产生了置位(中止)。
铲除标志位选用的是库函数TIM_ClearITPendingBit(P1,P2),参数与判别的函数相同。
详细函数如下:
void TIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//在这儿碑文中止内容}}
④完结调用
只要在main函数里调用TIM3_Init()函数,并填入恰当的参数,即可完成准确的守时中止,例如取得一秒,即72M个数字中止一次,可分解为10000*7200,装备如下:
TIM3_Init(9999,7199);