搜索
bottom↓
回复: 13

利用icp捕捉测频的问题

[复制链接]

出0入0汤圆

发表于 2007-10-20 10:18:59 | 显示全部楼层 |阅读模式
我看了马老师的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的信号,这是什么原因呢?
谢谢大家的帮助

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2007-10-20 21:19:23 | 显示全部楼层
你真的看懂了我的例子?

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

出0入0汤圆

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

出0入0汤圆

发表于 2007-10-21 13:14:49 | 显示全部楼层
先彻底弄懂我的例子,然后照搬,看能不能测100K的频率。接下来进行改动,以适合你的需要。

出0入0汤圆

 楼主| 发表于 2007-10-21 14:31:46 | 显示全部楼层
谢谢马老师,例子我以弄懂,可因为外围电路有限,无法照搬您的程序,所以只能按改动的这个程序来,可问题不知道出在哪?输出总是固定频率。而且还有直流成分,这是什么原因呢?
再次感谢

出0入0汤圆

发表于 2007-10-21 14:58:40 | 显示全部楼层
TCCR1B=0x00;去掉试试看

出0入0汤圆

 楼主| 发表于 2007-10-21 15:09:37 | 显示全部楼层
fuanzwg TCCR1B=0x00;去掉试试看
能解释一下么?为什么要去掉?
还有我测得信号后输出的方波怎么会有直流分量呢?

出0入0汤圆

发表于 2007-10-21 20:52:10 | 显示全部楼层
看样子你需要买一块AVR-51多功能板了,它可以帮助你进行产品的前期设计、测试和验证。就你目前的水平,还不具备直接上产品系统的能力。

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

出0入0汤圆

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

出0入0汤圆

发表于 2007-10-22 13:40:01 | 显示全部楼层
你不能放弃,要加油!

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

出0入0汤圆

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

出0入0汤圆

发表于 2007-10-22 17:08:36 | 显示全部楼层
祝贺一下。希望能坚持,并打好基础。一旦有了一定的实践积累,你的水平就会有大的飞跃。

出0入0汤圆

发表于 2012-5-23 17:13:11 | 显示全部楼层
谢谢,马老师。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-26 23:18

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

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