狗啃模拟 发表于 2022-10-18 23:47

mm32f0010 mm32f0020 测LSI时钟频率

可以看到这个种方法可以精确到小数点后一位

本方法主要思想为用正常的定时器测得准确的时间,然后用准确的时间,根据看门狗定时器时间计算公式反推频率
代码写的太乱仅写出主要代码

正常的定时器中断设置 由于我采用2分频来计算时间所有一个周期肯定是不够的所以我们把每次定时器溢出的次数加起来

狗啃模拟 发表于 2022-10-18 23:48

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
    {
      time_num++;//定时器溢出计数
    }
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除中断标志位
}


void WWDG_IWDG_IRQHandler(void)
{
   
// static u16 iii;


//    printf("%d ",IWDG->SR);

TIM_Cmd(TIM3,0);//关掉定时器读取定时器的值
   
      if(IWDG->SR){//由于我配置的这个看门狗中断会连续进入两次所以给了个判断实际用处不大可以删除

//    if(++iii==2)
//    {
      iii = 0;
    LSI_HZ= TIM3->CNT;//读取定时器的值
    TIM3->CNT= 0;    //定时器数据清0
    TIM_Cmd(TIM3,1);
      
//    }
}
               
    EXTI_ClearFlag(EXTI_Line17);
    IWDG_WriteAccessCmd(0x5555);
    IWDG->CR |= 0x02;
    IWDG->KR = 0xAAAA;
//   

}

狗啃模拟 发表于 2022-10-18 23:49

看门狗配置
void Iwdg_Irq_ON(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;

    EXTI_DeInit();
    EXTI_StructInit(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line = EXTI_Line17 ;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt ;
    EXTI_InitStructure.EXTI_Trigger =   EXTI_Trigger_Rising_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    EXTI_ClearITPendingBit(EXTI_Line17);

    NVIC_InitStructure.NVIC_IRQChannel = WWDG_IWDG_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


#define IWDG_FLAG_IVU               ((uint16_t)0x0004)
void IVU_CheckStatus(void)
{
    while(1) {
      if(IWDG_GetFlagStatus(IWDG_FLAG_IVU) == RESET) {
            break;
      }
    }
}
void Write_Iwdg_ON(u16 IWDG_Prescaler, u16 Reload)
{
    RCC_LSICmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

    PVU_CheckStatus();
    IWDG_WriteAccessCmd(0x5555);
    IWDG_SetPrescaler(IWDG_Prescaler);

    RVU_CheckStatus();
    IWDG_WriteAccessCmd(0x5555);
    IWDG_SetReload(Reload & 0xfff);

    IVU_CheckStatus();
    IWDG_WriteAccessCmd(0x5555);
    IWDG->IGEN = 0x50;

    IWDG_ReloadCounter();
    IWDG_WriteAccessCmd(0x5555);
    IWDG->CR |= 1;
    IWDG_Enable();
}

void PWR_STOP_iwdg_Init(void)
{
    u16 i;
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWREN, ENABLE);
//    deleyNop(10000);
//    for(i = 0; i < 10; i++) {
//      LED1_TOGGLE();
//      deleyNop(1000);
//    }
    Iwdg_Irq_ON();
    Write_Iwdg_ON(IWDG_Prescaler_4, 2500+0x50);//计算方法 time = Reload/40000*IWDG_Prescaler   s


}


void my_delay_ms(u16 m)    ;
u16 low=0;


int main(void)
{GPIO_InitTypeDefGPIO_InitStructure;
    u16 time_y;
      float HZ;
    //mco输出LSI时钟 PA7迎角
      RCC_LSICmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_SYSCFG, ENABLE);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig( GPIOA, GPIO_PinSource7, GPIO_AF_3);
    RCC_MCOConfig(RCC_MCO_LSI);
   
    USART1_Init();

    time_x = 2; //用处不大可以删除
    time_y = time_x; //用处不大可以删除
    PWR_STOP_iwdg_Init();

    TIM3_Int_Init(0xffff-1,time_y-1);//2分频
    printf("ok");
   
    while(1)
    {
      if(LSI_HZ!=low )//频率不同时重新计算 实际用处不大可以删除
      {
            HZ=48000000/time_y;//得到分频频率
            HZ=(LSI_HZ+0xffff*time_num)/HZ; //实际时间
            time_num = 0;//定时器溢出计数
            printf("%f",HZ);//输出实际时间      
            HZ =4/HZ*2500;//得到实际时间按看门狗公式反推频率
            printf("   %.2f\r\n",HZ);//输出实际频率
      low =LSI_HZ ;
      }
//    printf("%d ",aaa);
//      my_delay_ms(1000);
    }
}
页: [1]
查看完整版本: mm32f0010 mm32f0020 测LSI时钟频率