一.實(shí)驗(yàn)?zāi)康?/p>
了解STM32中定時(shí)器的原理。
掌握在STM32如何實(shí)現(xiàn)精確定時(shí)。
二.實(shí)驗(yàn)要求
了解STM32中定時(shí)器的原理。
掌握在STM32如何實(shí)現(xiàn)精確定時(shí)。
學(xué)習(xí)STM32通用定時(shí)器的編程方式,實(shí)現(xiàn)LED每秒閃爍一次。
三.實(shí)驗(yàn)軟硬件
PC機(jī)一臺(tái)
WINDOWS操作系統(tǒng)
ARM集成開發(fā)環(huán)境
WSN實(shí)驗(yàn)箱
四.實(shí)驗(yàn)步驟
1.定時(shí)器簡介
STM32總共有8個(gè)定時(shí)器,TIM1和TIM8是16位的高級(jí)定時(shí)器,TIM2、TIM3、TIM4、TIM5是通用定時(shí)器。本實(shí)驗(yàn)中使用通用定時(shí)器TIM2,來實(shí)現(xiàn)精確定時(shí)。
通用定時(shí)器是一個(gè)通過可編程預(yù)分頻器驅(qū)動(dòng)的16 位自動(dòng)裝載計(jì)數(shù)器構(gòu)成。這里為了體現(xiàn)其精確定時(shí),用LED燈進(jìn)行觀察實(shí)驗(yàn)現(xiàn)象。如果有條件的實(shí)驗(yàn)室,可以配置示波器來觀察信號(hào)情況。(特別是在做脈沖實(shí)驗(yàn)進(jìn)行波形輸出時(shí))。使用定時(shí)器預(yù)分頻器和RCC 時(shí)鐘控制器預(yù)分頻器,脈沖長度和波形周期可以在幾個(gè)微秒到幾個(gè)毫秒間調(diào)整。
2. 定時(shí)器時(shí)鐘配置
如圖4.20所示,TIMx的有八個(gè),其中TIM1和TIM8掛在APB2總線上,而TIM2-TIM7則掛在APB1總線上。其中TIM1&TIM8稱為高級(jí)控制定時(shí)器(advanced control timer).他們所在的APB2總線也比APB1總線要好。APB2可以工作在72MHz下,而APB1最大是36MHz。

圖4.17 TIM時(shí)鐘配置
由圖4.20可知,當(dāng)APB1 的預(yù)分頻系數(shù)為1 時(shí),這個(gè)倍頻器不起作用,定時(shí)器的時(shí)鐘頻率等于APB1 的頻率;當(dāng)APB1的預(yù)分頻系數(shù)為其它數(shù)值(即預(yù)分頻系數(shù)為2、4、8 或16)時(shí),這個(gè)倍頻器起作用,定時(shí)器的時(shí)鐘頻率等于APB1 的頻率兩倍。因?yàn)锳PB1最大為36MHz,而AHB預(yù)分頻輸出的頻率為72MHz,所以APB1預(yù)分頻器進(jìn)行了2分頻,所以定時(shí)器的時(shí)鐘頻率為2倍的APB1的頻率,即72MHz。
3.通用定時(shí)器初始化配置
通用定時(shí)器初始化配置流程為:
3.1 首先進(jìn)行配置一個(gè)TIM_TimeBaseInitTypeDef 的結(jié)構(gòu)體。
例如:TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
3.2 將定時(shí)器TIMx設(shè)置為默認(rèn)值的定時(shí)器。例如:TIM_DeInit(TIM2);
3.3根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位 。進(jìn)行如下配置。
a.配置定時(shí)器的周期加載值(TIM_Period)。它設(shè)置了在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值。它的取值必須在0x0000和0xFFFF之間。例如:
TIM_TimeBaseStructure.TIM_Period=1000;
b.設(shè)置定時(shí)器時(shí)鐘預(yù)分頻值(TIM_Prescaler)。設(shè)置了用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值。它的取值必須在0x0000和0xFFFF之間。例如:
TIM_TimeBaseStructure.TIM_Prescaler= 71;
c.設(shè)置時(shí)鐘分割。實(shí)驗(yàn)中設(shè)置為如下,即來自APB1的時(shí)鐘不分頻。
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
d.選擇定時(shí)器的計(jì)數(shù)方式。這里選擇向上計(jì)數(shù)方式。其從0開始計(jì)數(shù),當(dāng)向上計(jì)數(shù)值增加到配置的周期加載值時(shí),會(huì)觸發(fā)定時(shí)器中斷。然后計(jì)數(shù)值自動(dòng)清零。
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
e.初始化定時(shí)器。調(diào)用定時(shí)器API函數(shù)為:TIM_TimeBaseInit();
f.實(shí)驗(yàn)中采用中斷的方式進(jìn)行精確定時(shí)。所以在初始化定時(shí)器時(shí)要清除以前的中斷標(biāo)志。調(diào)用定時(shí)器的中斷標(biāo)志位函數(shù)為:TIM_ClearFlag(TIMx, TIM_FLAG_Update);
g.使能定時(shí)器中斷。調(diào)用定時(shí)器中斷API函數(shù)為:
TIM_ITConfig(TIMx,TIM_IT_Update,ENABLE);
h.使能定時(shí)器TIM_Cmd(TIMx, ENABLE);
4.NVIC初始化配置
4.1.設(shè)置中斷名稱。本例為TIM2_IRQn。
4.2.中斷優(yōu)先級(jí)的設(shè)置。
4.3. IRQ通道使能。
4.4. 根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器TIM2.
以上為設(shè)置流程。根據(jù)以上設(shè)置,例如調(diào)用相關(guān)的API函數(shù)如下NVIC中斷,具體請(qǐng)參考STM32數(shù)據(jù)手冊(cè)。
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//開TIM2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
5.實(shí)現(xiàn)LED(綠燈和紅燈)以1s、2s、5s的頻率閃爍。其中配置GPIO、TIM的時(shí)鐘;GPIO設(shè)置;定時(shí)器中斷需要配置NVIC;定時(shí)器的初始化;以及定時(shí)器中斷處理。
注:發(fā)生中斷時(shí)間=(TIM_Prescaler+1)* (TIM_Period+1)/FLK(此處FLK為72MHz)
五.實(shí)驗(yàn)報(bào)告具體要求
實(shí)驗(yàn)報(bào)告應(yīng)包括以下幾個(gè)部分:
1.實(shí)驗(yàn)?zāi)康摹?/p>
2.問題描述。
3.實(shí)驗(yàn)詳細(xì)步驟(包含源碼)。
4.實(shí)驗(yàn)過程中遇到的問題,及解決辦法。
5.實(shí)驗(yàn)心得。
實(shí)驗(yàn)代碼
#include "stm32f10x.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_tim.h"
#include "misc.h"
#include "core_cm3.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIM_Configuration(void);
void TIM2_IRQHandler(void);
void NVIC_Configuration(void);
#define GreenLight_On() GPIO_SetBits(GPIOB,GPIO_Pin_8)
#define GreenLight_Off() GPIO_ResetBits(GPIOB,GPIO_Pin_8)
#define REDLight_On() GPIO_SetBits(GPIOB,GPIO_Pin_9)
#define REDLight_Off() GPIO_ResetBits(GPIOB,GPIO_Pin_9)
/*
* 函數(shù)名:main
* 描述 :主函數(shù)
* 輸入 :無
* 輸出 :無
*/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
TIM_Configuration();
// 等待中斷觸發(fā)
while(1);
}
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
//編程習(xí)慣,用于異常處理
SystemInit(); //初始化微控制系統(tǒng)
RCC_DeInit(); //將RCC時(shí)鐘控制器設(shè)為默認(rèn)狀態(tài)
//使能外部晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部晶振穩(wěn)定
/*這一步是必須的,不穩(wěn)定的時(shí)鐘無法為
外設(shè)如GPIO、UART、ADC等提供服務(wù)*/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
//如果外部晶振啟動(dòng)成功,則進(jìn)行下一步操作
if(HSEStartUpStatus==SUCCESS)
{
//設(shè)置HCLK(AHB時(shí)鐘)=SYSCLK=72
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//PCLK1(APB1) = HCLK/2=36MHZ
RCC_PCLK1Config(RCC_HCLK_Div2);
//PCLK2(APB2) = HCLK=72MHZ
RCC_PCLK2Config(RCC_HCLK_Div1);
//FLASH時(shí)序控制
//推薦值:SYSCLK = 0~24MHz Latency=0
// SYSCLK = 24~48MHz Latency=1
// SYSCLK = 48~72MHz Latency=2
//開啟FLASH預(yù)取指令功能
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
//PLL設(shè)置 SYSCLK/1 * 9 = 8/1*6 = 9MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
//啟動(dòng)PLL
RCC_PLLCmd(ENABLE);
//等待PLL穩(wěn)定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){};
//系統(tǒng)時(shí)鐘SYSCLK來自PLL輸出
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//切換時(shí)鐘后等待系統(tǒng)時(shí)鐘穩(wěn)定
while(RCC_GetSYSCLKSource()!=0x08){};
}
//啟動(dòng)GPIO
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);
//啟動(dòng)TIM2
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2,ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
// TIM 配置
void TIM_Configuration(void)
{
void TIM_TimeBaseInit(TIM_TypeDef*TIMx,
TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //前面指是哪個(gè)TIM,后面指TimeBaseInitStruct結(jié)構(gòu)體指針。
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定義TIM初始化類型結(jié)構(gòu)體變量
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = 9999; //設(shè)置自動(dòng)重載計(jì)數(shù)周期值
TIM_TimeBaseStructure.TIM_Prescaler =7199; //設(shè)置分頻系數(shù)
//設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值 10Khz的計(jì)數(shù)頻率
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分頻因子
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //設(shè)置為向上計(jì)數(shù)方式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM2, ENABLE); //允許自動(dòng)重裝載寄存器(ARR)
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //允許TIM2溢出中斷
TIM_Cmd(TIM2, ENABLE); //TIM2開啟時(shí)鐘
}
// TIM2 中斷處理
void TIM2_IRQHandler(void)
{
int i, j;
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
//清除TIMx的中斷待處理位:TIM 中斷源
REDLight_On();
for(i = 0; i < 999; i++)
for(j = 0; j < 999; j++);
REDLight_Off();
}
//注意這里清除中斷源,不然無法正確切換模式ON||OFF
// NVIC 配置
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//開TIM2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
按照公式計(jì)算得到的單位是秒!
https://www.cnblogs.com/sankye/archive/2012/05/05/2484711.html
http://www.51hei.com/stm32/4261.html