找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1593|回复: 7
收起左侧

STM32F103频率采集误差问题

[复制链接]
ID:584195 发表于 2021-8-23 07:49 | 显示全部楼层 |阅读模式
我用stm32F103RC定时器3通道2来采集频率,输入频率为1.8KHZ,测得为2KHZ。用示波器实测也是1.8KHz。程序如下.请问我这程序要怎么改才能采集到正确的数据。需要用运算放大器吗?

/***********************************************************************************************
  //上升沿捕获
************************************************************************************************/
TIM_ICInitTypeDef  TIM3_ICInitStructure;

void TIM3_counter_Init(u16 arr,u16 psc)
{         
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
           NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,  ENABLE);          //使能TIM5时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA时钟
       
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7;              //PA7 清除之前设置  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //PA7 浮空输入  
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_ResetBits(GPIOA,GPIO_Pin_7);                                                              //PA7 下拉
       
        //初始化定时器5 TIM5         
        TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
        TIM_TimeBaseStructure.TIM_Prescaler =psc;         //预分频器   
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        //初始化TIM5输入捕获参数
        TIM3_ICInitStructure.TIM_Channel = TIM_Channel_2;                   //         选择输入端 IC1映射到TI1上
          TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;           //上升沿捕获
          TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
          TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                             //配置输入分频,不分频
          TIM3_ICInitStructure.TIM_ICFilter = 0x00;                                                            //IC1F=0000 配置输入滤波器 不滤波
          TIM_ICInit(TIM3, &TIM3_ICInitStructure);

        TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2); //选择IC2为始终触发源
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//TIM从模式:触发信号的上升沿重新初始化计数器和触发寄存器的更新事件
    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发
       
        //中断分组初始化
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级2级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
       
        TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);//不能允许更新中断 ,允许CC2IE捕获中断       
       
           TIM_Cmd(TIM3,ENABLE);         //使能定时器3

}
/***********************************************************************************************

************************************************************************************************/
u32  counter=0;                                                                           // 每秒计数
int  Frequency=0;

void TIM3_IRQHandler(void)
{
        static int  i =0;
        if (TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)  
    {
      TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);             //清楚TIM的中断待处理位
                        counter = (u32)TIM_GetCapture2(TIM3);               
      Frequency =72000000/counter;
                  printf("当前频率为:%d Hz\r\n",Frequency/7200);       //打印数据                       
                        for(i=0;i<2000000;i++)
                        {         
                                ;
                        }
                       
    }
}


[07:49:19.112]收←◆当前频率为:2000 Hz

[07:49:20.189]收←◆当前频率为:2000 Hz

[07:49:21.266]收←◆当前频率为:2000 Hz

[07:49:22.343]收←◆当前频率为:2000 Hz

[07:49:23.420]收←◆当前频率为:2000 Hz

[07:49:24.497]收←◆当前频率为:2000 Hz

[07:49:25.574]收←◆当前频率为:2000 Hz


回复

使用道具 举报

ID:265988 发表于 2021-8-23 09:14 | 显示全部楼层
是不是小数点没有分离啊
回复

使用道具 举报

ID:584195 发表于 2021-8-23 10:22 | 显示全部楼层
oyyp 发表于 2021-8-23 09:14
是不是小数点没有分离啊

这是整数,没有精确到Khz,单位是Hz按理来讲不会出问题的
回复

使用道具 举报

ID:313048 发表于 2021-8-23 17:05 | 显示全部楼层
首先是不需要用到运放的,首先确定你的定时器中断所取时间是否合理,其次是你在定时器中断里面放那个for循环是完全没有必要的。
回复

使用道具 举报

ID:584195 发表于 2021-8-24 00:34 | 显示全部楼层
AUG 发表于 2021-8-23 17:05
首先是不需要用到运放的,首先确定你的定时器中断所取时间是否合理,其次是你在定时器中断里面放那个for循 ...

谢谢,感谢提示,我更改一下看看。
回复

使用道具 举报

ID:419909 发表于 2021-8-24 08:46 | 显示全部楼层
不要在中断里执行太多命令。一般只在中断里赋值给某个变量。再在主循环打印。
回复

使用道具 举报

ID:584195 发表于 2021-8-24 20:27 | 显示全部楼层
wfqxgw 发表于 2021-8-24 08:46
不要在中断里执行太多命令。一般只在中断里赋值给某个变量。再在主循环打印。

能帮我看看吗,我今天把for去掉了,但是还是采集到2000Hz
回复

使用道具 举报

ID:584195 发表于 2021-8-24 21:04 | 显示全部楼层
我后面看了其他的贴子,抄了一下程序,现在可以采集正确了。
/***********************************************************************************************
* TIM2配置捕获模式
************************************************************************************************/
void TIM2_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  NVIC_InitTypeDef NVIC_InitStructure;
  
  TIM_ICInitTypeDef TIM_ICInitStructure;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA时钟
        
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//TIM2_CH2
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA,&GPIO_InitStructure);


  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  
  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择TIM2—CH2,选择输入端IC2映射到TI2上
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI2上
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //在捕获输入上每控测到一个边沿执行一次捕获
  TIM_ICInitStructure.TIM_ICFilter = 0; //滤波设置,经历几个周期跳变定波形稳定。(采样高电平,只有连续采集到N个电平是高电平时才认为是有效的,否则低于N个时认为是无效的,N取0x0-0xF)
  TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);//以上是输入捕获配置
  TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2); //选择滤波后的TI2FP2输入作为触发源,触发下面程序的复位
  TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);//从模式控制器被设置为复位模式-选中的触发信号上升沿重新初始化计数器并产生一个更新信号(上升沿一到,TIM2->CNT被清零,每次上升沿来到,CNT都会被清零)
  TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);//启动定时器的被动触发
  TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//捕获中断打开
  TIM_Cmd(TIM2,ENABLE);//使能定时器2
}


float Frequency1=0;
float pulse=0;
u32 duty=0;
u16 freq=0;
u8 flag = 0;


void TIM2_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM2,TIM_IT_CC2) == Bit_SET)
  {
    IC2Value=TIM_GetCapture2(TIM2);//获得CCR2的值
    pulse=TIM_GetCapture1(TIM2);//获得CCR1的值
    DutyCycle=pulse/IC2Value;
    Frequency=72000000/IC2Value;
    duty=(u32)(DutyCycle*100);
    freq=(Frequency);

    flag=1;

    TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);

  }
}

当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz
当前频率为:1799 Hz

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表