打印

(原创)一个很基础,也很容易出问题的中断---欢迎大家讨

[复制链接]
楼主: 一朝成名
手机看帖
扫描二维码
随时随地手机跟帖
21
zealane| | 2008-1-19 22:55 | 只看该作者 回帖奖励 |倒序浏览

如果16位cpu

如果16位cpu,是否就不会发生存取错误。。。

使用特权

评论回复
22
AIRWILL| | 2008-1-20 14:00 | 只看该作者

10楼分析得有理,不过细节上有出入

" 问题一般出在255跳变的256的时候 

关键在if(count > 250)这句.

可能被中断捣乱为count=0~~~(实际为256)"


 看看 keil C 对 if(count > 250) 的编译结果:

                        SETB    C
                 R     MOV     A,count+01H ;------(1)
                       SUBB    A,#00H
                 R     MOV     A,count     ;------(2)
                       SUBB    A,#0FAH
                 R     xJLT    ?C0546

假如在指令 (1) 后和 (2) 前发生中断,并且,中断将 count 值 由260 更新为 251, 这里执行情况是 count = 0, count+01H =4 (好象count = 4)的情况.

于是, 2楼的问题就出现了.
这样的问题很头痛,因为即使用DEBUG 仿真器调试, 也不会发现 count = 4 的情况!

不过,突然我想,如果这样写中断服务,能不能解决问题?

#pragma vector = TIMER1_COMPA_vect
__interrupt void my_interrupt_routine(void) //定时中断
{
    count--;        //count = 251~260
    if(count < 251)
    {
        count = 260;
    }
    flag = 1;
}

当然: main()的初始化也得变动一下.

使用特权

评论回复
23
fabest| | 2008-1-20 22:05 | 只看该作者

...........................

这个问题是有点头痛.一不小心很容易搞错....
#pragma vector = TIMER1_COMPA_vect
__interrupt void my_interrupt_routine(void) //定时中断
{
    count++;        //count = 251~260
    if(count > 250) flag_1=1;//能不能将这条语句加在中断里...
    else flag_1=0;
    if(count > 260)
    {
        count = 251;
    }
    
    flag = 1;
    
}

使用特权

评论回复
24
一朝成名|  楼主 | 2008-1-22 10:45 | 只看该作者

沉了......

使用特权

评论回复
25
smartpower| | 2008-1-22 11:55 | 只看该作者

我来提一种在这个程序上可用的方法

#include <iom48.h>
#include <inavr.h>

unsigned int count;
unsigned long sum;
unsigned long error;
unsigned char flag;

#pragma vector = TIMER1_COMPA_vect      //这个中断函数不变
__interrupt void my_interrupt_routine(void) //定时中断
{
    count++;        //count = 251~260
    
    if(count > 260)
    {
        count = 251;
    }
    
    flag = 1;
    
}

void tmr1_ini() ////定时中断初始化
{
    TCNT1  = 0x00;
    
    OCR1A  = 80;
    TIMSK1 = 0x02;
    
    TCCR1A = 0x00;
    TCCR1B = 0x09;
}

void main(void)
{
    unsigned int buf;   //增加此变量
    
    count = 251;
    sum = 0;
    error = 0;
    
    tmr1_ini();
    __enable_interrupt();
    
    while(sum < 100000)
    {
        if(flag > 0)
        {
            sum++;
            flag = 0;
        }
        
        do                      //增加这四句,
        {                       //
            buf = count;        //
                                //
        }while( buf != count);  //
        
        
        if( buf > 250 )         //更改这一名
        {
            __delay_cycles(2);  //一定执行这句话
        }
        else
        {
            error++;            //改好后就一定不会执行这句话
        }
    }
    
    
    while(1)                    //下断点,看error的数值,这下可就一定是0了
    {
        __delay_cycles(2);
        __delay_cycles(2);
        __delay_cycles(2);
    }
}

使用特权

评论回复
26
AIRWILL| | 2008-1-22 12:33 | 只看该作者

就事论事的简单办法

        
void main(void)
{
    count = 251;
    sum = 0;
    error = 0;
    
    tmr1_ini();
    __enable_interrupt();
    
    while(sum < 100000)
    {
        if(flag > 0)
        {
            sum++;
            flag = 0;
        
            if(count > 250)         //count = 251~260
            {
                __delay_cycles(2);  //按理一定执行这句话
            }
            else
            {
                error++;            //现在没有机会执行这句话了
            }
       }
     }
    
    
    while(1)                    //下断点,看error的数值
    {
        __delay_cycles(2);
        __delay_cycles(2);
        __delay_cycles(2);
    }
}

    
    
    

使用特权

评论回复
27
wuxi_stl| | 2008-1-22 14:56 | 只看该作者

26L的修改似乎变更了逻辑关系!

使用特权

评论回复
28
hq_y| | 2008-1-22 14:58 | 只看该作者

smartpower?俺注册一个coldpower

使用特权

评论回复
29
smartpower| | 2008-1-22 16:02 | 只看该作者

这么说我的兄弟要诞生了?

coldpower?兄弟?那的的?

使用特权

评论回复
30
IceAge| | 2008-1-22 23:20 | 只看该作者

这个问题,避开中断的打断固然是个解决办法

不过很牵强。从设计的角度看,不算是好的解决方案,因为中断与主程序之间成为 "强" 关联。更好一些的办法应该是:通知。count 不应该认为的骨肉分离,定时到了后,设置 timeout 标志通知出去,这样程序更清晰明确(标志只有真假两个值),同时也避免了潜在的风险(16-bit 的cpu 不是解决之道,还有 32-bit 的问题)。

另一种方法,基本上不存在此类的问题,就是中断驱动,亦即原来的所谓主程序全部放入中断中,现在的"主" 程序简单的休眠等待中断,或是 做一些 On_Idle 后台工作。

使用特权

评论回复
31
windymeng| | 2008-1-23 18:48 | 只看该作者

沉思中`

看了你们的留言```哎```感觉真的很惭愧```自己没学什么家伙``

使用特权

评论回复
32
zhuhai2004| | 2008-1-23 22:54 | 只看该作者

有的CPU提供16位的寄存器是否有这方面的考虑哦?

使用特权

评论回复
33
一朝成名|  楼主 | 2011-8-24 23:41 | 只看该作者
好多年的帖子了。。。现在看看,恍如隔世啊。。。。。

使用特权

评论回复
34
lisijun100| | 2011-8-25 00:24 | 只看该作者
:lol 学习之

使用特权

评论回复
35
原野之狼| | 2011-8-25 00:36 | 只看该作者
不容易 赠条裤子吧:lol

使用特权

评论回复
36
DownCloud| | 2011-8-25 01:47 | 只看该作者
35# 原野之狼
这么久才给酷啊! 问你一个问题啊, count不是 int 型吗? 他们说 count=256时为0,我有点不解, 应该是 0x0100 (256)吧? 又不是char型的。。。

使用特权

评论回复
37
DownCloud| | 2011-8-25 02:09 | 只看该作者
知道了,是读count的时候又进了中断呀。。。
额。。。

使用特权

评论回复
38
天地良芯| | 2011-8-25 09:29 | 只看该作者
学习了。。

使用特权

评论回复
39
一朝成名|  楼主 | 2011-8-25 10:06 | 只看该作者
不容易 赠条裤子吧:lol
原野之狼 发表于 2011-8-25 00:36


话说,年少的时候,讨论的一些问题还是蛮有技术含量的

哈哈哈

使用特权

评论回复
40
刘前辈| | 2011-8-25 12:04 | 只看该作者
#LZ:
解决中断带来的问题的方法:
1、
2、
3
4、
5、


果真原创,提醒一点书上没强调的:
    关中断虽然有这样那样的危险性,但是:当中断ISR 和用户任务之间存在共享资源时,关中断是唯一的互斥处理方法。

LZ的2、3、4、5、是任务之间的通用互斥方法。根本不适用于中断ISR。举个例子:

1、谁都知道,“信号量”是一种睡眠锁。中断ISR里玩睡眠锁?
2、谁都知道,“自旋锁”用于时间片循环调度内核,中断ISR里玩自旋锁?测谁等谁呀?


、、

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则