登录 免费注册 首页 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

M48的中断机制导致计时失误!

作者:xiaoxiong 栏目:单片机
M48的中断机制导致计时失误!
我用INT1(优先级较高)来检测一个固定频率的信号上升沿,
用Timer2计算外部信号相邻两个上升沿的时间。

因为其它原因,Timer2的时钟分频不能过大(已定为64分频),所以要增加一个全局变量(设为timer2IntCunt)来计算Timer2的溢出中断次数(即在Timer2溢出中断里对timer2IntCunt累加)。

在INT1中断程序里,进行如下操作(示意):
{
    read timer2IntCunt;            //用局部变量保存timer2IntCunt;
    read TCNT2;                    //用........保存TCNT2;
    clear TCNT2;                   //清TCNT2;
    if (timer2IntCunt not change)  //如果读TCNT2后timer2IntCunt未变;
    {
        OUTPUT TCNT2;              //将TCNT2从串口输出;
        OUTPUT timer2IntCunt;      //将.....从串口输出;
    }
    clear timer2IntCunt;           //清timer2IntCunt;
}

我PC机上收到的数为(十六进制):
timer2IntCunt|  TCNT2 |
05           |  06    |     //OK;
05           |  02    |     //一点误差,OK;
04           |  FD    |     //OK;
04           |  03    |     //NG!应该是05 03才对!
05           |  FE    |     //NG! 应该是04 FE才对!
05           |  01    |     //OK;
............................

问题:
A、“04 03”可能是因为刚进TIN1中断,TCNT2就溢出了。
可是Timer2是64分频,最多也只能出现04 00,0401.
B、“05 FE”就想不出原因了。总不可能是:TCNT2还没加到FF就进timer2中断对timer2IntCunt累加了吧??

不知我把问题讲明白了没。
恳请各位慢慢看。
希望大家多发言!

谢谢!!!


2楼: >>参与讨论
zsmbj
这不能说明问题。
如果int1中断的时候刚好在另外一个中断里执行,一般是不会进入int1中断的。除非等到那个中断执行完成。所有有可能导致某一个沿的时间被延迟了。

和你的64分频没有任何关系啊。

其实你的这个方案最好的方法是用ICP功能,就是检测两个沿的间隔时间,由于这个时间是由硬件实现的,所以不会有误差。



3楼: >>参与讨论
xwj
晕,这是什么鬼语法,看得真别扭!
要注意串口的非适时性

LZ,还是把你的程序贴出来吧

4楼: >>参与讨论
农民讲习所
读TCNT2时,如果处于低位向高位进位时刻
read TCNT2有出错机会,就是楼主的问题。所以再读出TCNT2后再比较TCNT2高位是否不变,变再读一次即可。(正处于进位时刻)

5楼: >>参与讨论
xiaoxiong
大家慢慢看!!!
”最好的方法是用ICP功能“
不好意思!我的资源都被占了,特别是Timer1,一定不能用了!

用到的中断中,只有INT1比Timer2中断的优先级高!
而INT1中断程序总共不多于15条汇编,占用CPU不多于26clok!
所以,就算INT1“挤“了timer2,也不过是timer2到01才进timer2中断!
可它出现了“04 03”

“晕,这是什么鬼语法,看得真别扭!”
大哥,我不是说“进行如下操作(示意):”吗?所谓“示意”啊!
怎么说,这是公司的东东啊!(虽然是我写的)


农民讲习所,
还是你说的对!我也这样认为!
可那“05 FE”是怎么出来的?我真是想不明白!


* - 本贴最后修改时间:2006-11-11 13:25:48 修改者:xiaoxiong

6楼: >>参与讨论
xiaoxiong
还有。。。
“所以再读出TCNT2后再比较TCNT2高位是否不变,变再读一次即可”

我的“if (timer2IntCunt not change)”就是这个意思!

对于串口,我是用局部变量把TCNT2和timer2IntCunt存下来,再发给PC的,所以不会有实时不实时的事!

* - 本贴最后修改时间:2006-11-10 22:20:01 修改者:xiaoxiong

7楼: >>参与讨论
xiaoxiong
如果明天我还没解决!
那我就把原码的片段拷上来给大家看看。

谢谢大家的时间!!!

* - 本贴最后修改时间:2006-11-10 22:46:11 修改者:xiaoxiong

8楼: >>参与讨论
xiaoxiong
原码:
/*Timer2 溢出中断.-------------------------------------------------------------
对gTmer2IntCnt累加*/
#pragma vector = TIMER2_OVF_vect
__interrupt void FreqInCunt(void)
{
    gTimer2IntCnt++;
}


/*外部中断1---------------------------------------------------------------
读Timer2的CNT值,清零Timer2的CNT值,加上Timer2 中断次数,计算周期*/
#pragma vector = INT1_vect
__interrupt void SpeedCommand(void)
{
    UCHAR freqInTmp;
    UCHAR freqInCntTmp;

    freqInCntTmp= gTimer2IntCnt;              //读Timer2中断次数;
    freqInTmp = GET_FREQ_IN();                //宏,读Timer2计数值;
    CLEAR_FREQ_CNT();                         //宏,清Timer2计数值;

    if (freqInCntTmp == gTimer2IntCnt)       //判断是否有进位误差;
    {
        guiFreqIn = (((UINT)(freqInCntTmp) << 8) + freqInTmp);
    }

    gTimer2IntCnt = 0;
}

/*在主程序里将guiFreqIn分两次从串口发出,就是上述的数字*/

* - 本贴最后修改时间:2006-11-12 11:19:04 修改者:xiaoxiong

9楼: >>参与讨论
zsmbj
你对中断优先级的理解是错误的。
在程序中,进入一个中断后,是关闭了全局中断的。退出后才打开。所以在一个中断里执行,另外一个高优先级的中断不会进来的。除非在中断程序中再次打开中断。

你的程序除了int1,和timer2还有timer1中断吧,比如说timer1中断执行的时间比较长。那就有可能导致错误出现。

还有你在int1里来判断的语句没有用处,因为在这个中断里,timer2即使溢出了也不会进入,要等到int1中断退出后才执行。所以这个恒为真。

建议:
单独测试,则只保留timer2中断和int12个中断程序。看看会出什么效果。

另外一个重点是要保障你输入的方波是绝对没有问题的。






10楼: >>参与讨论
农民讲习所
GET_FREQ_IN()错误
GET_FREQ_IN(); 是宏的话,一定是出错的地方。就是在读TCNT2时发生进位错误的。

__interrupt void SpeedCommand(void)
{
    UCHAR freqInTmp;
    UCHAR freqInCntTmp;

    T2停止

    freqInCntTmp= gTimer2IntCnt;              //读Timer2中断次数;
    freqInTmp = GET_FREQ_IN();                //宏,读Timer2计数值;
  
    if( T2中断标志 ){
       freqInCntTmp++;
    }
    T2打开


    CLEAR_FREQ_CNT();                         //宏,清Timer2计数值;

    if (freqInCntTmp == gTimer2IntCnt)       //判断是否有进位误差;
    {
        guiFreqIn = (((UINT)(freqInCntTmp) << 8) + freqInTmp);
    }

    gTimer2IntCnt = 0;
}

* - 本贴最后修改时间:2006-11-11 17:08:43 修改者:农民讲习所

11楼: >>参与讨论
xiaoxiong
高手!
zsmbj和农民讲习所:

谢谢你们的回答!我觉得你们俩才是真正看了我上面的文字!你们也真正有料的高手!
谢谢!!!

zsmbj:
“你对中断优先级的理解是错误的。”
Yes!!!
我确实对AVR的中断系统没有真正理解!中断不能嵌套的MCU我之前只用了PIC,但它只有一个中断向量,我还未遇到过类似情况!这次开始用AVR,虽然看了AVR的不嵌套中断系统,但实际应用时根本没有这种思维方式。
你说的非常对,我的系统中还有Timer0中断,代码还真不少,而且中断非常频繁,我支持你的说法!等我周一去验证!
谢谢您!

农民讲习所:
你所分析的,应该是可嵌套中断系统里发生的事。
如果是可嵌套中断系统,那你回答的应该是个非常满意的答案!
谢谢!
谢谢您!

祝大家更上一层楼!


                  精益求精,振兴中华民族!
         低制日货,狠打大和牲畜!

* - 本贴最后修改时间:2006-11-12 11:46:49 修改者:xiaoxiong

12楼: >>参与讨论
xiaoxiong
PIC应该也有这种情况出现。
正在吃饭,突然想到PIC的单一中断向量系统应该也会有类似问题出现才对。

不知各位什么意见?

13楼: >>参与讨论
hotpower
if (freqInCntTmp == gTimer2IntCnt)纯属废话
进入int1中断后AVR会自动关中断,T2中的gTimer2IntCnt不可能再变化,即使T2此时中断.
所以freqInCntTmp与gTimer2IntCnt是恒等的关系.再者也没必要用freqInCntTmp做暂存. 

14楼: >>参与讨论
xiaoxiong
“纯属废话”——马后炮!
“纯属废话”

是!是我没理解好非嵌套中断系统!
Sorry!

15楼: >>参与讨论
农民讲习所
修改部分和中断嵌套没关系,和T2是否运行有关系
读GET_FREQ_IN()时,T2可能溢出,gTimer2IntCnt就应该多+1。如果T2嵌套T1,不停止T2读GET_FREQ_IN(),一样可能T2可能溢出及gTimer2IntCnt改变。

所以再好是停T2读最好。

16楼: >>参与讨论
lucidmask
re
不明白为什么要CLEAR_FREQ_CNT();

17楼: >>参与讨论
xiaoxiong
我今天调出来了。
zsmbj:
“比如说timer1中断执行的时间比较长。那就有可能导致错误出现”
对!非常对!

农民讲习所 :
“所以再好是停T2读最好”
仔细想想,你说的还是有道理——不管是否可嵌套中断系统。

lucidmask:
"不明白为什么要CLEAR_FREQ_CNT();"
这是为计算下个周期的开启动作,就是清TCNT2值,从零开始计数。。。

To All:
我总结一下,希望我能写明白:
A、Timer2溢出时,CPU可能在任意其它中断程序里——这就造成溢出中断的滞后(推迟到INT1中断之后都有可能)!(04 03)
B、信号跳变时,有同样的问题存在——这就造成了外部中断INT1的滞后!(05 FE)
C、刚进INT1(尚未保护现场)到读TCNT2前这段时间,如果Timer2发生溢出——这就造成进位误差!(可能会出现04 00,04 01)

哈哈。。。这个非嵌套中断系统带来的问题还真不少!不知道ATMEL为什么这样设计,为的哙?难道还有其它优点?

18楼: >>参与讨论
zsmbj
所以说这个方案最好的就是使用icp。
是实现了硬件对2个沿的时间处理,不会有误差。建议你的方案把timer1用来做icp。



19楼: >>参与讨论
xiaoxiong
我也想啊!
可是16位的Timer只有Timer1一个啊!!!

参与讨论
昵称:
讨论内容:
 
 
相关帖子
请问AVRISP  MKii的6个引脚分别接什么?(原来用10脚的座)
ATMEGA8-16AC可否用ATMEGA8-16PC替换
哪位有proteus的M48库?
11.7-8日的西安 全国单片机与嵌入式系统展览会
求教
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入


Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号