|
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统 驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe |
M48的中断机制导致计时失误! |
作者:xiaoxiong 栏目:单片机 |
我用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 于 2006/11/10 19:57:00 发布:
这不能说明问题。 如果int1中断的时候刚好在另外一个中断里执行,一般是不会进入int1中断的。除非等到那个中断执行完成。所有有可能导致某一个沿的时间被延迟了。 和你的64分频没有任何关系啊。 其实你的这个方案最好的方法是用ICP功能,就是检测两个沿的间隔时间,由于这个时间是由硬件实现的,所以不会有误差。 |
3楼: | >>参与讨论 |
作者: xwj 于 2006/11/10 20:07:00 发布:
晕,这是什么鬼语法,看得真别扭! 要注意串口的非适时性 LZ,还是把你的程序贴出来吧 |
4楼: | >>参与讨论 |
作者: 农民讲习所 于 2006/11/10 20:14:00 发布:
读TCNT2时,如果处于低位向高位进位时刻 read TCNT2有出错机会,就是楼主的问题。所以再读出TCNT2后再比较TCNT2高位是否不变,变再读一次即可。(正处于进位时刻) |
5楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/10 22:13:00 发布:
大家慢慢看!!! ”最好的方法是用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 于 2006/11/10 22:15:00 发布:
还有。。。 “所以再读出TCNT2后再比较TCNT2高位是否不变,变再读一次即可” 我的“if (timer2IntCunt not change)”就是这个意思! 对于串口,我是用局部变量把TCNT2和timer2IntCunt存下来,再发给PC的,所以不会有实时不实时的事! * - 本贴最后修改时间:2006-11-10 22:20:01 修改者:xiaoxiong |
7楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/10 22:21:00 发布:
如果明天我还没解决! 那我就把原码的片段拷上来给大家看看。 谢谢大家的时间!!! * - 本贴最后修改时间:2006-11-10 22:46:11 修改者:xiaoxiong |
8楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/11 13:17:00 发布:
原码: /*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 于 2006/11/11 14:22:00 发布:
你对中断优先级的理解是错误的。 在程序中,进入一个中断后,是关闭了全局中断的。退出后才打开。所以在一个中断里执行,另外一个高优先级的中断不会进来的。除非在中断程序中再次打开中断。 你的程序除了int1,和timer2还有timer1中断吧,比如说timer1中断执行的时间比较长。那就有可能导致错误出现。 还有你在int1里来判断的语句没有用处,因为在这个中断里,timer2即使溢出了也不会进入,要等到int1中断退出后才执行。所以这个恒为真。 建议: 单独测试,则只保留timer2中断和int12个中断程序。看看会出什么效果。 另外一个重点是要保障你输入的方波是绝对没有问题的。 |
10楼: | >>参与讨论 |
作者: 农民讲习所 于 2006/11/11 17:03:00 发布:
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 于 2006/11/12 11:17:00 发布:
高手! zsmbj和农民讲习所: 谢谢你们的回答!我觉得你们俩才是真正看了我上面的文字!你们也真正有料的高手! 谢谢!!! zsmbj: “你对中断优先级的理解是错误的。” Yes!!! 我确实对AVR的中断系统没有真正理解!中断不能嵌套的MCU我之前只用了PIC,但它只有一个中断向量,我还未遇到过类似情况!这次开始用AVR,虽然看了AVR的不嵌套中断系统,但实际应用时根本没有这种思维方式。 你说的非常对,我的系统中还有Timer0中断,代码还真不少,而且中断非常频繁,我支持你的说法!等我周一去验证! 谢谢您! 农民讲习所: 你所分析的,应该是可嵌套中断系统里发生的事。 如果是可嵌套中断系统,那你回答的应该是个非常满意的答案! 谢谢! 谢谢您! 祝大家更上一层楼! 精益求精,振兴中华民族! 低制日货,狠打大和牲畜! * - 本贴最后修改时间:2006-11-12 11:46:49 修改者:xiaoxiong |
12楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/12 12:01:00 发布:
PIC应该也有这种情况出现。 正在吃饭,突然想到PIC的单一中断向量系统应该也会有类似问题出现才对。 不知各位什么意见? |
13楼: | >>参与讨论 |
作者: hotpower 于 2006/11/12 12:23:00 发布:
if (freqInCntTmp == gTimer2IntCnt)纯属废话 进入int1中断后AVR会自动关中断,T2中的gTimer2IntCnt不可能再变化,即使T2此时中断. 所以freqInCntTmp与gTimer2IntCnt是恒等的关系.再者也没必要用freqInCntTmp做暂存. |
14楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/12 21:33:00 发布:
“纯属废话”——马后炮! “纯属废话” 是!是我没理解好非嵌套中断系统! Sorry! |
15楼: | >>参与讨论 |
作者: 农民讲习所 于 2006/11/12 21:45:00 发布:
修改部分和中断嵌套没关系,和T2是否运行有关系 读GET_FREQ_IN()时,T2可能溢出,gTimer2IntCnt就应该多+1。如果T2嵌套T1,不停止T2读GET_FREQ_IN(),一样可能T2可能溢出及gTimer2IntCnt改变。 所以再好是停T2读最好。 |
16楼: | >>参与讨论 |
作者: lucidmask 于 2006/11/13 11:01:00 发布:
re 不明白为什么要CLEAR_FREQ_CNT(); |
17楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/13 21:22:00 发布:
我今天调出来了。 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 于 2006/11/13 21:32:00 发布:
所以说这个方案最好的就是使用icp。 是实现了硬件对2个沿的时间处理,不会有误差。建议你的方案把timer1用来做icp。 |
19楼: | >>参与讨论 |
作者: xiaoxiong 于 2006/11/13 21:34:00 发布:
我也想啊! 可是16位的Timer只有Timer1一个啊!!! |
|
|
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入 |
Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号 |