搜索
bottom↓
回复: 9

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

[复制链接]

出0入0汤圆

发表于 2009-5-25 20:55:32 | 显示全部楼层 |阅读模式
买了马老师的书,业余时间一直在研读,从中也学了不少,在此要感谢马老师!!
由于本人只会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[16] PROGMEM = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//common+
const unsigned char position[8] PROGMEM = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

unsigned char posit=0;
unsigned char dis_buff[8]={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 int  icp_v1,icp_v2;


void display(void)
{
  PORTC = 0xff;
  PORTA = pgm_read_byte(&led_7[dis_buff[posit]]);
  if(posit==1) PORTA &=0x7f;
  PORTC = pgm_read_byte(&position[posit]);
  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;
        }
   }
}

出0入0汤圆

 楼主| 发表于 2009-5-26 14:17:58 | 显示全部楼层
没有路过的高人解答??期待!!!

出0入0汤圆

 楼主| 发表于 2009-5-26 20:16:46 | 显示全部楼层
问题找到结贴,是自己粗心,计第脉冲个数时 if(icp_n>max_icp) ,应该是if(icp_n>max_icp) ,汗!!!!

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

出0入0汤圆

发表于 2009-5-26 20:32:49 | 显示全部楼层
另外,当你使用8M系统时钟,测量转换应设置在2K,而且测量频率的下限提高到250Hz,200Hz以下频率测量不能测量了,具体你自己分析一下。

出0入0汤圆

 楼主| 发表于 2009-5-27 08:07:49 | 显示全部楼层
谢谢马老师回复!2楼我少打了个“=”,找到问题,心情太激动了!:),谢谢马老师为我纠正;下限频率提高,200HZ以下T/C1已经溢出了。

出0入0汤圆

发表于 2009-6-13 10:54:16 | 显示全部楼层
楼主留个联系方式,讨论下哈~!!

出0入0汤圆

 楼主| 发表于 2009-6-13 15:51:16 | 显示全部楼层
qq:19915993

出0入0汤圆

发表于 2009-8-22 14:12:40 | 显示全部楼层
好。谢谢分享。

出0入0汤圆

发表于 2010-8-10 09:20:59 | 显示全部楼层
不!!!!!!错

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-19 18:03

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

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