STM32 IO中斷方式測試頻率


 一、STM32 IO中斷方式測試頻率有要求,頻率不能過快,目前測試2M沒問題,頻率過高中斷觸發就處理不過來。

二、過快的頻率得先降頻,用D觸發器對頻率進行降頻,如下圖所示,2、4、8、16分頻,此例用2M時鍾進行測試,對2M時鍾進行2、4、8、16分頻

 

 

 

三、設置一個定時器,用於計時,可用於測試一段函數使用的時間

用TIM2或TIM5定時器,是因為計數器可以支持到32位,一般都可以滿足測試函數時間,而不需要再去寫定時器中斷函數。

定時器框圖如下:

 

 

 

(1)、自動重裝載寄存器TIM_Period 設置最大,也就0~0xFFFFFFFF

(2)、預分頻TIM_Prescaler,設置定時器計數時鍾,也就是計一個數需要的時間。

    <a>、得知道當前用的定時器是掛在哪個總線上?

     >>可以查看資料手冊,當前用的TIM2定時器掛在APB1上


    <b>、要得到CK_CNT,得知道CK_PSC,也就是TIMxCLK(CK_INT)是多少?

               >>從上面知道TIM2是掛在APB1上,也就是PCLK1,再system_stm32f4xx.c ->static void SetSysClock(void)中

     查看PCLK1和PCLK2分別是由HCLK 4分頻和2分頻得到,PCLK1=180/4=45M 和PCLK2=180/2 =90M, 分頻系數PPRE1 = 4、PPRE2 =2,      TIMxCLK(CK_INT) = 45M ?其實是不對的

 

 

 

搜索TIMxCLK關鍵字,可以找到這段文字. 從上面看可得知分頻系數PPRE1 = 4、PPRE2 =2,所以 TIMxCLK = 2 * PCLKx ,即TIMxCLK = 2 * 45M =90M

 

   TIMxCLK = 2x45M =90M ,為了便於計算,將定時器時鍾設置為1M,也就是計一個數用1us的時間,可將預分頻器值設置90-1=89,定時器時鍾CK_CNT = (89-0+1)* 1 /(45*2) = 1M .注意:預分頻器是從開始計數,所以是(89-0+1)

 

 3、基本定時器沒有預分頻功能,此項會被忽略,故TIM_ClockDivision = 0,也可以設置幾個參數看看是否變動。

 4、計數方式TIM_CounterMode 設置為遞增計數

 

 1 void times_on(void)
 2 {
 3   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 4 
 5   RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE);
 6 
 7   /* Time base configuration */
 8   TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF;  //自動重裝載寄存器的值  TIM2/TIM5定時器是32位計數器,計數器從0開始計數
 9   TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock / 2) / 1000000) - 1;   //預分頻器從0開始計數,180M/2-1 = 89,故預分頻器值是90,定時器時鍾TIMx_clk = 90*1/(pclk1*2) = 90*1/(45*2)=1MHz
10   TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //可以忽略
11   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //遞增計數
12 
13   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);    //結構體進行初始化
14   TIM_ARRPreloadConfig(TIM2, ENABLE);                //使能自動加載
15    
16   /* TIM Interrupts disable */
17   TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, DISABLE);
18 
19   /* TIM2 enable counter */
20   TIM_Cmd(TIM2, ENABLE);
21   
22 }
23 void times_off(void)
24 {
25   TIM_Cmd(TIM2, DISABLE);
26   
27 }
28 
29 uint32_t get_cur_times()  //獲取計時器當前值,通過前后兩次獲取的值做差值,算出所得耗時時間
30 {
31     return TIM2->CNT;
32 }

 

四、利用IO上升沿中斷方式觸發,在中斷里計數,比如計數10000次,也就是10000個時鍾周期

 

IO配置:

void  gpio_config(void)
{
    //PA0外部中斷觸發
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

中斷配置:

void EXTI_Config(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    
    //PA0作為外部中斷,得相連接
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
    
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;//通道
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中斷
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿
    EXTI_InitStructure.EXTI_LineCmd  = ENABLE;//使能
    EXTI_Init(&EXTI_InitStructure);
}

void NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //由於使用的是PA0,對應的是EXTI0通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中斷使能
    NVIC_Init(&NVIC_InitStructure);    
}

 

stm32f4xx_it.c 中斷函數:

#define EXIT_CNT  10000  //測試10000個時鍾周期計數

float T = 0.0;
float Fre = 0.0;
uint32_t  exit_cnt = 0;
uint8_t exit_flg = 0;
__IO uint32_t time_1 = 0;
__IO uint32_t time_2 = 0;

void EXTI0_IRQHandler()
{
    if(0 == exit_cnt)
    {
        time_1 =  get_cur_times(); //首次觸發進入中斷,獲取當前值
    }
    
    EXTI_ClearITPendingBit(EXTI_Line0);
    exit_cnt ++;
    
    if(EXIT_CNT == exit_cnt)
    {
        time_2 =  get_cur_times();//計數達到設定值后,獲取當前值
        exit_cnt = 0;
        T = (time_2 - time_1)*1.0/EXIT_CNT;  //前后獲取的值做差值,算出一個時鍾周期時間
        Fre = 1/T * 1000*1000; //換算出頻率
        exit_flg = 1;
    }
}

 

主函數:

int main(void)
{  
   gpio_config();
   Debug_USART_Config(); times_on(); //開啟定時器 EXTI_Config(); NVIC_Config();
while(1) {
     demo_chipid_read();
if(1 == exit_flg) { exit_flg = 0; printf("------------------------------------------\r\n"); printf("T = %lf(us)\r\n", T); printf("Fre = %lf(Hz)\r\n", Fre); printf("------------------------------------------\r\n"); } Delay_ms(850); }
}

 

測試2M源時鍾、4分頻、8分頻、16分頻結果如下:

      

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM