搜索
bottom↓
回复: 6

关于mega16利用定时器1测量输入信号的频率和占空比

[复制链接]

出0入0汤圆

发表于 2014-9-2 14:06:30 | 显示全部楼层 |阅读模式
        在学习AVR过程中遇到了这个问题,我想利用定时器中断1的输入捕获功能来获得输入PWM的频率和占空比,查阅了一些资料,知道要先在上升沿触发,然后再下降沿触发,得到高电平的时间。
于是想在中断函数里面重新初始化输入捕获,改在下降沿触发。想利用LED灯的闪烁来看在上升沿和下降沿触发的情况。但是始终不行,部分代码如下,请大神赐教。

void ICEInit(void) //T/C1初始化
{
    TIMSK=0X20; //使能捕获中断
    TCCR1A=0X00;//T/C1时钟与系统相同,本文使用系统AVR内部自带8MHz振荡源.T/C1时钟周期为1μs
    TCCR1B=0XC2; //使能噪音抑制,下降沿触发中断,fosc/8
}
#pragma interrupt_handler CAPT_ISR:6
void CAPT_ISR(void)
{
       
    uchar a;
    uint temp;
    newFall = ICR1; //read ICR1
    Set_Bit(PORTD,1);
    CLI();
    TIMSK=0X20;
    TCCR1A=0X00;
    TCCR1B = 0x82;
    SEI();
....
....
}

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

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

出0入0汤圆

发表于 2014-9-2 16:25:49 | 显示全部楼层
请说明现象,怎么个不行法?

出0入0汤圆

发表于 2014-9-3 10:37:24 | 显示全部楼层
#pragma interrupt_handler timer1_capt_isr:6
void timer1_capt_isr(void)
{
  //wave_count++;

   if(TCCR1B&(1<<ICES1))  //如果是上升沿捕获
     {up = TCNT1; TCNT1 = 0;}
   else
     {down = TCNT1;}
   TCCR1B ^= (1<<ICES1);  //反转ICES1, 在上升和下降沿都能触发中断  (初始化的是上升沿触发)
}
中断服务程序里面不要加那么多设置吧。 改变出发边沿的话只需要设置ICES1就可以了,其他的初始化放在对定时器初始化就饿可以了。中断服务程序尽量简洁一些。
另外,根据个人经验和理解,我建议你直接读TCNT1,因为对TCNT1可以对其进行赋值操作,ICR1的用法貌似在输入捕捉里面不可以随意改动初值,它只是将计数器的值copy进去而已。 并且我读出的ICR1跟TCNT1的值是不一样的,中间差一点点。
如果有理解不对的地方,还请大神赐教!!!  

出0入0汤圆

 楼主| 发表于 2014-9-3 14:12:31 | 显示全部楼层
mk_avatar 发表于 2014-9-3 10:37
#pragma interrupt_handler timer1_capt_isr:6
void timer1_capt_isr(void)
{

void int1_init()
{
    MCUCR = 0x0C;//外部中断1上升沿触发
        GICR = 0x80;//使能外部中断1
}
#pragma interrupt_handler INT_1:3
void INT_1(void)
{
    unsigned i;
        TCCR1B = 0x00;
    TCNT1H=0x00;
        TCNT1L=0x00;
        TCCR1A = 0x00;
        TCCR1B = 0x03; //start Timer
        MCUCR=0x08;//
        TCCR1B=0x00;
        //count=i;
        i = TCNT1;
        Clr_Bit(PORTD,0);
        if(i>2&&i<100)
        {
            Clr_Bit(PORTD,1);
        }       
}
我也在调试你的程序,在你没回复之前,我先用的外部中断1,在上升沿触发中断,进入中断程序,然后清空计数器,打开定时器,然后变为下降沿触发,
关闭定时器,把值读出来,然后测试这个值大概在什么范围,判断是不是进入下降沿中断了,事实证明没有进去啊,这个是怎么回事呢?请教啊

出0入0汤圆

 楼主| 发表于 2014-9-3 14:19:55 | 显示全部楼层
一往无前 发表于 2014-9-2 16:25
请说明现象,怎么个不行法?

进入不了下降沿的中断

出0入0汤圆

发表于 2014-9-3 15:39:45 | 显示全部楼层
你可以先用信号发生器或者是用单片机产生一个固定周期和占空比的波形,周期长一些来测定参数。 我用的M16, TC1, 输入捕捉; 实验:对255HZ,占空比75%的波形检测,我中断里面读出的up值为128,down值为96(有时会有+ - 1 的浮动),占空比就是75%.   至于其频率的话,就是直接用系统晶振频率/TC1的预分频/up, 就得到了。你自己试验一下把。
我看了你用外部中断做的程序了,你只是用了TCCR1B的第三位来开关定时器,对定时器没有做其他的操作,貌似有问题。你读出来值没有?是多大?  另外,如果你感觉没有进入外部中断,再重新检查一下 MCUCR .GICR寄存器和 SEI()语句。  你的外部中断里面的流程你检查一下,有点混乱。
如果只需要测频率的话,你只需要一直读取上升沿或者下降沿其中一个的值即可,每次读完之后置零。 中断里面: 读数-置零即可;
测占空比时,上升沿和下降沿都能触发中断,并且需要分清楚上升沿和下降沿。 中断里面:判断目前是上升沿还是下降沿-改变触发方式-读数-置零
中断服务程序里面要处理的内容不宜太长,对于定时器的初始化设置就放在外边比较好。
对16位的TCNT1的读数,试试分开读,
//value_t = TCNT1L;
// value_t|=(unsigned int)(TCNT1H<<8);
建议你如果需要频率和占空比一起测的话,最好还是用输入捕捉比较好,不会占用很多资源,能测的频率范围也比较大。

出0入0汤圆

 楼主| 发表于 2014-10-30 16:42:32 | 显示全部楼层
mk_avatar 发表于 2014-9-3 15:39
你可以先用信号发生器或者是用单片机产生一个固定周期和占空比的波形,周期长一些来测定参数。 我用的M16,  ...

我这个程序还是不行,我是用的八分频,周期为1us,就是说TCNT1在一个脉冲周期加1,我测量的是接收机的信号,理论上是20ms周期,1ms或者2ms的高电平时间,读出来的数应该在1000才对啊,可是我用串口软件看的数,总是在乱蹦,下面是其中一部分数据:
92 E0 92 D6 70 D1 83 A5 A5 9B BA 92 C2 66 C2 73 C2 7D C2 89 C2 A6 C2 BD C2 C1 EC C2 76 C2 7F C2 97 C2 C2 E1 C2 D0 C2 A8 C2 92 DF 69 CF 7A C6 8B 92 C2 6D C2 77 C2 8E C2 C2 E1 C2 BC C2 A9 C2 AF EA C2 E2 C2 B9 C2 A9 C2 92 F0 74 D0 91
A6 A3 92 C1 6C C2 75 C2 83 C2 8E C2 B1 C2 B4 C2 BE E2 C2 7F C2 8E C2 9E C2 B8 F1 C2 D6 C2 B8 C2 B1 C2 A0 C2 92 DE 71 D6 79 C6 8B AD A2 92 C2 73 C2 84 C2 89 C2 8C A2 B6 92 C2 8F C2 AE C2 C2 E8 C2 E0 C2 C7 C2 92 EE 69 D5 6F CF 82 AE
纠结了好久好久,还是查不出自己哪儿错了,求指点

void port_init(void)  
{   
    PORTD = 0xFF;  //输入上拉电阻使能,输出引脚为高电平
    DDRD = 0xBF;  //PD4,PD5为输出,PD6为输入
}
void ICEInit(void)  
{  
    port_init();//端口的初始化
    TIMSK=0X20;//使能捕获中断  
    TCCR1A=0X00;
        TCCR1B=0XC2;//使能噪声抑制,上升降沿触发,八分频,周期为1us
}
#pragma interrupt_handler CAPT_ISP:6

void CAPT_ISP(void)
{
     unsigned char sreg;
     if(TCCR1B&(1<<ICES1))//假如是上升沿中断
         {
                 TCNT1=0;//TCNT1清零
                 TCCR1B^=(1<<ICES1);//设置为下降沿中断
         }
         else if(!(TCCR1B&(0<<ICES1)))//假如是下降沿中断
         {
             sreg = SREG;
                 _CLI();
             up = TCNT1L;
                 up |= ((unsigned int)TCNT1H<<8);
                 SREG = sreg;
                 TCCR1B|=(1<<ICES1);
         }
         TIFR&=(1<<ICF1);//清除中断标志位
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-7-23 17:24

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

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