OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 18132|回复: 28

我用定时器捕获来测频率,高频倒是挺准的,低频为什么不准呢?

[复制链接]

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
发表于 2012-9-3 10:15:18 | 显示全部楼层 |阅读模式
我把定时器的PSC设为0,也就是72M频率。

arr设为最大0XFFFF。然后进行捕获下降沿

从  TIM2->CCR1;TIM2->CCR2  分别读出方波的周期和占空比

再进行计算。60KHZ的误差较小,实测为60150,误差在我的允许范围内。

就是低到1KHZ就不行了,应该是重载溢出了。这怎么解决呢
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-9-3 10:17:08 | 显示全部楼层
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 10:21:25 | 显示全部楼层
实际可以测到400-60K。误差小于0.5%。再想往高,往低测就测不到了
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 10:30:51 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
怎么个溢出处理?
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-3 10:55:37 | 显示全部楼层
回复【4楼】a546924171:
---------------------------------
。。。。计溢出了多少次。。。。
if一个定时器的溢出中断就可以了。
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 12:08:21 | 显示全部楼层
回复【5楼】lsj9383:
---------------------------------
回复【5楼】lsj9383:
---------------------------------
是啊,我是计数溢出中断的。测高频的时候计数器又不会溢出。可是计算的不对
if(TIM2->SR&0X0001)//溢出中断
{
OV_count++;
if(OV_count>100)
{
OV_count=0;
}
}
TIM2->SR&=~(1<<0);//清除中断标志位  
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-3 12:44:59 | 显示全部楼层
是不是换算成时间的时候有点问题?
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 14:01:19 | 显示全部楼层
回复【7楼】lsj9383:
---------------------------------
我计算溢出和捕获是用同一个定时器。这样可以吗?

我的频率是24M,重载值是65535.

所以我计算的是   频率=24M/(捕获时测的TIM2->CCR1+65535*溢出的次数)

这样应该对吧?
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-3 16:15:03 | 显示全部楼层
嗯..可以是同一个定时器
嗯...你直接就用第一次捕获的时间了吗....我感觉应该用两次捕获的时间相减才可以算吧....
因为不知道单片机开始工作的时候,波处于什么状态。
除非你那个波是单片机自己发出的....
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 16:23:34 | 显示全部楼层
回复【9楼】lsj9383:
---------------------------------
我是测一个方波的两个下降沿之间的时间,求出频率的。频率精确度还在我的允许范围之内,

就是溢出中断,我在溢出中断里设置了一个变量,用变量计溢出次数。然后在低频段可以了。

但是频率加高,就不会溢出了,可是计数变量却怎么清不掉。导致了频率计算错误
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-3 17:55:27 | 显示全部楼层
回复【10楼】a546924171:
---------------------------------
。。。。不是吧,为啥会清不掉....
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 18:24:20 | 显示全部楼层
回复【11楼】lsj9383:
---------------------------------
因为在低频时定时器会溢出,然后计数溢出次数。

在高频时候,捕获定时器也会溢出。这样溢出次数就乱掉了

不懂怎么弄啊,- -
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-3 19:00:25 | 显示全部楼层
高频溢出的原因是什么呢
是正常溢出的话 照样可以算时间啊,
捕获到了就暂时把定时器给停了嘛、
计算完频率后把该清理的变量给清理了,再打开定时器啊?
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-3 21:10:53 | 显示全部楼层
回复【13楼】lsj9383:
---------------------------------
我也是按这个流程想的,你看看我的中断程序,对不

//定时器2中断服务程序  
void TIM2_IRQHandler(void)
{                  
    //捕获处理
    if(TIM2->SR&0X0002)
    {
if(cap_flag==0)
{
LED1=!LED1;
TIM2->CR1&=0x00;    //关闭定时器2
OV_count=0;
    IC1Value=TIM2->CCR1; 
    Frequency = 24000000/(IC1Value);
cap_flag=0;
TIM2->CR1|=0x01;    //使能定时器2
}
if(cap_flag==1)
{
LED0=!LED0;
TIM2->CR1&=0x00;    //关闭定时器2
    IC1Value=TIM2->CCR1; 
    Frequency = 24000000/(IC1Value);
OV_count=0;
cap_flag=0;
TIM2->CR1|=0x01;    //使能定时器2
}
TIM2->SR&=~(1<<1);//清除中断标志位
    }
if(TIM2->SR&0X0001)//溢出中断
{
OV_count++;
cap_flag=1;
TIM2->SR&=~(1<<0);//清除中断标志位 
}
}
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-4 08:51:59 | 显示全部楼层
嗯...感觉上....怎么是一捕捉到就会进行算频率的处理啊,因为 cap_flag=多少都会算Frequency....
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-4 09:04:43 | 显示全部楼层
回复【15楼】lsj9383:
---------------------------------
捕获到了说明这方波的一个周期结束了,所以进行计算

捕获到了先判断是不是有溢出过,没溢出过就说明是较高频率的,把定时器关掉,防止定时器溢出,然后计算

如果是溢出过的,说明是低频信号,计算出溢出次数,再计算。可是这样还是不行
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-4 09:05:14 | 显示全部楼层
回复【15楼】lsj9383:
---------------------------------
谢谢啊,跟帖跟那么多次,我都不好意思
回复 支持 反对

使用道具 举报

18

主题

158

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
400
金钱
400
注册时间
2011-11-23
在线时间
0 小时
发表于 2012-9-4 09:26:49 | 显示全部楼层
回复【17楼】a546924171:
---------------------------------
首先,不要配置从模式控制器在捕获成功时复位计数器,这样就不会在收到捕获中断的同时出现溢出中断。

其次,你需要把ARR参数配置为其最大值0xFFFF,这样可以得到最少的溢出中断。

这样配置后,如果在中断程序中发现捕获中断与溢出中断同时出现,则可能有下述两种情况:
1)捕获中断先于溢出中断出现:此时读出的捕获数值CCR应该是一个接近0xFFFF的数值,这样测量的周期就是(溢出中断累计次数*0x10000+CCR)。
2)捕获中断晚于溢出中断出现:此时读出的捕获数值CCR应该是一个接近于0的数值,这样测量的周期就是((溢出中断累计次数+1)*0x10000+CCR)。
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-4 10:54:28 | 显示全部楼层
回复【17楼】a546924171:
---------------------------------
嗯...没关系,我也是刚入门而已~
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-4 22:28:40 | 显示全部楼层
回复【18楼】shuilian007:
---------------------------------
很奇怪,我仿真测试,

方波来的第一个上升沿,不管是高频还是低频都会检测到。

然后为什么高频信号也会先溢出,然后又捕获到。

按道理应该是,连续捕获到两次再溢出才对啊
回复 支持 反对

使用道具 举报

50

主题

207

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
427
金钱
427
注册时间
2012-7-21
在线时间
0 小时
 楼主| 发表于 2012-9-4 22:59:50 | 显示全部楼层
回复【20楼】a546924171:
---------------------------------
这是我的配置程序
int  main(void)
{
        Stm32_Clock_Init(9); //系统时钟设置
        delay_init(72);//延时函数初始化 
        uart_init(72,9600);
        Capture_Init(0xffff,0);    //设2,三分频,65535溢出。可以测370HZ以上。
        LED_Init();
        while(1)
        {
//                Frequency = 24000000/(IC1Value+OV_count*65535);
                DutyCycle = (IC2Value*100)/IC1Value;//占空比=(IC2Value/IC1Value)*100;
                printf("Frequency = %d\r\n",Frequency);
//                printf("DutyCycle = %d\r\n",DutyCycle); 
        }
}


void Capture_Init(u16 arr,u16 psc)
{
        //此部分需手动修改 IO口设置  
        RCC->APB2ENR|=1<<0;    //  
        RCC->APB1ENR|=1<<0;       //TIM2 时钟使能 
        RCC->APB2ENR|=1<<2;    //使能PORTA时钟 
        
        TIM2->ARR=arr;  //设定计数器自动重装值//刚好1ms    
        TIM2->SC=psc;  //预分频器,

        GPIOA->CRL&=0XFFFFFFF0;//PA0 输出  
        GPIOA->CRL|=0X00000004;//复用功能输出       
        GPIOA->ODR|=1<<0;//PA0 上拉
        
//        TIM2->SMCR|=0x0040; 
        TIM2->CCMR1|=1<<0;//CC1S=01 选择输入端 
        TIM2->CCER|=0<<1; //CC1P=0 选择有效转换边沿  上升沿有效
        TIM2->CCMR1|=0<<2; //IC1PS=00 配置输入分频 无预分频器,捕获输入口上检测到的每一个边沿都触发一次捕获
        TIM2->CCMR1|=0<<4; //IC1F=0011配置输入滤波器


        TIM2->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
        TIM2->DIER|=1<<1;   //允许更新捕获中断 
        TIM3->DIER|=1<<0;   //允许更新中断                                
//        TIM3->DIER|=1<<6;   //允许触发中断           
        TIM2->CR1|=0x01;    //使能定时器2
        MY_NVIC_Init(1,3,TIM2_IRQChannel,2);//抢占1,子优先级3,组2          
}

u32   OV_count=0;
u32   cap_count;
u32   old_cap=0;
u32   new_cap=0;
u32   cap_diff=0;

//定时器2中断服务程序  
void TIM2_IRQHandler(void)
{                  
        //捕获处理
    if(TIM2->SR&0X0002)
    {
                TIM2->SR&=~(1<<1);//清除中断标志位      
        if(1==cap_count)        //捕获频率
        {        
                OV_count=0;
                old_cap=TIM2->CCR1;       
        }
        else if(cap_count>10)
        {
                new_cap=TIM2->CCR1;
                cap_diff=new_cap-old_cap+65535*OV_count;                        
                Frequency=720000000/cap_diff;//这里72000000*10是对10次捕获求平均值
                cap_count=0;
                OV_count=0;
        }
            cap_count++;                
    }
        if(TIM2->SR&0X0001)//溢出中断
        {
                OV_count++;
                TIM2->SR&=~(1<<0);//清除中断标志位      
        }
}

回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2012-9-5 12:55:57 | 显示全部楼层
GPIOA->CRL&=0XFFFFFFF0;//PA0 输出   
GPIOA->CRL|=0X00000004;//复用功能输出

我建议将此位改成输入 改成8.......      
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2013-12-14
在线时间
0 小时
发表于 2013-12-16 21:52:56 | 显示全部楼层
   这个问题我最近解决了,在定时器前预分频下就行了,还有,我们老师说,高频有上限,但低频肯定测得了的
回复 支持 反对

使用道具 举报

4

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2014-6-18
在线时间
1 小时
发表于 2014-7-3 11:21:57 | 显示全部楼层
回复【23楼】孙磊:
---------------------------------
请问你是直接进行预分频的吗,为什么我进行了预分频后直接就检测不到频率了,高频也检测不到了
回复 支持 反对

使用道具 举报

4

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2014-11-13
在线时间
0 小时
发表于 2014-12-15 09:48:28 | 显示全部楼层
求楼主发一份资料x45v@qq.com,小弟感激不尽
回复 支持 反对

使用道具 举报

0

主题

19

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2015-5-13
在线时间
1 小时
发表于 2015-5-20 09:00:49 | 显示全部楼层
回复【14楼】a546924171:你的F 是什么型的?
---------------------------------
回复 支持 反对

使用道具 举报

12

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2015-1-12
在线时间
14 小时
发表于 2015-7-31 14:06:49 | 显示全部楼层
回复【3楼】a546924171:
---------------------------------
楼主可以共享一下最后调试低频测量成功的代码吗,才入门,对定时器的一些操作不清楚,想学习一下经验,或者直接发QQ:1321939226@qq.com也行
回复 支持 反对

使用道具 举报

Y123Y 该用户已被删除
发表于 2016-4-21 21:18:04 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

9

主题

63

帖子

0

精华

高级会员

Rank: 4

积分
567
金钱
567
注册时间
2017-7-27
在线时间
99 小时
发表于 2018-4-22 22:14:19 | 显示全部楼层
a546924171 发表于 2012-9-3 21:10
回复【13楼】lsj9383:
---------------------------------
我也是按这个流程想的,你看看我的中断程序,对 ...

是不是数据类型的问题
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 01:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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