stm8L测量LSI频率,提高AWT精度,解决LSI误差的问题

这个网上资料比较少,用AWU测量的方式是stm8s系列的。翻遍了stm8L的手册才发现用BEEP可以测量,英文的看的头疼。

image.png

手册上只有寥寥两语,大意是要设置BEEP的寄存器连接到TIM2 定时器的输入测量。那还得研究一下定时器测频率。

根据这个图,要先使能BEEP时钟,然后选择LSI。


image.png

再设置 BEEP_CSR1 MSR位。接下来是定时器捕获。

char measureFlag = 0;
long lsiFreq = 0;
char count = 0;

//校正LSI误差引起AWT不准的问题
long measureLSI()
{
  
  //利用BEEP 蜂鸣器寄存器和time2 来测试LSI的频率
  
  //1.打开蜂鸣器时钟,选择时钟为LSI
  CLK_PCKENR1_bit.PCKEN16 = 1;
  CLK_CBEEPR_bit.CLKBEEPSEL0 = 1;
  CLK_CBEEPR_bit.CLKBEEPSEL1 = 0;  //01 选择 LSI
  
  //连接到TIM2, ICAP1  测量
  BEEP_CSR1_bit.MSR = 1;
  
  //初始化TIM2
  CLK_PCKENR1_bit.PCKEN10 = 1; //使能时钟
  
  TIM2_CR1_CEN = 0;  //关闭
  TIM2_CCER1_bit.CC1E = 0;  //使不能捕获
  TIM2_CR1_URS=1;//仅当计数器溢出时才发生中断请求, 为0时可能有其他情况
  TIM2_CR1_UDIS=1;//禁止更新事件//计数器溢出属于更新事件
  
  TIM2_CR1_DIR = 0;  //加法计数器
  TIM2_CR1_ARPE = 0;  //不通过预装载寄存器

  
  //设置捕获模式
  TIM2_CCMR1_bit.CC1S = 1;  // CC1 channel is configured as input, IC1 is mapped on TI1FP1
  TIM2_CCER1_bit.CC1P = 0; //上升沿触发
  TIM2_IER_bit.CC1IE = 1;  //使能捕获中断
  
  TIM2_SMCR_bit.TS = 5;
  TIM2_SMCR_bit.SMS = 4;
  
  TIM2_CCER1_bit.CC1E = 1;  //使能捕获
  TIM2_CR1_CEN = 1;  //开启
  
  //等待测量完成、关闭TIM2  BEEP
  while(measureFlag == 0);
  CLK_PCKENR1_bit.PCKEN10 = 0; //使能时钟
  TIM2_CR1_CEN = 0;
  TIM2_CCER1_bit.CC1E = 0;
  
  BEEP_CSR1_bit.MSR = 0;
  CLK_PCKENR1_bit.PCKEN16 = 0;
  
#ifdef DEBUG
  printf("LSI_FREQ=%ld\n", lsiFreq);
#endif
  
  return lsiFreq;
}

#pragma vector=TIM2_CAPCOM_CC1IF_vector
__interrupt void TIM2_CAPCOM_CC1IF_ISR (void)

{

   if(TIM2_SR1_CC1IF == 1)
   {
     TIM2_SR1_CC1IF = 0;//清除中断标志位

     unsigned int ccr1 =  TIM2_CCR1H;

     ccr1 <<= 8;
     ccr1 += TIM2_CCR1L;
     
     //ccr1得到的时间为整个周期的时间, 包括波峰、波谷
     //主时钟数为16M  16M 除以 单个周期的时间  就是  测出来的频率
      lsiFreq = HSI_FREQ / ccr1;
    
      //关中断,否则程序跑不下去
      count++;
      if(count >= 10)
      {
        measureFlag = 1;
        TIM2_IER_bit.CC1IE = 0;
      }
   }
}

多测几次会准一点。也可以多测几次取均值

你可能感兴趣的:(stm8L测量LSI频率,提高AWT精度,解决LSI误差的问题)