專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> STM32 >> 瀏覽文章

stm32f103 tim3_etr完成高頻信號的頻率計(jì)算

作者:huqin   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時間:2014年05月05日   【字體:

 學(xué)習(xí)stm32已經(jīng)有一段時間了,接到第一個項(xiàng)目的時候是關(guān)于stm32f051的ad配置和da配置,本科時候連51都沒接觸過的人一上來就是32位單片機(jī),著實(shí)讓我蛋疼菊緊的很。還好慢慢的啃了中文手冊和網(wǎng)上的一些例程,總算是完成的功能。這些個有時間再整理上傳吧、

 
之后又弄了些103的東西,今天主要整理一下在進(jìn)行信號頻率計(jì)算的時候遇到的一些問題和解決辦法,以便日后查看。也希望給碰到類似問題的童鞋一些啟發(fā)。
 
實(shí)驗(yàn)要求:使用tim3_etr實(shí)現(xiàn)對高頻脈沖的頻率檢測
硬件要求:stm32f103為核心,頻率輸入管腳為PD2(uart5_rx/t3_etr)
 
剛拿到這個實(shí)驗(yàn)的時候我連tim3是什么東西都不知道,然后查閱手冊對tim3的了解如下:(個人見解)
1.timx可以定時,可以進(jìn)行輸入捕獲,輸入捕獲可以測頻率可測脈沖寬度,這就是這個實(shí)驗(yàn)要用到的功能
2.timx_CCR1 捕獲/比較使能寄存器是一個比較重要的寄存器,該寄存器用來存儲捕獲發(fā)生時TIMx_CNT值,我們從TIMx_CCR1中就可以讀出通道一捕獲發(fā)生時刻的TIMx_CNT的值,通過兩次捕獲(上升沿一次,下降沿一次)的差值,就可以計(jì)算出高電平脈沖的寬度,f=1/脈寬。不過貌似這只適用于低頻脈沖。我沒有用這種方法。
3.TIMx_etr 是外部觸發(fā)的第二種模式,主要用于脈沖計(jì)數(shù)。我們要用的就是他
 
大體了解之后就開始在網(wǎng)上找各種代碼來看,大同小異,不過不修改的話都不太能直接用。測頻率無非就是兩個值,一個是基準(zhǔn)時間t,一個是脈沖個數(shù)n。f = n/t 就OK了
 
現(xiàn)在要解決的問題,就是如何測量脈沖個數(shù)的問題。每一個TIM都一個自己的計(jì)數(shù)器,和一個自己的預(yù)裝載寄存器ARR.這里既然這是為了計(jì)數(shù),那么設(shè)置ARR的值為0xFFFF,最大值。
 
配置代碼如下所示
 
  TIM_DeInit(TIM3);
  TIM_TimeBaseStructure.TIM_Period =0xFFFF;//當(dāng)計(jì)數(shù)器從0記到FFF為一個周期,自動裝載寄存器ARR中的值
  TIM_TimeBaseStructure.TIM_Prescaler = 0X00; 
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;//設(shè)置時鐘系數(shù) 不分頻
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上計(jì)數(shù)模式
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // Time base configuration
 
 
  TIM_ITRxExternalClockConfig(TIM3,TIM_TS_ETRF); //配置外部觸發(fā),否則不會計(jì)數(shù)
  TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0);
  TIM_SetCounter(TIM3, 0);  //設(shè)置計(jì)數(shù)器為0
  TIM_Cmd(TIM3, ENABLE);
 
至此tim3_etr配置完畢。
 
接下來要解決的問題是如何進(jìn)行10ms精確定時。使用tim2實(shí)現(xiàn),配置如下
 
void Tim2_Config(){
        TIM_TimeBaseInitTypeDef   TIM2_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        
        TIM_DeInit(TIM2);
  TIM2_TimeBaseStructure.TIM_Period =10000;
  TIM2_TimeBaseStructure.TIM_Prescaler = 71; 
  TIM2_TimeBaseStructure.TIM_ClockDivision = 0x0;//ÉèÖÃʱÖÓϵÊý ²»·ÖƵ
  TIM2_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//ÏòÉϼÆÊýģʽ
  TIM_TimeBaseInit(TIM2, &TIM2_TimeBaseStructure); // Time base configuration
        TIM_ClearFlag(TIM2,TIM_FLAG_Update);//Çå³þ¸üбê־λ
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); 
        
        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
        
        TIM_Cmd(TIM2, ENABLE);                
}
 
中斷函數(shù)配置如下
void TIM2_IRQHandler(void)   
{
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) 
        {
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
                Frequency_value = TIM_GetCounter(TIM3)*10/0.01/1000;//單位khz
                TIM_SetCounter(TIM3, 0);  
        }
}
 
通過串口發(fā)送出去,串口發(fā)送配置如下
void uart_Init(void){
        GPIO_InitTypeDef  GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;              
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
 
                                  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;                 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_Init(GPIOA, &GPIO_InitStructure);        
 
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART1, &USART_InitStructure); 
 
  USART_Cmd(USART1, ENABLE);
}
 
int fputc(int ch, FILE *f){
        USART_SendData(USART1, (unsigned char) ch);   
        //while (!(USART1->SR & USART_FLAG_TXE));   
        while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);       
        return (ch);   
}
 
void UART_send_byte(uint8_t byte) 
{
while(!((USART1->SR)&(1<<7)));
USART1->DR=byte;        
}                
 
void UART_Send(uint8_t *Buffer, uint32_t Length)
{
             TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE ); //此處一定要有否則串口會發(fā)送錯誤
        while(Length != 0)
        {
                while(!((USART1->SR)&(1<<7)));//µÈ´ý·¢ËÍÍê
                USART1->DR= *Buffer;
                Buffer++;
                Length--;
        }
             TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); 
}
 
 
至此,實(shí)驗(yàn)結(jié)束。驗(yàn)證通過
關(guān)閉窗口

相關(guān)文章