nzls 发表于 2008-6-1 16:30:27

T1扑捉程序,帮忙指点

马潮老师,我根据你在《AVR单片机嵌入式系统原理与应用实践》334页中的扑捉程序,我用液晶显示,程序我也改动一下,利用T1溢出中断次数来检测低频,同时我直接利用T1扑捉的降噪使能位,没有用书上的if(icp_2==icp_1)来判断测量是否有效。但显示不出正确的结果,如646hz显示55hz~58hz,只是会在一瞬间显示646hz,我实在是早不到原因,附上程序希望马潮老师帮忙指正
////////////////////////////////////////////
// Target : M16
// Crystal: 4.0000Mhz

#include <mega16.h>
sfrw ICR1=0x26;
sfrw TCNT1=0x2c;
#include<1621sunrendanpai.h>
#include<delay.h>   
#defineTOIE00
#defineOCIE01
#defineTOIE12
#defineTICIE1 5
bit icp_ok,t1counten=0;
long icp_v1,icp_v2;
uchar ddat[]={0,0,0,0,0,0,0};
uchar icp_n,t1count;

void port_init(void)
{
// PORTB=0xff;
// DDRB|=(1<<0)|(1<<1)|(1<<2)|(1<<3);                  //检测为输出
PORTD|=(1<<6);                                        //扑捉上拉有效
DDRD&=~(1<<6);                                        //设置扑捉为输入   
io_init();
}
// Timer 1 overflow interrupt service routine
interrupt void timer1_ovf_isr(void)
{
if(t1counten)
    {
   if(++t1count>65)      //t1count>65次溢出,频率小于1HZ,在信号停止的情况下
   icp_ok=1;               //能够及时退出显示0hz
    }         
}

// Timer 1 input capture interrupt service routine
interrupt void timer1_capt_isr(void)
{
if(icp_n==0)                  //是否是第一个上升沿
      {
       icp_v1=ICR1;
       icp_n++;                  //上升沿次数++
       t1counten=1;                //第一个扑捉上升沿,t1溢出中断计数使能
      }
else
      {
       icp_n=0;                  
       icp_v2=ICR1;
       TIMSK&=~((1<<TICIE1)|(1<<TOIE1));   //禁止t1扑捉中断和溢出中断
       icp_ok=1;                           //扑捉完成标志
       t1counten=0;                        //t1溢出中断计数禁止
      }   
}
//====================================
void timer1_init(void)
{
TCNT1=0x0000;
TCCR1B = 0xC1; //start Timer
}
//===================================
void init_devices(void)
{
//stop errant interrupts until set up
#asm("cli"); //disable all interrupts
port_init();
timer1_init();
TIMSK|=(1<<TICIE1)|(1<<TOIE1);
ACSR=0x80;
#asm("sei")
//all peripherals are now initialized
}

//-----------------------------------------
void f_to_disbuf(long v)
{
   uchar i;
   for(i=0;i<7;i++)
   {
      ddat=v%10;
      v/=10;
   }
}
//---------------------------------------------
void main(void)
{
long fv;
long icp_2;
icp_n=0;                                          //上升沿次数
t1counten=0;                                    
t1count=0 ;                                        //t1溢出中断次数
init_devices();
while(1)
   {
      if(icp_ok)                                     //扑捉是否完成
         {
          icp_ok=0;
          icp_2=0xffff*t1count+icp_v2-icp_v1;      //脉冲周期
          fv=4000000/icp_2;                           //转换成频率
          f_to_disbuf(fv);                            //送显示缓冲区
          LCD_REST();
          LCD_dpwrite_char(0,ddat);                   //显示
          delay_ms(100);                               //
          t1count=0;                                 //T1溢出中断次数回零
          TIMSK|=(1<<TICIE1)|(1<<TOIE1);               //T1扑捉中断和溢出中断使能
         }   
         
   }
}

fsclub 发表于 2008-6-1 17:32:51

扑捉?

这个动作不错。楼主能不能表演一下怎么个扑法?

machao 发表于 2008-6-1 18:44:23

fv=4000000/icp_2;                           //转换成频率
          f_to_disbuf(fv);                            //送显示缓冲区
          LCD_REST();
          LCD_dpwrite_char(0,ddat);


把上面一段改成
          fv = 646;                           //转换成频率
          f_to_disbuf(fv);                            //送显示缓冲区
          LCD_REST();
          LCD_dpwrite_char(0,ddat);

也就是假定每次频率就是646HZ,看你的显示是否正确?然后将646改成其它的数,如2345等,先调试你的显示部分吧.

nzls 发表于 2008-6-1 19:35:36

显示部分应该没有问题,因为通过AVR studio 模拟观察,液晶显示和fv变化一致。

machao 发表于 2008-6-1 20:04:13

t1count=0;                                 //T1溢出中断次数回零
                     <======增加清T1中断标志试试
          TIMSK|=(1<<TICIE1)|(1<<TOIE1);               //T1扑捉中断和溢出中断使能
=====================================================================================
在我的例子中有清中断标志的语句,你知道它的作用么?为何省掉了?

nzls 发表于 2008-6-1 22:09:40

谢谢马老师,按你说的做问题解决了,我当初之所以省掉,我想在响应捕捉和溢出中断时,中断标志位由硬件清标志位。

machao 发表于 2008-6-1 22:17:07

没错呀,AVR在响应捕捉和溢出中断时,中断标志位是由硬件清标志位的.

可是你想过吗,为何要加上这句清中断标志位的语句,要明白为什么.

nzls 发表于 2008-6-2 09:14:26

是不是在捕捉完成时,设立禁止捕捉和溢出中断使能,而溢出中断可能此时并没有中断,所以其中断标志位还存在,所以最后要加上清溢出和捕捉位的动作,我是这样理解的,不知是否正确?

machao 发表于 2008-6-2 16:57:14

进行完一次测量后,尽管禁止了T1捕捉和溢出中断,可是T1外部的输入信号还在呀,T1也还在继续的工作.

当你在处理数据和显示过程中,T1外部的输入信号可能已经有N个上升沿出现了,T1也就产生N捕捉,而且T1也溢出过了,因此捕捉中断和溢出中断的标志位可能都是置位的,只是由于禁止了中断,没有响应,中断标志不会被硬件清除了.此时你开中断,马上就会响应中断,但数据肯定是不对了.
页: [1]
查看完整版本: T1扑捉程序,帮忙指点