STM32:基本定時器詳解
阿新 • • 發佈:2019-02-04
一、基本定時器介紹
在STM32中,基本定時器有TIM6、TIM7等。基本定時器主要包含時基單元,提供16位的計數,能計數0~65535。基本定時器除了計數功能以外,還能輸出給DAC模組一個TRGO訊號。基本定時器框圖如下:
二、時基單元介紹
STM32的所有定時器都具備時基單元,時基單元的功能就是簡單的計數,即計數時鐘源TMxCLK的脈衝個數,這個時鐘源來至APB1匯流排。高階和通用定時器還可以使用其他的時鐘源進行計數,在高階定時器和通用定時器中會詳細介紹。在基本定時器框架中可知時基單元包含如下三個部分:
1.ARR 自動重灌載暫存器
2.CNT 計數器
3.PSC 預分頻器
基本定時器的定時(計數)功能配置如下:
void TIM6_IRQHandler(void) { static int counter = 0; if(TIM_GetITStatus(TIM6,TIM_IT_Update)) { //在設定TIM_SelectOnePulseMode(TIM6,TIM_OPMode_Single);後中斷進去兩次 TIM_ClearITPendingBit(TIM6,TIM_IT_Update); } } //基本定時器 void TIM6_Configuration() { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //時鐘使能 TIM_TimeBaseInitStruct.TIM_Period = 10 -1; TIM_TimeBaseInitStruct.TIM_Prescaler = 72; TIM_TimeBaseInitStruct.TIM_ClockDivision = 0; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStruct);// TIMx->EGR.UG NVIC_InitStruct.NVIC_IRQChannel = TIM6_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStruct); TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE); TIM_ClearITPendingBit(TIM6,TIM_IT_Update); // TIM_SelectOnePulseMode(TIM6,TIM_OPMode_Single);//如需配置單脈衝模式,開啟此註釋 TIM_ARRPreloadConfig(TIM6,ENABLE); TIM_Cmd(TIM6,ENABLE);//CEN 位 TIM_ClearITPendingBit(TIM6,TIM_IT_Update); }
值得說明的是,基本定時器還支援單脈衝模式,配置單脈衝模式如程式碼註釋即可。單脈衝模式要注意的是在定時器溢位兩次後才關閉定時器,即失能定時器。在程式碼中,配置有中斷,在單脈衝模式下,可以清晰的看到進入定時器中斷2次。
三、定時器訊號輸出
定時器的訊號輸出與定時器中的控制暫存器2(TIM6->CR2)的MMS位相關,基本定時器輸出的訊號只能用作DAC的觸發,而高階定時器、通用定時器的輸出訊號可以觸發定時器以及DAC,具體細節這裡不細說。定時器訊號輸出的例子可以參考我的博文http://blog.csdn.net/quentinecho/article/details/79068001。這個例子中使用TIM6輸出的TRGO訊號啟動了DAC產生一個三角波,當然其他的DAC觸發方式也可以產生一個三角波。
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "system_stm32f10x.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
/*DAC輸出 = Vref x (DOR/4095)*/
//DAC的兩個通道可以配置使用
//相同觸發源/不同觸發源
//同時觸發/獨立觸發 DAC_DualSoftwareTriggerCmd函式設定軟體同時觸發
//使用波形發生器/不使用波形發生器
//使用三角波發生器/使用噪聲發生器/不使用波形發生器
//設定相同DAC_LFSRUnmask_TriangleAmplitude的值/設定不相同DAC_LFSRUnmask_TriangleAmplitude的值
//等等以上各種情況可以任意組合,互不影響。
void DAC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
DAC_InitTypeDef DAC_InitStruct;
//第一步 使能時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
//第二步 配置引數
/*一旦使能DACx通道,相應的GPIO引腳就會自動與DAC的模擬輸出相連,為了避免寄生的干擾和額外的功耗,引腳PA4/PA5在之前應當設定成“模擬輸入”
注意是“模擬輸入“,因為STM32中沒有模擬輸出,所以雖然PA4 PA5是輸出模擬訊號,也只能設定成GPIO_Mode_AIN*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_SetBits(GPIOA,GPIO_Pin_4 | GPIO_Pin_5) ;//PA.4 PA.5輸入高 ,上拉輸入起抗干擾的作用
// /*DAC 通道1 PA4 產生噪聲*/
// DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_Noise;
// DAC_InitStruct.DAC_Trigger = DAC_Trigger_T6_TRGO;//DAC_Trigger_T6_TRGO;
// DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//輸出快取可以用來減少輸出阻抗,無需外部運放即可直接驅動外部負載
// DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bits10_0;//每次觸發計算一次LSFR演算法,並將得到的值再加上DAC_DHRx的數值,去掉溢位位後寫入DAC_DORx暫存器,輸出特定的電壓
// DAC_Init(DAC_Channel_1,&DAC_InitStruct);//參與LSFR演算法的位數由DAC_LFSRUnmask_TriangleAmplitude來確定,DAC_LFSRUnmask_Bits10_0數值表示有10位參與LSFR計算
/*DAC 通道1 PA4 普通數模轉換*/
DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_None;//關閉波形發生器
DAC_InitStruct.DAC_Trigger = DAC_Trigger_T6_TRGO;//DAC_Trigger_Software/DAC_Trigger_Ext_IT9
DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//輸出快取可以用來減少輸出阻抗,無需外部運放即可直接驅動外部負載
DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//該引數與噪聲/三角波發生器相關,普通DAC轉換是設定為0即可
DAC_Init(DAC_Channel_1,&DAC_InitStruct);
/*DAC 通道2 PA5 產生三角波*/
DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
DAC_InitStruct.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;//內部的三角波計數器每次觸發時候之後累加1,該計數器的值與DAC_DHRx的數值相加,去掉溢位位後寫入DAC_DORx暫存器,輸出電壓
DAC_Init(DAC_Channel_2,&DAC_InitStruct);//三角波計數器的最大值由DAC_LFSRUnmask_TriangleAmplitude來確定,當計數器達到這個最大值,然後三角波計數器開始遞減
//第三步 使能器件
//DAC_SetDualChannelData(DAC_Align_12b_R,4095,0);等價於DAC_SetChannel1Data(DAC_Align_12b_R, 4095); DAC_SetChannel2Data(DAC_Align_12b_R, 0);
/*DAC 通道1 PA4 使能*/
DAC_SetChannel1Data(DAC_Align_12b_R, 4095); //12位右對齊資料格式設定DAC值 設定值最大為4095,設定成4096則溢位,DORx即為0
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
/*DAC 通道2 PA5 使能*/
DAC_Cmd(DAC_Channel_2, ENABLE); //使能DAC1
DAC_SetChannel2Data(DAC_Align_12b_R, 0); //12位右對齊資料格式設定DAC值
}
//基本定時器
void TIM6_Configuration()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//第一步 使能時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //時鐘使能
//第二步 配置引數
TIM_TimeBaseInitStruct.TIM_Period = 10 -1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 72;
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStruct);// TIMx->EGR.UG
/*TIM6,7可以輸出3種類型的TRGO訊號
#define TIM_TRGOSource_Reset ((uint16_t)0x0000) //復位 UG
#define TIM_TRGOSource_Enable ((uint16_t)0x0010) //使能 CEN
#define TIM_TRGOSource_Update ((uint16_t)0x0020) //更新事件
*/
TIM_SelectOutputTrigger(TIM6,TIM_TRGOSource_Update);//輸出觸發TRGO訊號 這裡TRGO訊號就是定時器溢位產生的更新訊號
//第三步 使能器件
TIM_Cmd(TIM6,ENABLE);//CEN 位
}
int main()
{
DAC_Configuration();
TIM6_Configuration();
while(1)
{
}
}