實驗目的:
讓蜂鳴器每隔一秒響一次;
實驗步驟:
實驗程序:
/************************led.c***********************/
#include"stm32f4xx.h"http://在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;//關(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ù):
主要是關(guān)于寄存器的相關(guān)配置
*/
voidTIM3_Init(void){
/*************************
定時器中斷的設置:
*************************/
//使能TIM3時鐘;
RCC->APB1ENR|=1<<1;
/*預分頻器*/
TIM3->PSC=8400-1;
/*ARR為自動重載寄存器*/
TIM3->ARR=10000-1;
//使能更新中斷
TIM3->DIER|=1;
//使能計數(shù)器
TIM3->CR1|=1;
/*TIM中斷分組設置*/
//SCB和NVIC,可參考STM32F3與STM32F4系列CortexM4內(nèi)核編程手冊.pdf
SCB->AIRCR|=0x5<<8;//設置分組
NVIC->IP[29]|=0;//設置優(yōu)先級,具體可分析MY_NVIC_Init()函數(shù);
//若不使能,則中斷不會發(fā)生
NVIC->ISER[0]|=1<<29;//使能中斷;
}
/*每1000ms產(chǎn)生一次中斷*/
voidTIM3_IRQHandler(void){
/*
中斷處理函數(shù):
*/
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//思考一下為啥要設置整個時鐘(到時可參考時鐘那章節(jié));
delay_init(168);//初始化延時函數(shù)
LED_Init();
Beep_Init();
TIM3_Init();
while(1){
PFout(9)=0;
delay_ms(1000);
PFout(9)=1;
delay_ms(1000);
}
}
實驗分析:
我們主要分析一下定時器中斷中,關(guān)于寄存器的設置問題
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條語句的作用就是設置預分頻器和自動重載寄存器;
但是在設置這兩個寄存器之前,我們必須要搞清楚一點就是:計數(shù)器的時鐘頻率從哪里來?
查看定時器的框圖:
注:由上述的定時器框圖,我們可以得知:CK_INT也就是來自RCC的TIMxCLK
再結(jié)合第5條語句,其作用就是將CEN位寫入1,所以,這樣,我們就將預分頻器的時鐘CK_PSC設置為了內(nèi)部時鐘CK_INT;
此時,我們需要搞清楚CK_INT的時鐘多少,在test.c中,我們看到:Stm32_Clock_Init()這個函數(shù),其函數(shù)體如下:
voidStm32_Clock_Init(u32plln,u32pllm,u32pllp,u32pllq)
{
RCC->CR|=0x00000001;//設置HISON,開啟內(nèi)部高速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()函數(shù),進到其函數(shù)體內(nèi),我們可以看到:
//時鐘設置函數(shù)
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
//Fvco:VCO頻率
//F