搜索
bottom↓
回复: 8

T1扑捉程序,帮忙指点

[复制链接]

出0入0汤圆

发表于 2008-6-1 16:30:27 | 显示全部楼层 |阅读模式
马潮老师,我根据你在《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>   
#define  TOIE0  0
#define  OCIE0  1
#define  TOIE1  2
#define  TICIE1 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 [TIM1_OVF] 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 [TIM1_CAPT] 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[6-i]=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扑捉中断和溢出中断使能
         }     
         
     }
}

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

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

出0入0汤圆

发表于 2008-6-1 17:32:51 | 显示全部楼层
扑捉?

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

出0入0汤圆

发表于 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等,先调试你的显示部分吧.

出0入0汤圆

 楼主| 发表于 2008-6-1 19:35:36 | 显示全部楼层
显示部分应该没有问题,因为通过AVR studio 模拟观察,液晶显示和fv变化一致。

出0入0汤圆

发表于 2008-6-1 20:04:13 | 显示全部楼层
t1count=0;                                   //T1溢出中断次数回零
                       <======增加清T1中断标志试试
          TIMSK|=(1<<TICIE1)|(1<<TOIE1);               //T1扑捉中断和溢出中断使能
=====================================================================================
在我的例子中有清中断标志的语句,你知道它的作用么?为何省掉了?

出0入0汤圆

 楼主| 发表于 2008-6-1 22:09:40 | 显示全部楼层
谢谢马老师,按你说的做问题解决了,我当初之所以省掉,我想在响应捕捉和溢出中断时,中断标志位由硬件清标志位。

出0入0汤圆

发表于 2008-6-1 22:17:07 | 显示全部楼层
没错呀,AVR在响应捕捉和溢出中断时,中断标志位是由硬件清标志位的.

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

出0入0汤圆

 楼主| 发表于 2008-6-2 09:14:26 | 显示全部楼层
是不是在捕捉完成时,设立禁止捕捉和溢出中断使能,而溢出中断可能此时并没有中断,所以其中断标志位还存在,所以最后要加上清溢出和捕捉位的动作,我是这样理解的,不知是否正确?

出0入0汤圆

发表于 2008-6-2 16:57:14 | 显示全部楼层
进行完一次测量后,尽管禁止了T1捕捉和溢出中断,可是T1外部的输入信号还在呀,T1也还在继续的工作.

当你在处理数据和显示过程中,T1外部的输入信号可能已经有N个上升沿出现了,T1也就产生N捕捉,而且T1也溢出过了,因此捕捉中断和溢出中断的标志位可能都是置位的,只是由于禁止了中断,没有响应,中断标志不会被硬件清除了.此时你开中断,马上就会响应中断,但数据肯定是不对了.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-7-23 04:19

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

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