qigui2 发表于 2007-10-20 10:18:59

利用icp捕捉测频的问题

我看了马老师的11章的实战练习的icp测频的方法,结合自己的问题编写了测频程序,可总有问题,查了半天也不知道哪错了。因为外围电路有限,无法输出所测得频率,所以我利用T0口ctc模式产生所测得频率的方波,来检测测频的正确与否。我的问题是无论给什么频率的信号,输出总是20kHz的信号。我测频的范围大概在50KHz到100KHz之间,比如100KHz,我用1MHz对其捕捉,一个周期只能计10个,所以我计64个周期,共640个,这样为了准确些。程序如下:
//ICC-AVR application builder : 2007-10-19 15:44:21
// Target : M48
// Crystal: 1.0000Mhz

#include <iom48v.h>
#include <macros.h>
unsigned int icp_v1,icp_v2;
char icp_n;
int icp_ok;
void port_init(void)
{
PORTB = 0x01;
DDRB= 0x00;
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0x00;
DDRD= 0x40;
}

//TIMER1 initialize - prescale:1
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x00 /*INVALID SETTING*/; //setup
TCNT1L = 0x00 /*INVALID SETTING*/;
OCR1AH = 0x00 /*INVALID SETTING*/;
OCR1AL = 0x00 /*INVALID SETTING*/;
OCR1BH = 0x00 /*INVALID SETTING*/;
OCR1BL = 0x00 /*INVALID SETTING*/;
ICR1H= 0x00 /*INVALID SETTING*/;
ICR1L= 0x00 /*INVALID SETTING*/;
TCCR1A = 0x00;
TCCR1B = 0xC1; //start Timer
}

#pragma interrupt_handler timer1_capt_isr:11
void timer1_capt_isr(void)
{
//timer 1 input capture event, read (int)value in ICR1 using;
if (icp_n >= 64)   // 第N个上升沿到
    {
      icp_v2 = ICR1;      // 记录第N个上升沿时间
      TIMSK1 = 0x00;       // 禁止T/CI输入捕捉和溢出中断
      icp_ok = 1;
    }
    else if (icp_n == 0)
    {
      icp_v1 = ICR1;      // 记录第1个上升沿时间
    }   
    icp_n++;   

}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();

MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;

TIMSK0 = 0x00; //timer 0 interrupt sources
TIMSK1 = 0x20; //timer 1 interrupt sources
TIMSK2 = 0x00; //timer 2 interrupt sources

PCMSK0 = 0x00; //pin change mask 0
PCMSK1 = 0x00; //pin change mask 1
PCMSK2 = 0x00; //pin change mask 2
PCICR = 0x00; //pin change enable
PRR = 0x00; //power controller
SEI(); //re-enable interrupts
//all peripherals are now initialized
icp_n = 0;
}
//
void main(void)
{
long fv;
unsigned int icp_2;
init_devices();
//insert your functional code here...
icp_ok=0;
while(1)
{
if (icp_ok == 1)    // 完成一次测量
                {
                                if (icp_v2 >= icp_v1)          // 计算N个上升沿的时钟脉冲个数,
                                    icp_2 = icp_v2 - icp_v1;   
                                else
                                    icp_2 = 65536 - icp_v1 + icp_v2;
                               
                                fv=1000000*(long)64/icp_2;   // 换算成频率值
                                TCCR0B = 0x00; //stop
                                    TCNT0 = 0x00;
                          TCCR1B=0x00;
                                OCR0A=(int)(1000000/(2*fv)-1);
                                TCCR0A=0x42;
                                TCCR0B=0x01;
                }
                               
        }                       

}
我的问题是无论给什么频率的信号,输出总是20kHz的信号,这是什么原因呢?
谢谢大家的帮助

machao 发表于 2007-10-20 21:19:23

你真的看懂了我的例子?

我的例子可以测试62.5hz到128K的频率,连误差分析都给出了。

qigui2 发表于 2007-10-21 10:37:07

首先感谢马老师的解答,把我分析问题的重点引导到误差方面,第一次没有认真分析误差,看了之后我认为我所测得100KHz的周期为10us,晶振1MHz无分频,由于捕捉64次所以测量绝对误差为正负1us/64,那么测量误差为9.984375~10.015625us,对应的频率为99.84KHz~100.156KHz,这样不应该产生那么大的误差阿??还有我知道书中的程序是测试62.5hz到128K的频率,可我这里只需要测100KHz左右的,所以无需量程转换。

machao 发表于 2007-10-21 13:14:49

先彻底弄懂我的例子,然后照搬,看能不能测100K的频率。接下来进行改动,以适合你的需要。

qigui2 发表于 2007-10-21 14:31:46

谢谢马老师,例子我以弄懂,可因为外围电路有限,无法照搬您的程序,所以只能按改动的这个程序来,可问题不知道出在哪?输出总是固定频率。而且还有直流成分,这是什么原因呢?
再次感谢

fuanzwg 发表于 2007-10-21 14:58:40

TCCR1B=0x00;去掉试试看

qigui2 发表于 2007-10-21 15:09:37

fuanzwg TCCR1B=0x00;去掉试试看
能解释一下么?为什么要去掉?
还有我测得信号后输出的方波怎么会有直流分量呢?

machao 发表于 2007-10-21 20:52:10

看样子你需要买一块AVR-51多功能板了,它可以帮助你进行产品的前期设计、测试和验证。就你目前的水平,还不具备直接上产品系统的能力。

我现在设计产品过程中,也是经常先在AVR-51板上测试和验证关键的算法和程序功能段的。

qigui2 发表于 2007-10-22 08:37:53

谢谢马老师的建议,可是我现在没那个条件,只能自己焊焊了,所以很多外部干扰无法排除,而且atmega48没有仿真软件支持(除avr自己的那个,但功能太小),所以只能在我焊的一个最小系统上试验,我的问题我大概已经明白,虽然大家没给出答案,但多少给了我一些方向,谢谢大家。我的系统只能测5k-18k之间的频率,原因就是捕获中断指令太多,而且1MHz的主频又太慢,所以中断执行时间太长,如果测的频率太高,已超出下一次捕获中断来到的时间了,所以就出问题了。

machao 发表于 2007-10-22 13:40:01

你不能放弃,要加油!

M48可以工作到8M:内部的RC为8M,将1/8的分频标志熔丝位禁止就可以了。通过做这个东西,同时把AVR基本的应用掌握好。

qigui2 发表于 2007-10-22 16:14:53

呵呵,上午已经搞定了。谢谢马老师,和你说的一样不要8分频了。现在的范围在20KHz到150KHz,对原程序进行了修改可以实时更新所测得频率,已经基本满足指标的要求了。
    还有再次感谢马老师,我接触avr不到三个礼拜,原来51单片机也是略知皮毛,多多感谢论坛和网站给我的帮助使我快速入门。

machao 发表于 2007-10-22 17:08:36

祝贺一下。希望能坚持,并打好基础。一旦有了一定的实践积累,你的水平就会有大的飞跃。

liangws201 发表于 2012-5-23 17:13:11

谢谢,马老师。

371278638 发表于 2012-6-2 23:41:48

谢谢,学习了!
页: [1]
查看完整版本: 利用icp捕捉测频的问题