搜索
bottom↓
回复: 20

avr T1定时器捕获功能测评率

[复制链接]

出0入0汤圆

发表于 2012-7-5 16:44:18 | 显示全部楼层 |阅读模式
/*主函数*/
#include <iom16v.h>
#include <macros.h>
#include "12864.h"
#include "delay.h"

#define uint unsigned int
#define uchar unsigned char

uint Cnt1;                             //第一次捕获值
uint Cnt2;                           //第二次捕获值
uint Cnt;                   //捕获差值
uchar Flag=0;                   //捕获次数
uchar Data[6]={0,0,0,0,0,0};//显示初值,最后一个0是结束符,方便液晶显示
void init_timer1(void)                          //初始化T/C1的输入捕获中断
{
DDRD=0x00;
PORTD=0xff;//设置D口为带上拉电阻输入       
TCCR1A = 0;//设值为普通模式
TCCR1B |= (1 << ICNC1)|(1 << CS11);///输入捕获噪声抑制使能,下降沿触发,1/8分频
TIMSK |= (1 << TICIE1);//输入捕捉中断使能
SREG=0x80;        //打开总中断
                               

}

void hz(uint i,uchar *p)                 //显示处理,+48是因为液晶显示的是ASCII码
{p[4]=i%10;//个
p[3]=i%100/10;//十
p[2]=i%1000/100;//百
p[1]=i%10000/1000;//千
p[0]=i/10000;//万

}

void main()
{
uint t;
port_init();
init_timer1();       
lcd_init();
lcd_clr();
while(1);
}


#pragma interrupt_handler timer1_capt:6
void timer1_capt(void)
{
        Cnt2=(ICR1H<<8)+ICR1L;           //cnt2存放点前捕获值
        Cnt=Cnt2-Cnt1;                           //cnt存放两次时间差
        Cnt1=Cnt2;                                   //cnt1存放上次捕获值
        Flag++;       
        if(Flag==2)
         {
        Flag=0;                                   //清除捕获标志位
        hz(Cnt,Data);                           //显示处理
        Lcd_DisplayOnenum(1,1,Data);                 //显示
        Cnt=0;Cnt1=0;Cnt2=0;                //清除捕获值几捕获差值
         }
}

我用AVR16 的T1定时器的捕获功能做测频计测频率时,不能正常工作,我的外接信号是信号发生器发出的方波,当我把频率调大时12864显示的频率减小。并且显示的频率与我给的方波的频率差别很大,这个问题我弄了好久都没解决,请高手们指点一下,谢谢了!!!

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-7-6 00:32:54 | 显示全部楼层
本帖最后由 thomascao 于 2012-7-6 00:49 编辑

Cnt 你没换算成频率,是被测量频率的周期,所以你测量的频率越高,显示的值越小,换算下就好了。
另你没考虑T1溢出问题,帮你在程序里提出了。(如你测量频率周期小于(频率大于)T1溢出范围,那就不用加了)


/*主函数*/
#include <iom16v.h>
#include <macros.h>
#include "12864.h"
#include "delay.h"

#define uint unsigned int
#define uchar unsigned char

//uint Cnt1;                             //第一次捕获值
//uint Cnt2;                           //第二次捕获值
//uint Cnt;                   //捕获差值

unsigned long int Cnt1; //*************************考虑溢出,不考虑溢出可不修改
unsigned long int Cnt2; //*************************考虑溢出,不考虑溢出可不修改
unsigned long int Cnt;  //**************************考虑溢出,不考虑溢出可不修改

uchar Flag_OVF=0;  //****************************溢出次数计数,不考虑溢出可不修改

uchar Flag=0;                   //捕获次数
uchar Data[6]={0,0,0,0,0,0};//显示初值,最后一个0是结束符,方便液晶显示
void init_timer1(void)                          //初始化T/C1的输入捕获中断
{
DDRD=0x00;
PORTD=0xff;//设置D口为带上拉电阻输入        
TCCR1A = 0;//设值为普通模式
TCCR1B |= (1 << ICNC1)|(1 << CS11);///输入捕获噪声抑制使能,下降沿触发,1/8分频
TIMSK |= (1 << TICIE1);//输入捕捉中断使能
TIMSK |= (1 << TOIE1);   //T1溢出中断使能,********************不考虑溢出可不修改

//SREG=0x80;        //打开总中断 *********************放到main()中,等所有初始化结束后开
                                

}

void hz(uint i,uchar *p)                 //显示处理,+48是因为液晶显示的是ASCII码

{p[4]=i%10;//个
p[3]=i%100/10;//十
p[2]=i%1000/100;//百
p[1]=i%10000/1000;//千
p[0]=i/10000;//万

}

void main()
{
uint t;
port_init();
init_timer1();        
lcd_init();
lcd_clr();
SREG=0x80;        //打开总中断  **************************
while(1);
}

#pragma interrupt_handler T1_OVF:10 //T1 溢出中断  
void T1_OVF (void)
{
  if( Flag_OVF<?? )   //累计溢出次数,超出频率测量范围处理,自己编下******************
     {
        Flag_OVF++;
    }
else
   {
      Flag=0;                                   //清除捕获标志位
    Cnt=0;Cnt1=0;Cnt2=0;                //清除捕获值几捕获差值
    Flag_OVF=0; //溢出记数清除
    TIFR |=( 1 << ICF1 );// 清除捕获中断标记
    // 再加LCD显示 测量频率超出测量范围
   }
  }


#pragma interrupt_handler timer1_capt:6
void timer1_capt(void)
{
//        Cnt2=(ICR1H<<8)+ICR1L;           //cnt2存放点前捕获值
        cnt2=(ICR1H<<8)+ICR1L+ Flag_OVF * 65536  ;
            Cnt=Cnt2-Cnt1;                           //cnt存放两次时间差  
        //***Cnt 这你没换算成频率,这是你测量频率的周期,换算下,所以你测量的值频率越高,显示的值越小。
        //****************************************************
            Cnt1=Cnt2;                                   //cnt1存放上次捕获值
        Flag++;        
           if(Flag==2)
              {
                 Flag=0;                                   //清除捕获标志位
            hz(Cnt,Data);                           //显示处理
            Lcd_DisplayOnenum(1,1,Data);                 //显示
            Cnt=0;Cnt1=0;Cnt2=0;                //清除捕获值几捕获差值
            Flag_OVF=0;
                }
}

出0入0汤圆

 楼主| 发表于 2012-7-6 21:31:16 | 显示全部楼层
太谢谢你了,我刚学AVR对你面的寄存器用的并不熟,所以遇到好多问题,幸亏有你们这些高手,谢谢啊!!!

出0入0汤圆

 楼主| 发表于 2012-7-6 21:44:21 | 显示全部楼层
如果我想测正弦波的频率时,是不是要将正玄波转换成方波然后再用这种方法来测量

出0入0汤圆

发表于 2012-7-6 23:46:22 | 显示全部楼层
qq1328454800 发表于 2012-7-6 21:44
如果我想测正弦波的频率时,是不是要将正玄波转换成方波然后再用这种方法来测量 ...

模拟比较器+捕获

出0入0汤圆

 楼主| 发表于 2012-7-7 10:07:55 | 显示全部楼层
当我测量方波的频率上兆时第一个下降沿到来时开始计数,当第二个下降沿到来时程序就进入if(Flag==2)
              {
                 Flag=0;                                   //清除捕获标志位
            hz(Cnt,Data);                           //显示处理
            Lcd_DisplayOnenum(1,1,Data);                 //显示
            Cnt=0;Cnt1=0;Cnt2=0;                //清除捕获值几捕获差值
            Flag_OVF=0;
                }
的Lcd_DisplayOnenum(1,1,Data);   显示中 正在执行时,又来了一个下降沿,此时程序还会进入中断,这样不就影响lcd显示吗?  

出0入0汤圆

 楼主| 发表于 2012-7-7 11:14:50 | 显示全部楼层
我用的是内部8M晶振,八分频,理论值测得的最大频率为1M,为什么我用着程序最大只能测35K,并且误差比较大,数据处理我用的是unsigned long int plv;
plv=1000000/i;
p[4]=plv%10;//个
p[3]=plv%100/10;//十
p[2]=plv%1000/100;//百
p[1]=plv%10000/1000;//千
p[0]=plv/10000;//万
函数???

出0入0汤圆

发表于 2012-7-8 04:41:07 | 显示全部楼层
qq1328454800 发表于 2012-7-7 10:07
当我测量方波的频率上兆时第一个下降沿到来时开始计数,当第二个下降沿到来时程序就进入if(Flag==2)
       ...

是个问题,不过不是你担心的问题,是测量频率不准的问题。
由于描述起来很绕,我假设你的程序经过2次捕获中断,已经测量出频率值了,你在第2次捕获中断中进行频率计算并LCD显示当前测量到的频率。
但这时又来了新的一个频率信号,这样又将产生第3个捕获中断,但注意你处理 LCD显示当前测量到的频率 的程序是在捕获中断(既第2个捕获中断)里的,
由于进入中断后,全局中断被关闭,这样第3个捕获中断将不会立即执行,程序会在显示完LCD处理完当前中断里的其他操作正常退出中断并打开全局中断,
这时才进入第3个捕获中断,这样频率测量就不准了。
处理方法是在已经测量出频率并LCD显示中断退出时将TIFR寄存器中的ICF1清零( TIFR |=(1<<ICF1 ),舍弃在计算或显示中产生的捕获中断。

#pragma interrupt_handler timer1_capt:6
void timer1_capt(void)
{
//        Cnt2=(ICR1H<<8)+ICR1L;           //cnt2存放点前捕获值
        cnt2=(ICR1H<<8)+ICR1L+ Flag_OVF * 65536  ;
            Cnt=Cnt2-Cnt1;                           //cnt存放两次时间差  
        //***Cnt 这你没换算成频率,这是你测量频率的周期,换算下,所以你测量的值频率越高,显示的值越小。
        //****************************************************
            Cnt1=Cnt2;                                   //cnt1存放上次捕获值
        Flag++;        
           if(Flag==2)
              {
                 Flag=0;                                   //清除捕获标志位
            hz(Cnt,Data);                           //显示处理
            Lcd_DisplayOnenum(1,1,Data);                 //显示
            Cnt=0;Cnt1=0;Cnt2=0;                //清除捕获值几捕获差值
            Flag_OVF=0;          //清除溢出次数
            TIFR |=( 1 << ICF1 );// 清除捕获中断标记
                }
}

出0入0汤圆

发表于 2012-7-8 06:02:01 | 显示全部楼层
qq1328454800 发表于 2012-7-7 11:14
我用的是内部8M晶振,八分频,理论值测得的最大频率为1M,为什么我用着程序最大只能测35K,并且误差比较大 ...

8M 8分频率 =1M哦
你要测量1M信号
T1那才1个数。。。。,并且你使用了噪声抑制,附加了4个系统时钟周期的延迟,所以用测周法这不行了,你用计数法吧

如定时器0.5S,计数下一共有多少个被测量信号,再换算下就可以了。

出0入0汤圆

 楼主| 发表于 2012-7-8 14:15:32 | 显示全部楼层
恩,谢谢啊,我在试一下

出0入0汤圆

发表于 2012-7-8 14:36:31 | 显示全部楼层
1M的信号......液晶来得及刷新吗?

出0入0汤圆

 楼主| 发表于 2012-7-8 15:15:24 | 显示全部楼层
不能了,最大只能测量35K,然后把频率调大显示不变,难道用捕获功能测频率不行吗

出0入0汤圆

发表于 2012-7-8 16:02:43 | 显示全部楼层
低频应该可以,而且准确性很高。高频的话我觉得一个要考虑液晶的刷新率,另外还要考虑时钟(毕竟中断里面的那些语句执行还是要时间的)。所有高频的话,定时器定个时间间隔,然后数脉冲数目吧。

出0入0汤圆

 楼主| 发表于 2012-7-8 17:40:47 | 显示全部楼层
恩,我想应该加一个分频器,把被测的信号分频

出0入0汤圆

 楼主| 发表于 2012-7-8 17:41:52 | 显示全部楼层
忘了谢谢了

出0入0汤圆

发表于 2012-7-8 20:49:37 | 显示全部楼层
qq1328454800 发表于 2012-7-8 15:15
不能了,最大只能测量35K,然后把频率调大显示不变,难道用捕获功能测频率不行吗
...

低频 测周法 高频 计数法

出0入0汤圆

 楼主| 发表于 2012-7-8 21:03:03 | 显示全部楼层
恩,谢谢啊

出0入0汤圆

发表于 2012-8-6 15:00:59 | 显示全部楼层
不错哦,正需要

出0入0汤圆

发表于 2012-12-15 22:47:42 | 显示全部楼层
为什我我按照这个配置进不了中断啊?

出0入0汤圆

发表于 2012-12-16 20:31:54 来自手机 | 显示全部楼层
路过,学习一下

出0入0汤圆

发表于 2013-1-5 21:29:44 | 显示全部楼层
给力的帖子
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 06:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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