周波数測定を、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する

TIM1で外部信号の周波数測定をする方法はすでに解説しました.

TIM2,TIM3,TIM4でも同様のことができるのでしょうか?

結論をいうと、できません.TIM1でしかできません.(と強く推測します)

なぜか?

TIM1にはある
周波数測定には必須な TIM1_SMCR というレジスタが、TIM2,TIM3,TIM4 に存在しないんです.
実際にやってみましたけど、TIM2,TIM3では満足に動きませんでした.
TIM4は、TIM2,TIM3よりも機能がショボイのでそもそも無理です.

失敗したソースコードを下記で説明します.サンプルプログラムはこちらです.
外部からSTM8S-DISCOVERYのTIM1,TIM2,TIM3に1kHzのパルスを入力して、周波数測定結果をUARTへ送信するというプログラムです.
下記は main.c のポイント的なところです.

●CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
CLK_HSIPrescalerConfig( CLK_PRESCALER_HSIDIV1 );
CLK_SYSCLKConfig( CLK_PRESCALER_CPUDIV1 );
クロックとして内部発振16MHzを使います.
プリスケーラは使いません.
したがって、fMASTER=fCPU=16MHz が供給されます.

TIM1_DeInit();
@TIM1_PrescalerConfig(0, TIM1_PSCRELOADMODE_UPDATE);
ATIM1_PWMIConfig(TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI, TIM1_ICPSC_DIV1, 15);
BTIM1_SelectInputTrigger( TIM1_TS_TI1FP1 );
CTIM1->SMCR = (TIM1->SMCR & ~TIM1_SMCR_SMS) | 0b100; // TIM1->SMCR->SMS=100 (Reset mode)
TIM1_ITConfig(TIM1_IT_CC1, ENABLE);
TIM1_Cmd(ENABLE);
TIM1を周波数測定モードに設定しています.
@ABCのコードそれぞれは、下図の@ABCの構造を設定しています.
TIM1でなら、周波数とdutyを測定できます.


●TIM2_DeInit();
@TIM2_PrescalerConfig(TIM2_PRESCALER_1, TIM2_PSCRELOADMODE_UPDATE);
ATIM2_PWMIConfig(TIM2_CHANNEL_1, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 15);
TIM2_ITConfig(TIM2_IT_CC1, ENABLE);
TIM2_Cmd(ENABLE);
TIM2を周波数測定モードにしたいのですが、TIM2にはBCの機能がありません.
上図でBCが無いわけですから、16bitカウンタは廻るんですが、resetされませんので、周波数を測定できません.

●TIM3_DeInit();
TIM3_PrescalerConfig(TIM3_PRESCALER_1, TIM3_PSCRELOADMODE_UPDATE);
TIM3_PWMIConfig(TIM3_CHANNEL_1, TIM3_ICPOLARITY_RISING, TIM3_ICSELECTION_DIRECTTI, TIM3_ICPSC_DIV1, 15);
TIM3_ITConfig(TIM3_IT_CC1, ENABLE);
TIM3_Cmd(ENABLE);
TIM3を周波数測定モードにしたいのですが、TIM3にはBCの機能がありません.
上図でBCが無いわけですから、16bitカウンタは廻るんですが、resetされませんので、周波数を測定できません.


●TIM4_DeInit();
TIM4_TimeBaseInit( TIM4_PRESCALER_128, 255 ); // 16MHz/128/256=488Hz
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4_Cmd(ENABLE);
TIM4は、UARTに表示するためのインターバルを決めるタイマとして使います.

//  _________|~~~~~~|____________|~~~~~~|__________
//            <------------------->  TIM1_ICvalue1
//            <------>   TIM1_ICvalue2

u16 TIM1_IC_value1=0, TIM1_IC_value2=0;
void TIM1_IC_isr(void) interrupt 12
{
    TIM1_IC_value1 = TIM1_GetCapture1()+1;  // get value
    TIM1_IC_value2 = TIM1_GetCapture2()+1;  // get value
    TIM1_ClearFlag(TIM1_FLAG_CC1);
    TIM1_ClearFlag(TIM1_FLAG_CC2);
}
TIM1が外部入力信号の1周期を計測し終わったら、割り込みをかけますので、このルーチンへ飛んできます.
このルーチンでは
TIM1_GetCapturex() 関数で周波数測定結果を取りにいってgloval変数に保存します.

//  _________|~~~~~~|____________|~~~~~~|__________
//            <------------------->  TIM2_ICvalue1
//            <------>   TIM2_ICvalue2

u16 TIM2_IC_value1=0, TIM2_IC_value2=0;
void TIM2_IC_isr(void) interrupt 14
{
    TIM2_IC_value1 = TIM2_GetCapture1()+1;  // get value
    TIM2_IC_value2 = TIM2_GetCapture2()+1;  // get value
    TIM2_ClearFlag(TIM2_FLAG_CC1);
    TIM2_ClearFlag(TIM2_FLAG_CC2);
}
TIM2が外部入力信号の1周期を計測し終わったら、割り込みをかけますので、このルーチンへ飛んできます.
このルーチンでは
TIM2_GetCapturex() 関数で周波数測定結果を取りにいってgloval変数に保存します.

//  _________|~~~~~~|____________|~~~~~~|__________
//            <------------------->  TIM3_ICvalue1
//            <------>   TIM3_ICvalue2

u16 TIM3_IC_value1=0, TIM3_IC_value2=0;
void TIM3_IC_isr(void) interrupt 16
{
    TIM3_IC_value1 = TIM3_GetCapture1()+1;  // get value
    TIM3_IC_value2 = TIM3_GetCapture2()+1;  // get value
    TIM3_ClearFlag(TIM3_FLAG_CC1);
    TIM3_ClearFlag(TIM3_FLAG_CC2);
}
TIM3が外部入力信号の1周期を計測し終わったら、割り込みをかけますので、このルーチンへ飛んできます.
このルーチンでは
TIM3_GetCapturex() 関数で周波数測定結果を取りにいってgloval変数に保存します.

u16 cnt_tim4=0;
void TIM4_Update_isr(void) interrupt 23
{
    char TXStr[100];
  float MEASURED_HZ, MEASURED_DUTY;
    cnt_tim4++;
    if(cnt_tim4>=400)
    {
        cnt_tim4=0;
        GPIO_WriteReverse(GPIOD,GPIO_PIN_0); // int freq monitor CN4-1pin
       
        MEASURED_HZ = (float)fMASTER / (float)TIM1_IC_value1;
        MEASURED_DUTY = (float)TIM1_IC_value2 / (float)TIM1_IC_value1 * 100.0 ;
        sprintf(TXStr,"MEAS1: %9.2f[Hz] %5.2f[pct]",MEASURED_HZ,MEASURED_DUTY);
        SerialPutString(TXStr);
        sprintf(TXStr," TIM1_IC_value1=%u  TIM1_IC_value2=%u",TIM1_IC_value1,TIM1_IC_value2);
        SerialPutString(TXStr);
        SerialPutString("\r\n");
       
        MEASURED_HZ = (float)fMASTER / (float)TIM2_IC_value1;
        MEASURED_DUTY = (float)TIM2_IC_value2 / (float)TIM2_IC_value1 * 100.0 ;
        sprintf(TXStr,"MEAS2: %9.2f[Hz] %5.2f[pct]",MEASURED_HZ,MEASURED_DUTY);
        SerialPutString(TXStr);
        sprintf(TXStr," TIM2_IC_value1=%u  TIM2_IC_value2=%u",TIM2_IC_value1,TIM2_IC_value2);
        SerialPutString(TXStr);
        SerialPutString("\r\n");
       
        MEASURED_HZ = (float)fMASTER / (float)TIM3_IC_value1;
        MEASURED_DUTY = (float)TIM3_IC_value2 / (float)TIM3_IC_value1 * 100.0 ;
        sprintf(TXStr,"MEAS3: %9.2f[Hz] %5.2f[pct]",MEASURED_HZ,MEASURED_DUTY);
        SerialPutString(TXStr);
        sprintf(TXStr," TIM3_IC_value1=%u  TIM3_IC_value2=%u",TIM3_IC_value1,TIM3_IC_value2);
        SerialPutString(TXStr);
        SerialPutString("\r\n");
    }
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
}
UARTへ向けて周波数とdutyの計算結果を送信します.

inserted by FC2 system