搜索
bottom↓
回复: 14

关于avr输入捕捉的问题

[复制链接]

出0入0汤圆

发表于 2015-3-31 09:43:14 | 显示全部楼层 |阅读模式
现在想用AVR的输入捕捉功能区捕捉一个16ms周期2ms高电平时间的方波
但是一直捕捉不到,求大神解释,急啊,急啊,不知道问题出在哪儿了,在线等啊,不胜感激

unsigned char up;
unsigned char down;

void port_init(void)  
{  
    PORTD = 0xFF;  //输入上拉电阻使能,输出引脚为高电平
    DDRD = 0xBF;  //PD4,PD5为输出,PD6为输入
}
void ICEInit(void)  
{  
    TCCR1A=0X00;//时钟与系统相同
    TCCR1B=0XC2;//使能噪声抑制,上升降沿触发,八分频,周期为1us
    TIMSK=0X20;//使能捕获中断  
}
void main(void)
{
    DDRA=0xFF;    //PD口设成输出口
    PORTA=0xFF;
    port_init();//端口的初始化
    ICEInit();//输入捕获的初始化
    SEI();//打开总中断  
    while(1)
    {
         if((down>9)&&(down<11))
        {
            Set_Bit(PORTA,0);
            Clr_Bit(PORTA,0);  //PD0 置低
        }
        else if((down>19)&&(down<21))
        {
            Clr_Bit(PORTA,0);
            Set_Bit(PORTA,0);  //PD0 置高
        }
    }
}
#pragma interrupt_handler CAPT_ISP:0X0A

void CAPT_ISP(void)
{
    unsigned char sreg;
    unsigned char ssreg;
    if(TCCR1B&(1<<ICES1))//假如是上升沿中断
    {
        ssreg = SREG;
        _CLI();
        up = TCNT1L;
        up |= ((unsigned int)TCNT1H << 8);//读取TCNT1的值
        SREG = ssreg;
        TCCR1B^=(1<<ICES1);
    }
    else//假如是下降沿中断
    {
        sreg = SREG;
        _CLI();
        down = TCNT1L;//读取TCNT1的值
        down |= ((unsigned int)TCNT1H << 8);
       if(up<down)
            down = (down - up)/10;
        SREG = sreg;
        TCCR1B |= (1<<ICES1);
    }
    TIFR&=(1<<ICF1);//清除中断标志位
}

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

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

出0入0汤圆

发表于 2015-3-31 11:15:21 | 显示全部楼层
看看有没有中断产生。如果没有要么是输入信号问题,要么是ICP初始化问题,看看应用手册吧

出0入0汤圆

 楼主| 发表于 2015-3-31 11:20:28 | 显示全部楼层
xsh2005105326 发表于 2015-3-31 11:15
看看有没有中断产生。如果没有要么是输入信号问题,要么是ICP初始化问题,看看应用手册吧 ...

对着手册一位一位的确认了 没有问题啊 以前也调通过 现在中断都进不去 输入信号也有啊 很不解

出0入0汤圆

发表于 2015-3-31 12:00:55 | 显示全部楼层
本帖最后由 zhanan 于 2015-3-31 12:02 编辑

什么型号?

捕捉中断里面应该读ICR1寄存器吧,这个才是捕捉到的数据,用不着关中断读TCNT1
中断进不去,是不是和TIMSK1有关,这个是对应TC1的。

另外,AVR响应中断后捕捉标志会自动清0

出0入0汤圆

发表于 2015-3-31 12:07:25 | 显示全部楼层
jihongyuan 发表于 2015-3-31 11:20
对着手册一位一位的确认了 没有问题啊 以前也调通过 现在中断都进不去 输入信号也有啊 很不解 ...

使用大字体,小心ID不保。

出0入0汤圆

 楼主| 发表于 2015-3-31 12:51:26 | 显示全部楼层
zhanan 发表于 2015-3-31 12:00
什么型号?

捕捉中断里面应该读ICR1寄存器吧,这个才是捕捉到的数据,用不着关中断读TCNT1

mega16A ICR1不也是拷贝的TCNT1的值么,这两个寄存器都可以读取的啊,自动清零的状态只是在测频率的时候,要是测量占空比的话要手动清零,TIMSK的寄存器
• Bit 5 – TICIE1: T/C1输入捕捉中断使能
当该位被设为"1”,且状态寄存器中的I位被设为"1”时,T/C1的输入捕捉中断使能。一
旦TIFR的ICF1置位,CPU即开始执行T/C1输入捕捉中断服务程序 ( 见P43 “中断” )。
• Bit 4 – OCIE1A: 输出比较A匹配中断使能
当该位被设为"1”,且状态寄存器中的I位被设为"1”时,T/C1的输出比较A匹配中断使
能。一旦TIFR上的OCF1A置位,CPU即开始执行T/C1输出比较A匹配中断服务程序
(见P43 “中断” )。
• Bit 3 – OCIE1B: T/C1输出比较B匹配中断使能
当该位被设为"1”,且状态寄存器中的I位被设为"1”时,使能T/C1的输出比较B匹配中
断使能。一旦TIFR上的OCF1B置位,CPU即开始执行T/C1输出比较B匹配中断服务
程序 ( 见P43 “中断” )。
• Bit 2 – TOIE1: T/C1溢出中断使能
当该位被设为"1”,且状态寄存器中的I 位被设为”1” 时,T/C1的溢出中断使能。一旦
TIFR上的TOV1置位,CPU即开始执行T/C1溢出中断服务程序 ( 见P43 “中断” )。
我用的是0X20  第五位置1上升沿中断,其他的都置零了,没问题啊

出0入0汤圆

 楼主| 发表于 2015-3-31 12:52:06 | 显示全部楼层
alias 发表于 2015-3-31 12:07
使用大字体,小心ID不保。

啊?这个有限制么?不知道啊,下次注意

出0入0汤圆

发表于 2015-3-31 15:37:25 | 显示全部楼层
1.先确认中断进去了没有,可以把Set_Bit(PORTA,0);Clr_Bit(PORTA,0);  //PD0 置低   直接放中断里调用一下
2.unsigned char up;
unsigned char down;应该为unsigned int吧

出0入0汤圆

 楼主| 发表于 2015-3-31 15:48:57 | 显示全部楼层
gdjsfy_86 发表于 2015-3-31 15:37
1.先确认中断进去了没有,可以把Set_Bit(PORTA,0);Clr_Bit(PORTA,0);  //PD0 置低   直接放中断里调用一下
...

int 是八位的  最后的数据是16位的 所以我用的是char类型,中断没有进去,现在在找原因,但是输入捕捉中断是系统自动进入的,配置好了就行了,我把手册上看了几遍也没看出我哪儿配置错了啊

出0入0汤圆

发表于 2015-3-31 22:17:44 | 显示全部楼层
到底是进不去中断,还是数据处理有问题?

什么编译?#pragma interrupt_handler CAPT_ISP:0X0A  这里是写中断号还是中断地址?

       down |= ((unsigned int)TCNT1H << 8);   down是8位的变量,怎么能装16位呢?

在中断里面点一个灯,不就能看到进没进中断了。

捕捉有ICR为什么不用,偏偏去读TCNT。读TCNT的时候,已经不是捕捉时刻的值了。

出0入0汤圆

发表于 2015-3-31 22:38:21 | 显示全部楼层
中断内会被改变的变量要加上 Volatile 描述,否则…

出0入0汤圆

 楼主| 发表于 2015-4-1 09:30:11 | 显示全部楼层
zhanan 发表于 2015-3-31 22:17
到底是进不去中断,还是数据处理有问题?

什么编译?#pragma interrupt_handler CAPT_ISP:0X0A  这里是写 ...

down 是char类型的  已经改过为读取ICR1了,向量号是6,也改过来了,中断能进去了,但是数据处理好像还是不合适
unsigned char up;       //定义一个char类型的变量
unsigned char down;
#pragma interrupt_handler timer1_CAPT:6
void timer1_CAPT(void) //输入捕捉端口有下降沿电平,则触发中断
{
        unsigned char sreg;
        if(TCCR1B&(1<<ICES1))//假如是上升沿中断
        {
                 TCNT1=0;//TCNT1清零
                 TCCR1B^=(1<<ICES1);//设置为下降沿中断
                 TIFR|=(1<<ICF1);
                 //PORTA =~PORTA; //LED状态翻转
      }
        else if(!(TCCR1B&(1<<ICES1)))//假如是下降沿中断
     {
         sreg = SREG;
         _CLI();
         up = ICR1L;
         up |= ((unsigned int)ICR1H<<8);
         down = (up/100);
         SREG = sreg;
         TCCR1B|=(1<<ICES1);
         TIFR|=(1<<ICF1);
       //PORTA =~PORTA; //LED状态翻转
     }   
}
具体程序是这个样子的,但是down数据一直不对劲啊

出0入0汤圆

 楼主| 发表于 2015-4-1 09:31:15 | 显示全部楼层
alias 发表于 2015-3-31 22:38
中断内会被改变的变量要加上 Volatile 描述,否则…

啊?不是太明白,什么描述?

出0入0汤圆

发表于 2015-4-1 10:53:24 | 显示全部楼层
把up、down改为u16吧。 不然这句 up=((unsigned int)ICR1H<<8); 是无效的,也可能你故意丢的吧,8位就够了。
TCNT1=0;//TCNT1清零  这句也是有问题的,16位的寄存器必须先写高字节,后写低字节。

正确的捕捉应该是这样的:  按照捕捉的分辨率设置好定时器频率,启动定时器,捕捉一次,up记录下上升沿捕捉到的值ICR,再下降沿捕捉一次down记录一下,这两个捕捉在中断里面做,主程序中判断差值down-up就行了。不用改TCNT1的值,也不用关中断。

出0入0汤圆

 楼主| 发表于 2015-4-1 14:37:28 | 显示全部楼层
zhanan 发表于 2015-4-1 10:53
把up、down改为u16吧。 不然这句 up=((unsigned int)ICR1H

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

本版积分规则

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

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

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

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