STM32學(xué)習(xí)筆記之定時(shí)器的配置
實(shí)驗(yàn)?zāi)康模?/p>
讓蜂鳴器每隔一秒響一次;
實(shí)驗(yàn)步驟:
實(shí)驗(yàn)程序:
/************************led.c***********************/
#include"stm32f4xx.h"http://在SYSTEM目錄下可以找到
#include"sys.h"
voidLED_Init(void){
RCC->AHB1ENR|=1<<5;//使能GPIO端口的F時(shí)鐘
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時(shí)鐘
GPIO_Set(GPIOF,PIN8,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);//PF8設(shè)置,下拉
PFout(8)=0;//關(guān)閉蜂鳴器
}
/************************beep.h***********************/
#include"sys.h"
#ifndef_BEEP_H
#define_BEEP_H
voidBeep_Init(void);
#endif
/************************timer.c***********************/
#include"sys.h"
#include"stm32f4xx.h"
/*
本示例的作用就是,
讓蜂鳴器每隔一秒響一次;
*/
/*
關(guān)于定時(shí)器的操作可參考寄存器版的步驟
*/
/*
中斷初始化函數(shù):
主要是關(guān)于寄存器的相關(guān)配置
*/
voidTIM3_Init(void){
/*************************
定時(shí)器中斷的設(shè)置:
*************************/
//使能TIM3時(shí)鐘;
RCC->APB1ENR|=1<<1;
/*預(yù)分頻器*/
TIM3->PSC=8400-1;
/*ARR為自動(dòng)重載寄存器*/
TIM3->ARR=10000-1;
//使能更新中斷
TIM3->DIER|=1;
//使能計(jì)數(shù)器
TIM3->CR1|=1;
/*TIM中斷分組設(shè)置*/
//SCB和NVIC,可參考STM32F3與STM32F4系列CortexM4內(nèi)核編程手冊(cè).pdf
SCB->AIRCR|=0x5<<8;//設(shè)置分組
NVIC->IP[29]|=0;//設(shè)置優(yōu)先級(jí),具體可分析MY_NVIC_Init()函數(shù);
//若不使能,則中斷不會(huì)發(fā)生
NVIC->ISER[0]|=1<<29;//使能中斷;
}
/*每1000ms產(chǎn)生一次中斷*/
voidTIM3_IRQHandler(void){
/*
中斷處理函數(shù):
*/
if(TIM3->SR&0X0001){
PFout(8)=!PFout(8);
}
/*
在中斷里邊最后記得清中斷標(biāo)志:
*/
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);//設(shè)置時(shí)鐘,168Mhz//思考一下為啥要設(shè)置整個(gè)時(shí)鐘(到時(shí)可參考時(shí)鐘那章節(jié));
delay_init(168);//初始化延時(shí)函數(shù)
LED_Init();
Beep_Init();
TIM3_Init();
while(1){
PFout(9)=0;
delay_ms(1000);
PFout(9)=1;
delay_ms(1000);
}
}
實(shí)驗(yàn)分析:
我們主要分析一下定時(shí)器中斷中,關(guān)于寄存器的設(shè)置問題
1. RCC->APB1ENR |= 1 << 1;
這條語句的作用就是:使能TIM3時(shí)鐘;
外設(shè)這么多,我咋知道,我們應(yīng)該在哪條總線上去使能響應(yīng)的外設(shè)?
第一種辦法就是查看RCC寄存器,看其每個(gè)寄存器的每位的解釋;
第二種辦法就是看對(duì)應(yīng)芯片的整個(gè)框圖,如:
由上述視圖,我們可知:TIM3是掛在APB1總線上的,所以我們只需使能APB1ENR寄存器上的響應(yīng)的位就可以達(dá)到我們使能響應(yīng)的外設(shè)的時(shí)鐘的效果;
查看APB1ENR寄存器,我們可知:
所以在這里就寫成了RCC->APB1ENR "= 1 << 1
2. TIM3->PSC = 8400 - 1;
3. TIM3->ARR = 10000 -1 ;
第2條語句和第3條語句的作用就是設(shè)置預(yù)分頻器和自動(dòng)重載寄存器;
但是在設(shè)置這兩個(gè)寄存器之前,我們必須要搞清楚一點(diǎn)就是:計(jì)數(shù)器的時(shí)鐘頻率從哪里來?
查看定時(shí)器的框圖:
注:由上述的定時(shí)器框圖,我們可以得知:CK_INT也就是來自RCC的TIMxCLK
再結(jié)合第5條語句,其作用就是將CEN位寫入1,所以,這樣,我們就將預(yù)分頻器的時(shí)鐘CK_PSC設(shè)置為了內(nèi)部時(shí)鐘CK_INT;
此時(shí),我們需要搞清楚CK_INT的時(shí)鐘多少,在test.c中,我們看到:Stm32_Clock_Init()這個(gè)函數(shù),其函數(shù)體如下:
voidStm32_Clock_Init(u32plln,u32pllm,u32pllp,u32pllq)
{
RCC->CR|=0x00000001;//設(shè)置HISON,開啟內(nèi)部高速RC振蕩
RCC->CFGR=0x00000000;//CFGR清零
RCC->CR&=0xFEF6FFFF;//HSEON,CSSON,PLLON清零
RCC->PLLCFGR=0x24003010;//PLLCFGR恢復(fù)復(fù)位值
RCC->CR&=~(1<<18);//HSEBYP清零,外部晶振不旁路
RCC->CIR=0x00000000;//禁止RCC時(shí)鐘中斷
Sys_Clock_Set(plln,pllm,pllp,pllq);//設(shè)置時(shí)鐘
//配置向量表
#ifdefVECT_TAB_RAM
MY_NVIC_SetVectorTable(1<<29,0x0);
#else
MY_NVIC_SetVectorTable(0,0x0);
#endif
}
接著再追蹤Sys_Clock_Set()函數(shù),進(jìn)到其函數(shù)體內(nèi),我們可以看到:
//時(shí)鐘設(shè)置函數(shù)
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
//Fvco:VCO頻率
//F