yqing81 发表于 2009-5-25 20:55:32

移植马潮老师实验—基于T/C1捕捉功能的可变量程频率计的设计与实验,出现奇怪问题!请高

买了马老师的书,业余时间一直在研读,从中也学了不少,在此要感谢马老师!!
由于本人只会WINAVR,不会CAVR开发环境,另外有自己的学习板(非马老师的),做马老师书上的实验我都是结合自己的学习板将程序移植到WINAVR上,在做本实验时,移植时将程序稍有改动,并且外部晶振为8M(熔丝设定正确!!这个无须怀疑。),发现ICP测量显示的频率总是为实际频率的1/2,(即使完全移植马老师的实验程序并且外部晶振为4M,测量的频率也是实际的1/2),直到输入实际频率>8k后,显示频率才正确,研究了好几天没有结果,非常诡异,故请高手帮忙分析问题出在哪,若有幸能被马老师指教那更是件很高兴的事情,在此先感谢大家!!路过的看看并帮帮忙!!
贴上我移植的程序:
/*********************************************
File name                : demo_11_3.c
Chip type         : ATmega16
Program type      : Application
Clock frequency   : 8.000000 MHz
Memory model      : Small
External SRAM size: 0
Data Stack size   : 256
*********************************************/
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

const unsigned char led_7 PROGMEM = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//common+
const unsigned char position PROGMEM = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

unsigned char posit=0;
unsigned char dis_buff={0,0,0,0,0,0,0,0};
unsigned char f_2_d=0;
unsigned char max_icp=1;
volatile unsigned char time_2ms_ok=0,full_ok=0,icp_ok=0;
volatile unsigned char icp_n;
volatile unsigned inticp_v1,icp_v2;


void display(void)
{
PORTC = 0xff;
PORTA = pgm_read_byte(&led_7]);
if(posit==1) PORTA &=0x7f;
PORTC = pgm_read_byte(&position);
if(++posit>7) posit = 0;
}

void freq_to_disbuff(unsigned long freq_temp)
{
unsigned char i;
for(i=0;i<8;i++)
{
   dis_buff=freq_temp%10;
       freq_temp=freq_temp/10;
}
}

//T/C0比较匹配中断服务,2ms定时
INTERRUPT(SIG_OUTPUT_COMPARE0)
{
   time_2ms_ok=1;
}

//T/C1溢出中断服务
SIGNAL(SIG_OVERFLOW1)
{
full_ok=1;
}

//T/C1输入捕捉中断服务
SIGNAL(SIG_INPUT_CAPTURE1)
{
   if(icp_n>max_icp) //第N个上升沿到
{
   icp_v2=ICR1;
   TIMSK=(1<<OCIE0);//禁止T/C1输入捕捉和溢出中断,保持T/C0比较匹配中断服务使能
   icp_ok=1;
   }
   else if(icp_n==0)
{
   icp_v1=ICR1;//记录第一个上升沿时间
}       
icp_n++;
}
int main()
{
   unsigned long freq=0;
   unsigned int icp_temp1=0,icp_temp2=0;
   DDRA=0xFF;
   DDRC=0xFF;
   PORTD=(1<<PD6); //PD6(ICP)输入方式,上拉有效

   //T/C1初始化
   TCCR1A=0;
   TCCR1B=(1<<ICES1)|(0<<CS12)|(0<<CS11)|(1<<CS00); //clk,正常计数方式,上升沿出发捕捉
   ICR1=0;

   //T/C0初始化
   TCCR0=(1<<WGM01)|(0<<WGM00)|(0<<CS02)|(1<<CS01)|(1<<CS00);//CTC模式,64分频
   TCNT0=0;
   OCR0=249; //2000/(1/(8/64))=250,250-1=249; 2ms定时
   TIMSK=(1<<OCIE0)|(1<<TOIE1)|(1<<TICIE1);//使能T/C0比较匹配中断、T/C1溢出中断、T/C1输入捕捉中断
   sei();
   while(1)
   {              
           if(icp_ok==1)//完成一次测量
        {               
                if(icp_v2>=icp_v1)//计算N个上升沿时钟脉冲数
                        icp_temp2=icp_v2-icp_v1;
                else
                        icp_temp2=65536-icp_v1+icp_v2;
                if(!((icp_v2>=icp_v1)&&(full_ok==1)))//数据有效
                {
                        if(icp_temp2==icp_temp1) //两次个数相等,测量有效(防止干扰)
                        {
                                freq=80000000*(unsigned long)max_icp/(unsigned long)icp_temp2;//换算成频率值*10; ???为 什么理论freq=80000000*max_icp/icp_temp2;输入频率<8k,显示出的结果只为实际频率的一半????
                                f_2_d=1; //允许新频率送显示
                                if(freq>40000)
                                        max_icp=50;//如果输入频率大于4k,设置测量捕捉周期脉冲数为50个
                                else
                                        max_icp=1;//如果输入频率小于4k,设置测量捕捉周期脉冲数为1个
                        }
                }
                else                   //有溢出,数据无效设置测量捕捉周期脉冲数为1
                        max_icp=1;   
                icp_temp1=icp_temp2;
                icp_ok=0;
                     icp_n=0;    //开始新的一次测量
                full_ok=0;//清除溢出标志
                TIFR=(1<<ICF1)|(1<<TOV1); //回写标志位,清楚可能存在的输入捕捉、溢出中断标志
                     TIMSK|=(1<<TOIE1)|(1<<TICIE1);//恢复使能T/C1溢出中断、T/C1输入捕捉中断
   
        }
        if(time_2ms_ok==1)
        {
                if(f_2_d==1)
                {
                      freq_to_disbuff(freq); //新频率送显示
                      f_2_d=0;
                }
                     display();
                time_2ms_ok=0;
        }
   }
}

yqing81 发表于 2009-5-26 14:17:58

没有路过的高人解答??期待!!!

yqing81 发表于 2009-5-26 20:16:46

问题找到结贴,是自己粗心,计第脉冲个数时 if(icp_n>max_icp) ,应该是if(icp_n>max_icp) ,汗!!!!

===============================================
还是错呀:应该是if(icp_n >= max_icp)

machao 发表于 2009-5-26 20:32:49

另外,当你使用8M系统时钟,测量转换应设置在2K,而且测量频率的下限提高到250Hz,200Hz以下频率测量不能测量了,具体你自己分析一下。

yqing81 发表于 2009-5-27 08:07:49

谢谢马老师回复!2楼我少打了个“=”,找到问题,心情太激动了!:),谢谢马老师为我纠正;下限频率提高,200HZ以下T/C1已经溢出了。

linjinhai126 发表于 2009-6-13 10:54:16

楼主留个联系方式,讨论下哈~!!

yqing81 发表于 2009-6-13 15:51:16

qq:19915993

wowu 发表于 2009-8-22 14:12:40

好。谢谢分享。

hpdell 发表于 2010-8-10 09:20:59

不!!!!!!错

guxingganyue 发表于 2011-5-31 13:15:22

回复【4楼】yqing81
-----------------------------------------------------------------------

我8M晶振时,下限频率可以到200Hz一下的啊,我计算处理是125Hz,1/125Hz=0.008s,1/8M=0.125us,

在0.008s内可以计数的个数为:0.008s/0.125us=64000<65535,所以没有溢出啊。。。


为什么要定在200Hz一下呢???
页: [1]
查看完整版本: 移植马潮老师实验—基于T/C1捕捉功能的可变量程频率计的设计与实验,出现奇怪问题!请高