搜索
bottom↓
回复: 6

主函数和中断服务函数的分时执行

[复制链接]

出0入0汤圆

发表于 2012-9-10 17:09:43 | 显示全部楼层 |阅读模式
本帖最后由 gzyavr 于 2012-9-10 17:28 编辑

单片机的主程序和中断程序的执行的关系:
在没有中断的时候,在主程序的while中循环执行,当中断条件到,那么暂停主程序,进入中断服务函数运行。中断函数运行完后,返回主函数的中断处继续执行。

那么现在我用定时器实现了一个1ms的的中断。需要实现这样的一个效果:
全局变量赋值(进入中断的次数)。初值=10000,计时十分钟。十分钟后需要执行一段特定的程序,但是没有到十分钟的时候,主程序还是在执行者其它的函数。它的执行过程是这样的吧(每隔1ms进中断一次,断断续续的执行着主函数)
以下是实验程序【计时1s】:
u16 s;       //全局变量
bool time_mark;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~延时
void delay_ms(unsigned int ms)
{
unsigned int ti;
while(ms--)
{
for(ti=0;ti<200;ti++){} //1421
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~中断初始化设置
void Tim5_Init(void)
{
        TIM5->PSCR=0X02;   //4分频,3.6864M晶振的到得计数频1us
        TIM5->ARRH =0x03;  //1000次
        TIM5->ARRL =0xe8;
        TIM5->EGR=0X01;     // 软件产生一次中断 更新寄存器中值
        TIM5->IER|=0x01;     //允许溢出中断。
         _asm("RIM") ;           //开全局中断
        TIM5->CR1|=0X80;    //使能计数器,使能预装载,向上计数方式。
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~中断服务函数
@far @interrupt void TIM5_Server_Interrupt(void)
{
         _asm("SIM") ; //关全局中断
   s--;
  if(s<1)
   {
         time_mark=1;
         TIM5->CR1&=0xfe;  //关比定时器
    }
        TIM5->SR1&=0xfe;  //清除中断标志
        _asm("RIM");          //开全局中断
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~主函数文件
bool n=0;
extern time_mark;
extern  s;

void main(void)
{
        CLK_HSECmd(ENABLE);
        Tim5_Init();
        GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_OUT_PP_HIGH_FAST);//推挽输出低电平
        GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST);
  /* Infinite loop */
        while (1)
    {
           if(n==0)
                {
                 TIM5->CR1|=0X01;               //开延时中断 延时10分钟关闭路灯的啦。
                s=1000;
                 n=1;                                  //仅给延时赋一次种?
                 GPIO_WriteLow(GPIOD, GPIO_PIN_6);
                 }
       
                 GPIO_WriteHigh(GPIOD, GPIO_PIN_0);
                delay_ms(1000);
                 GPIO_WriteLow(GPIOD, GPIO_PIN_0);
                delay_ms(1000);
               
                if(time_mark==1)               //进入中断的次数完成标志
               {
                 time_mark=0;                   //标记清除
                 n=0;                               //赋值标记清除,可再次进入赋值
                 GPIO_WriteHigh(GPIOD, GPIO_PIN_6);
                delay_ms(500);
                }
      }
}
但是现在:
我如果改变延时函数为delay_ms(2000)的话,        if(time_mark==1){}  的这部分就不会执行了。这是为什么?这段延时怎么会影响中断呢??
按照我的理解应该是:我计时10分钟的话:
S=10000,然后计时器开始计时,每1ms进中断一次,在中断里面减S一次。出中断继续执行主程序中的可执行程序。待10000次中断后,执行一次if(time_mark==1){}。而主程序中的延时是完全不会影响中断的。但是事实是影响到了中断。这是什么原因呢?

出0入4汤圆

发表于 2012-9-10 17:44:53 | 显示全部楼层
都用定时了,还用延时?可以复用啊。

出0入0汤圆

发表于 2012-9-10 17:48:49 | 显示全部楼层
这个已经不是实时操作了,中断都是毫秒触发的,你延时这么久,问题自然多了

出0入0汤圆

 楼主| 发表于 2012-9-10 18:04:48 | 显示全部楼层
Keller 发表于 2012-9-10 17:48
这个已经不是实时操作了,中断都是毫秒触发的,你延时这么久,问题自然多了 ...

中断怎么和延时有关系呢,中断条件到了就进入中断服务函数执行,暂停主函数。当中断执行完成,再继续执行主函数。怎么会出问题呢。。哎
本人大菜鸟,很长时间没有搞单片机了,现在又开始重新拾起来了。有些简单的东西都通不过了,希望哥们多多指教啊

出0入0汤圆

 楼主| 发表于 2012-9-10 18:10:07 | 显示全部楼层
fulitun 发表于 2012-9-10 17:44
都用定时了,还用延时?可以复用啊。

可以的,刚才是调试阶段,就那样的了。。呵呵。谢谢啊

出0入0汤圆

 楼主| 发表于 2012-9-17 11:21:48 | 显示全部楼层
待解答。。

出0入0汤圆

 楼主| 发表于 2012-9-19 11:48:54 | 显示全部楼层
本帖最后由 gzyavr 于 2012-9-19 11:57 编辑

问题解决:
原因是因为在定时中断服务函数中标志位time_mark赋值为1后出中断。但是这个时候由于delay延时的过长,而不能正常进入与其相关的对应的函数中。就这样如中断,出中断进入delay.
大概就是这个原因的。

还有个问题就是bool这个定义的枚举变量。是用工程里面的定义的,枚举变量中所定义的枚举元素给其赋值。“只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量”
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-30 16:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表