1. 程式人生 > >STM32F030F4P6無法進入捕獲中斷的解決方法

STM32F030F4P6無法進入捕獲中斷的解決方法

出於節約成本又想快速上手的角度出發選擇了這款微控制器進行開發。但是stm32f030這款微控制器的網上資源比其他系列少了很多,輸入捕獲採集的例程更是極少。樓主使用PB1口進行捕獲採集計算頻率時發現無法進入捕獲中斷,經過學習其他歷程發現輸入捕獲時io口初始化很重要,io口需要設定為複用推輓輸出才能觸發捕獲中斷(請原諒樓主第一次用捕獲中斷)。最後實測頻率1-1000hz的訊號源輸出誤差在1%以下。部分程式碼分享如下,後續會上傳整個工程方便大家利用。

1.複用功能對映

GPIO_PinAFConfig(GPIOB, GPIO_Pin_1, GPIO_AF_0);//配置PB1為TIM14_CH1

2.IO口初始化

GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_NOPULL;//浮空狀態
GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;   //複用推輓輸出
GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);

3.定時器初始化

    TIM_TimeBaseInitTypeDef     TIM_TimeBaseStructure;
	TIM_ICInitTypeDef 			TIM_ICInitStruct;
    NVIC_InitTypeDef            NVIC_InitStructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);//使能時鐘
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
    /* 時基配置 */
    TIM_TimeBaseStructure.TIM_Period          = (0XFFFF) ;  //設定計數器
    TIM_TimeBaseStructure.TIM_Prescaler       = (48-1);  //設定預分頻的值48,1Mhz
    TIM_TimeBaseStructure.TIM_ClockDivision   = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode     = TIM_CounterMode_Up;//向上計數
    
    TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//通道2
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//對映到TI1上
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻TIM_ICPSC_DIV1
	TIM_ICInitStruct.TIM_ICFilter = 0;//配置輸入濾波器,不濾波
	TIM_ICInit(TIM14, &TIM_ICInitStruct);
    
    /* 使能TIM3全域性中斷*/
    NVIC_InitStructure.NVIC_IRQChannel            = TIM14_IRQn ;
    NVIC_InitStructure.NVIC_IRQChannelPriority    = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
	TIM_ITConfig(TIM14,TIM_IT_Update,ENABLE);//允許更新中斷
    TIM_ITConfig(TIM14,TIM_IT_CC1,ENABLE);//允許捕獲比較2中斷
    
	TIM_ClearITPendingBit(TIM14, TIM_IT_Update);//清除更新中斷
    TIM_ClearITPendingBit(TIM14, TIM_IT_CC1);//清除捕獲中斷
    TIM_Cmd(TIM14, ENABLE);

4.溢位中斷呼叫函式

void time14_updata_irq(void)//定時器更新中斷(計數溢位)中斷處理回撥函式
{
	if((TIM14_CH1_STA&0X80)==0)//還未成功捕獲
	{
		if(TIM14_CH1_STA&0X40)//已經捕獲到高電平了
		{
			if((TIM14_CH1_STA&0X3F)==0X3F)//高電平太長了
			{
				TIM14_CH1_STA|=0X80;		//標記成功捕獲了一次
				TIM14_CH1_VAL=0XFFFF;
			}
			else 
			{
				TIM14_CH1_STA++;
			}
		}	 
	}
}

5.捕獲中斷呼叫函式

void TIM14_CH1_CaptureCallback(void)//捕獲中斷髮生時執行
{                                            
	if((TIM14_CH1_STA&0X80)==0)//還未成功捕獲
	{
		if(TIM14_CH1_STA&0X40)		//捕獲到一個下降沿 		
		{	  			
			TIM14_CH1_STA|=0X80;		//標記成功捕獲到一次高電平脈寬
            TIM14_CH1_VAL=TIM_GetCapture1(TIM14);//獲取當前的捕獲值.
			TIM_OC1NPolarityConfig(TIM14,TIM_ICPolarity_Rising);//配置TIM5通道1上升沿捕獲
		}
		else  								//還未開始,第一次捕獲上升沿
		{
			TIM14_CH1_STA=0;			//清空
			TIM14_CH1_VAL=0;
			TIM14_CH1_STA|=0X40;		//標記捕獲到了上升沿
			TIM_Cmd(TIM14, DISABLE);//關閉定時器5
			TIM_SetCounter(TIM14,0);//清零計數
			TIM_OC1NPolarityConfig(TIM14,TIM_ICPolarity_Falling);//定時器5通道1設定為下降沿捕獲
			TIM_Cmd(TIM14, ENABLE);//使能定時器5
		}		    
	}	

6.計算頻率

if(TIM14_CH1_STA&0X80)        //成功捕獲到了一次高電平
{
	temp=TIM14_CH1_STA&0X3F; 
	temp*=0XFFFF;		 	    //溢位時間總和
	temp+=TIM14_CH1_VAL;      //得到總的高電平時間
	sys_state.sys_temp = temp;
	sys_state.frequency = (float)(1000000 / (float)sys_state.sys_temp);
	TIM14_CH1_STA=0;          //開啟下一次捕獲
}