关于avr输入捕捉的问题
现在想用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);//清除中断标志位
}
看看有没有中断产生。如果没有要么是输入信号问题,要么是ICP初始化问题,看看应用手册吧 xsh2005105326 发表于 2015-3-31 11:15
看看有没有中断产生。如果没有要么是输入信号问题,要么是ICP初始化问题,看看应用手册吧 ...
对着手册一位一位的确认了 没有问题啊 以前也调通过 现在中断都进不去 输入信号也有啊 很不解 本帖最后由 zhanan 于 2015-3-31 12:02 编辑
什么型号?
捕捉中断里面应该读ICR1寄存器吧,这个才是捕捉到的数据,用不着关中断读TCNT1
中断进不去,是不是和TIMSK1有关,这个是对应TC1的。
另外,AVR响应中断后捕捉标志会自动清0 jihongyuan 发表于 2015-3-31 11:20
对着手册一位一位的确认了 没有问题啊 以前也调通过 现在中断都进不去 输入信号也有啊 很不解 ...
使用大字体,小心ID不保。 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上升沿中断,其他的都置零了,没问题啊 alias 发表于 2015-3-31 12:07
使用大字体,小心ID不保。
啊?这个有限制么?不知道啊,下次注意 1.先确认中断进去了没有,可以把Set_Bit(PORTA,0);Clr_Bit(PORTA,0);//PD0 置低 直接放中断里调用一下
2.unsigned char up;
unsigned char down;应该为unsigned int吧 gdjsfy_86 发表于 2015-3-31 15:37
1.先确认中断进去了没有,可以把Set_Bit(PORTA,0);Clr_Bit(PORTA,0);//PD0 置低 直接放中断里调用一下
...
int 是八位的最后的数据是16位的 所以我用的是char类型,中断没有进去,现在在找原因,但是输入捕捉中断是系统自动进入的,配置好了就行了,我把手册上看了几遍也没看出我哪儿配置错了啊 到底是进不去中断,还是数据处理有问题?
什么编译?#pragma interrupt_handler CAPT_ISP:0X0A这里是写中断号还是中断地址?
down |= ((unsigned int)TCNT1H << 8); down是8位的变量,怎么能装16位呢?
在中断里面点一个灯,不就能看到进没进中断了。
捕捉有ICR为什么不用,偏偏去读TCNT。读TCNT的时候,已经不是捕捉时刻的值了。 中断内会被改变的变量要加上 Volatile 描述,否则…{:shocked:} 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数据一直不对劲啊 alias 发表于 2015-3-31 22:38
中断内会被改变的变量要加上 Volatile 描述,否则…
啊?不是太明白,什么描述? 把up、down改为u16吧。 不然这句 up=((unsigned int)ICR1H<<8); 是无效的,也可能你故意丢的吧,8位就够了。
TCNT1=0;//TCNT1清零这句也是有问题的,16位的寄存器必须先写高字节,后写低字节。
正确的捕捉应该是这样的:按照捕捉的分辨率设置好定时器频率,启动定时器,捕捉一次,up记录下上升沿捕捉到的值ICR,再下降沿捕捉一次down记录一下,这两个捕捉在中断里面做,主程序中判断差值down-up就行了。不用改TCNT1的值,也不用关中断。
zhanan 发表于 2015-4-1 10:53
把up、down改为u16吧。 不然这句 up=((unsigned int)ICR1H
好的,我试试
页:
[1]