STM32学习笔记之定时器的配置
扫描二维码
随时随地手机看文章
实验目的:
让蜂鸣器每隔一秒响一次;
实验步骤:
实验程序:
/************************led.c***********************/
#include"stm32f4xx.h"//在SYSTEM目录下可以找到
#include"sys.h"
voidLED_Init(void){
RCC->AHB1ENR|=1<<5;//使能GPIO端口的F时钟
GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_25M,GPIO_PUPD_PU);
PFout(9)=1;
PFout(10)=1;
}
/************************led.h***********************/
#ifndef_LED_H
#define_LED_H
voidLED_Init(void);
#endif
/************************beep.c***********************/
#include"sys.h"
#include"beep.h"
voidBeep_Init(void){
RCC->AHB1ENR|=1<<5;//使能PORTE时钟
GPIO_Set(GPIOF,PIN8,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);//PF8设置,下拉
PFout(8)=0;//关闭蜂鸣器
}
/************************beep.h***********************/
#include"sys.h"
#ifndef_BEEP_H
#define_BEEP_H
voidBeep_Init(void);
#endif
/************************timer.c***********************/
#include"sys.h"
#include"stm32f4xx.h"
/*
本示例的作用就是,
让蜂鸣器每隔一秒响一次;
*/
/*
关于定时器的操作可参考寄存器版的步骤
*/
/*
中断初始化函数:
主要是关于寄存器的相关配置
*/
voidTIM3_Init(void){
/*************************
定时器中断的设置:
*************************/
//使能TIM3时钟;
RCC->APB1ENR|=1<<1;
/*预分频器*/
TIM3->PSC=8400-1;
/*ARR为自动重载寄存器*/
TIM3->ARR=10000-1;
//使能更新中断
TIM3->DIER|=1;
//使能计数器
TIM3->CR1|=1;
/*TIM中断分组设置*/
//SCB和NVIC,可参考STM32F3与STM32F4系列CortexM4内核编程手册.pdf
SCB->AIRCR|=0x5<<8;//设置分组
NVIC->IP[29]|=0;//设置优先级,具体可分析MY_NVIC_Init()函数;
//若不使能,则中断不会发生
NVIC->ISER[0]|=1<<29;//使能中断;
}
/*每1000ms产生一次中断*/
voidTIM3_IRQHandler(void){
/*
中断处理函数:
*/
if(TIM3->SR&0X0001){
PFout(8)=!PFout(8);
}
/*
在中断里边最后记得清中断标志:
*/
TIM3->SR&=~(1<<0);
}
/*************************timer.h**********************/
#ifndef_TIMER_H
#define_TIMER_H
voidTIM3_Init(void);
#endif
/*************************test.c**********************/
#include"sys.h"
#include"delay.h"
#include"beep.h"
#include"timer.h"
#include"led.h"
intmain(void){
Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz//思考一下为啥要设置整个时钟(到时可参考时钟那章节);
delay_init(168);//初始化延时函数
LED_Init();
Beep_Init();
TIM3_Init();
while(1){
PFout(9)=0;
delay_ms(1000);
PFout(9)=1;
delay_ms(1000);
}
}
实验分析:
我们主要分析一下定时器中断中,关于寄存器的设置问题
1. RCC->APB1ENR |= 1 << 1;
这条语句的作用就是:使能TIM3时钟;
外设这么多,我咋知道,我们应该在哪条总线上去使能响应的外设?
第一种办法就是查看RCC寄存器,看其每个寄存器的每位的解释;
第二种办法就是看对应芯片的整个框图,如:
由上述视图,我们可知:TIM3是挂在APB1总线上的,所以我们只需使能APB1ENR寄存器上的响应的位就可以达到我们使能响应的外设的时钟的效果;
查看APB1ENR寄存器,我们可知:
所以在这里就写成了RCC->APB1ENR "= 1 << 1
2. TIM3->PSC = 8400 - 1;
3. TIM3->ARR = 10000 -1 ;
第2条语句和第3条语句的作用就是设置预分频器和自动重载寄存器;
但是在设置这两个寄存器之前,我们必须要搞清楚一点就是:计数器的时钟频率从哪里来?
查看定时器的框图:
注:由上述的定时器框图,我们可以得知:CK_INT也就是来自RCC的TIMxCLK
再结合第5条语句,其作用就是将CEN位写入1,所以,这样,我们就将预分频器的时钟CK_PSC设置为了内部时钟CK_INT;
此时,我们需要搞清楚CK_INT的时钟多少,在test.c中,我们看到:Stm32_Clock_Init()这个函数,其函数体如下:
voidStm32_Clock_Init(u32plln,u32pllm,u32pllp,u32pllq)
{
RCC->CR|=0x00000001;//设置HISON,开启内部高速RC振荡
RCC->CFGR=0x00000000;//CFGR清零
RCC->CR&=0xFEF6FFFF;//HSEON,CSSON,PLLON清零
RCC->PLLCFGR=0x24003010;//PLLCFGR恢复复位值
RCC->CR&=~(1<<18);//HSEBYP清零,外部晶振不旁路
RCC->CIR=0x00000000;//禁止RCC时钟中断
Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟
//配置向量表
#ifdefVECT_TAB_RAM
MY_NVIC_SetVectorTable(1<<29,0x0);
#else
MY_NVIC_SetVectorTable(0,0x0);
#endif
}
接着再追踪Sys_Clock_Set()函数,进到其函数体内,我们可以看到:
//时钟设置函数
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
//Fvco:VCO频率
//F