firewood2024 2025-03-25 17:07 采纳率: 50%
浏览 26

STM32F103测频法问题

主函数
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "PWM.h"
//#include "Timer.h"
#include "IC.h"
#include "OLED.h"
#include "ICFMM.h"

#define TIM3_CNT     (*(volatile uint32_t *)(TIM3_BASE + 0x24))

 uint32_t frequency = 10;
static uint32_t current_count = 0;    

int main(void)
{
    
    GPIO_TIM3_Init();
    TIM3_Counter_Init();
    TIM4_Init();
     PWM_Init();
     OLED_Init();
    
    
        /*显示静态字符串*/
     OLED_ShowString(1, 1, "Freq:00000Hz");        //1行1列显示字符串Freq:00000Hz
     OLED_ShowString(2, 1, "CNT3:00000Hz");        //1行1列显示字符串Freq:00000Hz
//     OLED_ShowString(2, 1, "Duty:00%");
//     TIM2_SetCompare(30);//PWM设置占空比
     TIM2_SetPrescaler(360-1);   //频率设置 72MHZ/(pres+1)/(ARR+1)
     while(1)
     {
      OLED_ShowNum(1, 6,frequency , 5);    //不断刷新显示输入捕获测得的频率
     // OLED_ShowNum(2, 6, IC_GetDuty(), 2);    //不断刷新显示输入捕获测得的频率
       OLED_ShowNum(2, 6, current_count , 5);         
     }
    
    

    
    
}








void TIM4_IRQHandler(void) 
    {
    static uint16_t  k = 50000;
    
        
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
         

//    读取TIM3的计数值
      

        frequency = TIM_GetCounter(TIM3);
        
        TIM_SetCounter(TIM3, 0);

                
        }
      
        // 清除中断标志
       
 
      TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
    
}


··

#include "stm32f10x.h"                  // Device header






void GPIO_TIM3_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void TIM3_Counter_Init(void) 
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//    TIM_ICInitTypeDef TIM_ICInitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    // 配置PA6为TIM3_CH1输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // TIM3基础配置
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;        // 计数器最大值65535
    TIM_TimeBaseStructure.TIM_Prescaler = 0;          // 无预分频
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

//    // 配置外部时钟模式1(TI1上升沿触发)
//    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
//    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
//    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
//    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//    TIM_ICInitStructure.TIM_ICFilter = 0x0;
//    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    // 配置从模式为外部时钟模式1
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1);
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); // TI1作为触发源

    // 启动TIM3
    TIM_Cmd(TIM3, ENABLE);

}


void TIM4_Init(void) 
    {
   
   
  
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    // TIM4配置为1秒中断(系统时钟72MHz)
    TIM_TimeBaseStructure.TIM_Period = 10000 - 1;     // 自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1;   // 预分频7200,得到10kHz时钟
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    // 使能TIM4更新中断
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

    // 配置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 启动TIM2
    TIM_Cmd(TIM4, ENABLE);
    
    
}






问题是前文给出的函数能正确获得PWM的频率2000HZ,

void TIM4_IRQHandler(void) 
    {
    static uint16_t  k = 50000;
    
        
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
         

//    读取TIM3的计数值
        Delay_ms(50);

        frequency = TIM_GetCounter(TIM3);
        
        TIM_SetCounter(TIM3, 0);
        
        }
      
        // 清除中断标志
       
 
      TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
    
}


我在中断里加50ms依然能测得正确的值即CNT = 2000,液晶显示2000HZ
但是我在它们之间加延时语句,CNT的值就变成了1900即


void TIM4_IRQHandler(void) 
    {
    static uint16_t  k = 50000;
    
        
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
         

//    读取TIM3的计数值
        Delay_ms(50);

        frequency = TIM_GetCounter(TIM3);
         Delay_ms(50);
        TIM_SetCounter(TIM3, 0);
        
    
        }
      
        // 清除中断标志
       
 
      TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
    
}

这是什么原因呢,函数的其它部分是江协科大的代码,好像TIM_SetCounter(TIM3, 0);执行到这句实话的CNT值才是正确的值,但是它又能无视前面的延时,自动得到一个正确的CNT值。 好奇怪问了deepseek,它也觉得不会发生这种情况

img

  • 写回答

5条回答 默认 最新

  • 阿里嘎多学长 2025-03-25 17:07
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    STM32F103测频法问题

    你的问题是关于STM32F103单片机的测频法问题。从你的代码中可以看到,你已经包含了stm32f10x.h头文件,这个头文件提供了stm32f103单片机的相关寄存器定义和宏定义。

    测频法是指使用单片机的时钟信号来测量某个信号的频率。通常情况下,我们可以使用单片机的时钟信号作为参考信号,然后使用计时器来计时测量信号的周期。然后,我们可以根据计时器的计时结果来计算信号的频率。

    在STM32F103单片机中,我们可以使用TIM2计时器来实现测频法。下面是一个简单的示例代码:

    #include "stm32f10x.h"
    #include "Delay.h"
    
    int main(void)
    {
        // 配置TIM2计时器
        TIM2_PSC = 0x00; // 计时器分频器
        TIM2_ARR = 0xFFFF; // 计时器自动重装寄存器
        TIM2_CR1 = TIM_CR1_CEN; // 计时器启用
    
        // 等待计时器启动
        Delay_ms(10);
    
        // 读取计时器的计时结果
        uint16_t timer_value = TIM2_CNT;
    
        // 计算信号的频率
        float frequency = (float)TIM2_PSC * 9000000 / timer_value;
    
        // 打印频率结果
        printf("Frequency: %f Hz\n", frequency);
    
        return 0;
    }
    

    在上面的代码中,我们首先配置了TIM2计时器,然后等待计时器启动。然后,我们读取计时器的计时结果,并根据计时结果计算信号的频率。最后,我们打印出频率结果。

    需要注意的是,这只是一个简单的示例代码,你可能需要根据你的实际情况进行修改和优化。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月25日