T1扑捉程序,帮忙指点
马潮老师,我根据你在《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>
#defineTOIE00
#defineOCIE01
#defineTOIE12
#defineTICIE1 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 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 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=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扑捉中断和溢出中断使能
}
}
} 扑捉?
这个动作不错。楼主能不能表演一下怎么个扑法? 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等,先调试你的显示部分吧. 显示部分应该没有问题,因为通过AVR studio 模拟观察,液晶显示和fv变化一致。 t1count=0; //T1溢出中断次数回零
<======增加清T1中断标志试试
TIMSK|=(1<<TICIE1)|(1<<TOIE1); //T1扑捉中断和溢出中断使能
=====================================================================================
在我的例子中有清中断标志的语句,你知道它的作用么?为何省掉了? 谢谢马老师,按你说的做问题解决了,我当初之所以省掉,我想在响应捕捉和溢出中断时,中断标志位由硬件清标志位。 没错呀,AVR在响应捕捉和溢出中断时,中断标志位是由硬件清标志位的.
可是你想过吗,为何要加上这句清中断标志位的语句,要明白为什么. 是不是在捕捉完成时,设立禁止捕捉和溢出中断使能,而溢出中断可能此时并没有中断,所以其中断标志位还存在,所以最后要加上清溢出和捕捉位的动作,我是这样理解的,不知是否正确? 进行完一次测量后,尽管禁止了T1捕捉和溢出中断,可是T1外部的输入信号还在呀,T1也还在继续的工作.
当你在处理数据和显示过程中,T1外部的输入信号可能已经有N个上升沿出现了,T1也就产生N捕捉,而且T1也溢出过了,因此捕捉中断和溢出中断的标志位可能都是置位的,只是由于禁止了中断,没有响应,中断标志不会被硬件清除了.此时你开中断,马上就会响应中断,但数据肯定是不对了.
页:
[1]