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

[复制链接]
 楼主| 一朝成名 发表于 2008-1-18 10:08 | 显示全部楼层 |阅读模式
闲来没事,发个总结供大家消遣。希望高手补充指正。
在此我没有区分51系统和嵌入式系统定义,可同等看待。

51系统&嵌入式系统————中断下的一切可能
我对中断的理解:
    中断分硬件中断、软件中断
    中断是前台程序程序调度的入口,异步事件处理的入口,CPU和外部沟通的桥梁,系统节拍的由来等等,所以可以说中断是系统的心脏是操作系统的一切。
    中断也随之带来了很多问题,我对中断所带来的问题的总结是:中断之下皆有可能,中断带来了一切不可“预知”的问题。中断问题是我们写程序架构的时候首要应该避免的问题,以免等写完程序才发现出现架构的不合理性,以及在后期调试或者运行当中出现很多“奇怪”和一些不便于查找的问题。
    并发和竞争的问题:当一个异步中断(事件)产生时,此时CPU处理程序的情况是不可预知的,我们不知道他运行到那里了,正在执行那个程序,那个数据结构,而当中断要求占有正在执行的资源的时候就出现了并发和竞争的问题,在次情况下,很有可能出现资源被改写的可能,而当中断返回后,CPU却要执行错误的程序或者资源。
    
解决中断带来的问题的方法:
1、    最简单的方法:关闭中断,防止一切的异步事件的发生当然就防止竞争的出现,避免了对当前程序或者资源的干扰。问题:如果当前程序执行的很长就导致了CPU丢失中断时间,造成有些事件不能被处理,所以我们要保证关闭中断的时间尽量的短。
2、    改写函数为重入性函数,这样中断只能改写函数的局部参数而不能修改全局参数从而解决了中断带来的问题。问题:在51有限资源下频繁的使用重入性函数会造成很大的资源浪费。
3、    操作系统中提到的“原子操作”,如同51下的单字节指令、标志位,这样一来非此即彼,解决了并发的可能。问题:复杂的程序操作是不可能只有单字节指令操作的,多字节操作起来就很难达到期望的效果。
4、    操作系统中提到的“信号量”的概念,其也就是高级的标志位。
在51系统当中也可以引进此概念,构造一个简单的信号量,可以解决多任务抢占资源的问题。
5、“自旋锁”的概念等等,除此之外在操作系统中有很多细分的方法应对不同的场合,可以解决中断所带来的的问题。
经验感觉:
    除了上述的一些方法之外,当我们写程序架构的时候应该做到“中断程序”
和“主程序”之间要有界限,不能互相干扰,如果一些实时性要求很高的程序可以放在中断程序中执行,但是要保证函数的简短,防止中断嵌套带来的问题或者死循环等。



 2008年1月16日晚
   by一朝成名


 楼主| 一朝成名 发表于 2008-1-18 10:12 | 显示全部楼层

借花献佛转smartpower的程序

#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)
{
    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);
    }
}

 
大家想这程序出问题的原因是什么
想想这个程序改进的方法是什么
想通了这个也许对大家有点帮助
IceAge 发表于 2008-1-18 10:46 | 显示全部楼层

8-bit 的cpu 上 16-bit 的 count 的存取

至少两条指令,而中断有可能发生在此间。

更好的做法是不要认为把 count 分开,也可以使用另一种结构: 中断驱动。
LastNew 发表于 2008-1-18 13:06 | 显示全部楼层

好学习

学习
LastNew 发表于 2008-1-18 13:33 | 显示全部楼层

IceAge老师

3楼: 8-bit 的cpu 上 16-bit 的 count 的存取 

至少两条指令,而中断有可能发生在此间。

更好的做法是不要认为把 count 分开,也可以使用另一种结构: 中断驱动。


中断驱动是啥子意思 
 
hotpower 发表于 2008-1-18 13:46 | 显示全部楼层

count做全局变量不关中断读16位是会出问题的

所以俺喜欢静态局部变量~~~
 楼主| 一朝成名 发表于 2008-1-18 14:18 | 显示全部楼层

~~~hot大叔顺便给俺指点两句

不知道俺的理解有没有错误或者其他的什么问题
sz_kd 发表于 2008-1-18 14:22 | 显示全部楼层

好东西

ayb_ice 发表于 2008-1-18 16:45 | 显示全部楼层

必要时关中断

一般是合作处理,比如中断读取后设标志,主循环先判断标志再使用。
hotpower 发表于 2008-1-18 17:00 | 显示全部楼层

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

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

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

 
5880527 发表于 2008-1-18 17:01 | 显示全部楼层

有很多时候不能关中断的,比如高速计数

就半截数据的问题嘛,在中断中每次修改数据时把一标志位置为1,主循环读数据之前清一下此标志,读完后再判一下此标志,如果被置位1了则数据被修改过了再读一下就是,读到的数据放到R之类的积存器慢慢享用,当然这是汇编哈,C不知道咋收拾了
hotpower 发表于 2008-1-18 17:04 | 显示全部楼层

不中断2次读较保险

55953797 发表于 2008-1-18 17:06 | 显示全部楼层

听课

ayb_ice 发表于 2008-1-19 08:31 | 显示全部楼层

还可以飞读,很多都有硬件飞读功能

LastNew 发表于 2008-1-19 09:30 | 显示全部楼层

支持不中断读2次

支持不中断读2次
55953797 发表于 2008-1-19 09:45 | 显示全部楼层

支持5880527

dld2 发表于 2008-1-19 09:47 | 显示全部楼层

总觉得关中断很暴力

hotpower 发表于 2008-1-19 10:17 | 显示全部楼层

哈哈~~~现在时髦很黄很暴力~~~OS都这么黄色~~~

xwj 发表于 2008-1-19 10:21 | 显示全部楼层

嗯,这个帖子里很黄很暴力 ,我赶紧关了

55953797 发表于 2008-1-19 10:43 | 显示全部楼层

51 关中断

在51关中断可以考虑,来中断后中断标志有效,开中断后系统根据中断标志再响应中断,只是时间被推迟了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

3299

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部