STM32學習之普通定時器是否能定時1us?

對於STM32F10x系列使用普通定時器能否能定時1us,筆者一直抱有懷疑態度。

於是筆者做了下述實驗:

代碼:

主函數:

int main(void)
{
SystemClock_Config();
LED_Init();//LED初始化
NVIC_Config();
Timer2_Config();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
while(1)
{
}

}

GPIO設置

void LED_Init(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE); //使能PB,PE時鐘

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;            //端口PC0配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置推輓輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO速度50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);     //初始化GPIOC.0
GPIO_SetBits(GPIOC,GPIO_Pin_0);                      //PC.0輸出高


GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;              //端口PD3配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置推輓輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO速度50MHz
GPIO_Init(GPIOD, &GPIO_InitStructure);     //初始化GPIOD.3
GPIO_SetBits(GPIOD,GPIO_Pin_3);                      //PD.3輸出高

}

NVIC設置:

void NVIC_Config(void)  
{  
NVIC_InitTypeDef NVIC_InitStructure;  

//選擇中斷分組0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  


//選擇TIM2的中斷通道  
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;       

//搶佔式中斷優先級設置爲0  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

//響應式中斷優先級設置爲0  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

//使能中斷  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

NVIC_Init(&NVIC_InitStructure);  

TIM2設置:

void Timer2_Config(void)  
{   
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   

TIM_DeInit(TIM2);  

//定時公式:(TIM_Period + 1) * (TIM_Prescaler + 1) / TIM2 Clock,向上
//TIM2時鐘設置72MHz  
TIM_TimeBaseStructure.TIM_Period=10-1;  //自動重裝載寄存器的值  

TIM_TimeBaseStructure.TIM_Prescaler=(36-1);         //時鐘預分頻數  

TIM_TimeBaseStructure.TIM_ClockDivision=0;  //採樣分頻(捕獲)普通定時不需要這個設置 ,無論怎麼改變不影響輸出頻率

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式  

TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);  

TIM_ClearFlag(TIM2,TIM_FLAG_Update);               //清除溢出中斷標誌  

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //使能更新中斷

TIM_Cmd(TIM2,ENABLE);                              //開啓時鐘  

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE); /*先關閉等待使用*/    
}   


中斷函數:

void TIM2_IRQHandler(void)   
{  
u8 i;
u8 ReadValue;  
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)    //檢測是否發生溢出更新事件  
{  
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);//清除TIM2的中斷待處理位  

                /************************************************/

                /***********************重點********************/
/*
for(i=0;i<10;i++)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}
 */

                /***********************重點********************/

                /*************************************************/
ReadValue = GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_0);  

if(ReadValue == 0)                   //若該端口當前爲低電平,  
{  
GPIO_SetBits(GPIOC,GPIO_Pin_0);//將其改爲高電平輸出 ;  
}      
else                            //若該端口當前爲高電平,  
{  
GPIO_ResetBits(GPIOC,GPIO_Pin_0);   //將其改爲低電平輸出;  
}  
}          
}  

上述代碼下載到單片機裏面,輸出100KHz的方波(5us定時),但是,筆者欲1us定時,簡單認爲:

TIM_TimeBaseStructure.TIM_Period=2-1;  //自動重裝載寄存器的值  

TIM_TimeBaseStructure.TIM_Prescaler=(36-1);         //時鐘預分頻數  

後來發現,輸出方波最高頻率爲250KHz,在網上查閱各類博客,發現並不能解決問題。

當隨手在中斷函數中加了幾句話(Period,Prescaler值不變),發現波形改變,於是就開始懷疑1us定時寄存器那樣設置,是不是中斷函數還未執行完畢,又發生了中斷,導致一直在中斷函數中。

爲驗證猜想,筆者做了一個實驗,在中斷函數中執行了10個:

for(i=0;i<10;i++)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}

輸出波形是這樣的:


正常100KHz波形是這樣的(上面那個函數屏蔽):


10個多餘的週期會導致波形頻率差這麼多,欲定時1us(前提中斷函數比較複雜),採用普通定時器這樣的辦法是不可以的。

如果中斷函數代碼時一句或者兩句,定時1us還有可能,普通定時器否則定時1us不可能實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章