stm 8 s 103 f 3 p 6の遅延関数

13543 ワード

stm 8 sを用いた場合は1 us精度のパルスを発生させることが期待されていたが,変調しても実現できなかった.現在の状況では、内部16 MHzのRCクロックソースを使用してtimer 4に与え、さらに8分周して25 usの割り込みを生成します.私ができる最小割り込み周期は15 us程度です.それは良い整数ではないことを考慮すると、主に整数、例えば1001000を遅らせると割り切れないので、25 usを最小単位とするしかありません.タイマーで1 usのパルスを発生できる人がいたら教えてください.ありがとうございます.基本的な考え方はtimer 4を25 usおきにカウントし、遅延関数を用いてtimer 4の割り込み回数を統計することです.指定した遅延時間が完了したらwhileループを終了します.
#include"stm8s.h"


uint8_t startflag = 0;
uint16_t timercnt = 0;


/*******************************************************************************
   ;init_clk()
    :       
    : 
    : 
   : 
    : 
*******************************************************************************/
void init_clk(void)
{
      //     
  CLK_HSICmd(ENABLE);//      RC
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//    
  CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
}

/*******************************************************************************
   :init_timer4()
    :   timer4
    : 
    : 
   : 
    : 
*******************************************************************************/
void init_timer4(void)
{

  TIM4_TimeBaseInit(TIM4_PRESCALER_8, 50);   //       0.5us@8  @16MHz
  TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
  TIM4_Cmd(ENABLE);
}

/*******************************************************************************
   :init_gpio()
    :   GPIO
    : 
    : 
   : 
    : 
*******************************************************************************/
void init_gpio(void)
{
  GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);
}

/*******************************************************************************
   :delayus()
    :    
    :us    
    : 
   : 
    :    25us    ,   25us,     
*******************************************************************************/
void delayus(uint16_t us)
{    
    //Set the flag to make ISR start to count
    startflag = 1;

    us = (us <= 25?25:us);

    us = us / 25 - 1;

    //  TIM4_Cmd(ENABLE);

    //Wait until expire 
    while(timercnt <= us);

    //TIM4_Cmd(DISABLE);

    //Clear flag and timer cnt
    startflag = 0;
    timercnt = 0;
}


/*******************************************************************************
   :delayms()
    :    
    :ms    
    : 
   : 
    :   1ms
*******************************************************************************/
void delayms(uint16_t ms)
{
  uint16_t i=0;
  uint16_t j=0;

  for(i=0;i<ms;i++)
  {
    delayus(1000);
  }
}

/*******************************************************************************
   :main()
    :::  
*******************************************************************************/
int main(void)
{
  init_gpio();
  init_clk();
  init_timer4();
  enableInterrupts();

  while(1)
  {
    GPIO_WriteReverse(GPIOB, GPIO_PIN_5);
    delayus(50);
    //delayms(750);
  }

  return 0;
}

void assert_failed(u8* file, u32 line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* Infinite loop */
  while (1)
  {
  }
}



割り込み関数:
/**
  * @brief Timer4 Update/Overflow Interrupt routine.
  * @param  None
  * @retval None
  */
 INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
 {
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */

  if(startflag == 1)
  {
    timercnt++;
  }
  TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
}

オシロスコープを使用してテストしたところ、delayus(1000);時測定の遅延は1014 usで、それ以上の14 usはどこから来たのか分からないし、他のパラメータを使うときも多く出てくる10+usがあるので、これ以上出てくる値にはちょっとつらくて、この誤差は少し大きいような気がします.その後、プログラムを見ると、カウンタが動作しているため、startflag=1が検出されたときにのみtimercntの累積が開始される可能性があります.これは、前回のカウンタが中断したばかりの場合、ユーザーがstartflag=1を設定するなど、少なくとも1つのカウントサイクルの遅延がある程度存在します.しかしtimer 4は次の割り込みが来るまでカウントできないので、少なくとも25 usはカウントできないのではないでしょうか.そうではありません.ログを書くとき、これはカウントが少なくなることに気づきました.マルチカウントではありません.その時、この問題を発見したとき、これが多時間になるとは思わなかったので、このメカニズムを使わないように、修正しました.まずカウンタを一時停止させ、ユーザーがdelayus()を呼び出したときにカウントを開始し、遅延時間になってからtimer 4を停止します.つまり、私が上のdelayus()に注釈したTIM 4_Cmd()の2つのインタフェース.このように変更した後、オシロスコープを1回使用すると、誤差が大きいことがわかりました.最初に使用したメカニズムほどではありませんが、delayus()で2回以上イネーブルとイネーブルインタフェースを呼び出した可能性があると思います.だから最後に始めのメカニズム、つまり上のコードに戻ります.
あ、そうだ、もうちょっと補足しますが、純ソフトウェアの遅延はあまりにもでたらめだと思います.単回で直接使うのですが
while(1)
{
    GPIO_WriteReverse(GPIOB, GPIO_PIN_5);
}

この方法では100 ns程度の遅延出力方波を実現できますが、200 ns,300 ns,500 ns,650 nsの遅延を実現するには本当に面倒です.見た目のように簡単な倍数のパラメータを修正すればいいわけではありません.全く規則がありません.どうせ私は見つけられません.そして、この法則を探すのは本当に面倒です.このように1つの関数呼び出し時間の消費にかかわるのは、1つの空の関数を呼び出しても時間がかかることと、呼び出されるたびの誤差が複数回呼び出される累積の問題であり、例えば1回のasm(「nop」)を呼び出し、2回、3回、4回、複数回の消費時間が規則的な線形の増加ではないまで、いずれにしても私はそれらの差カウントから得た遅延と実際にオシロスコープでテストした結果に大きな誤差があるので、先にやらないで、後でまたやる時間があるかもしれません.