打印

STM32为啥进定时器中断一定要有这样一句

[复制链接]
14195|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
eehomer|  楼主 | 2012-3-13 21:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
为啥进定时器中断一定要有这样一句if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
否则只能进一次中断,第二次就进不去了 怎么回事?:'(折腾我2个小时了。
沙发
logokfu| | 2012-3-14 00:00 | 只看该作者
这个是中断标志位检测函数啊。明白?

使用特权

评论回复
板凳
eehomer|  楼主 | 2012-3-14 09:47 | 只看该作者
2# **kfu
这个我明白。
因为我只使能了一个定时器的事件更新中断,所以我以为不检测,直接执行中断服务就可以了?
我不明白的是:为啥没有这句进了一次中断,第二次就进不了呢?

使用特权

评论回复
地板
sjnh| | 2012-3-14 10:40 | 只看该作者
这句没有没关系,有关系的是这个if条件里面的语句,你没贴出来(我的一直没有这句,但有if条件里面的语句)

使用特权

评论回复
5
yzzly| | 2012-3-14 12:41 | 只看该作者
谁说一定要有?我就不用。
void TIM2_IRQHandler(void)
{
        Tim2Cnt++;
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
}

使用特权

评论回复
6
eehomer|  楼主 | 2012-3-14 13:09 | 只看该作者
本帖最后由 eehomer 于 2012-3-14 13:12 编辑

完整的是这样的:
void TIM2_IRQHandler(void)
{
  if((TIM2->SR)&(1<<0))
  {
    if((GPIOC->ODR)&(1<<0))
    {
     GPIOC->BRR |= (1<<0);
    }
    else
    {
     GPIOC->BSRR |= (1<<0);   
    }
  }
  TIM2->SR = ~(1<<0);
}
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
其中 if((TIM2->SR)&(1<<0))和if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)一样的,我不知道为啥不能去掉这句。

使用特权

评论回复
7
eehomer|  楼主 | 2012-3-14 13:14 | 只看该作者
我写的定时器初始化
void timer2_init(void)
{
  RCC->APB1ENR |= (1<<0);              //TIM2 timer clock enable

  TIM2->PSC = 0x7F;
  TIM2->ARR = 0xFFFF;
  TIM2->CR2 &= ~(7<<0);                //Slave mode disable
  TIM2->CR1 |= (1<<7);                 //Auto-reload preload enable
  TIM2->CR1 &= ~(3<<5);                //Edge-aligned mode
  TIM2->CR1 &= ~(1<<4);                //Counter used as upcounter
  TIM2->CR1 |= (1<<2);                 //Only counter overflow/underflow generates an update interrupt or DMA request if enable       
  TIM2->CR1 &= ~(1<<1);
  TIM2->CR1 |= (1<<0);
  TIM2->DIER |= (1<<0);                //Update interrupt enable
  //TIM2->DIER |= (1<<6);
}
NVIC设置:
void NVIC_Config(void)
{
  //SCB->VTOR = ((uint32_t)0x08000000);
  NVIC->ISER[28>>0x05] = 1<<28;
}

使用特权

评论回复
8
eehomer|  楼主 | 2012-3-14 13:16 | 只看该作者
4楼、5楼两位好:我晚上回去再好好查下,看下是不是别的地方弄错了。

使用特权

评论回复
9
香水城| | 2012-3-14 14:10 | 只看该作者
LZ加上那个语句后的程序是什么样的?

使用特权

评论回复
10
eehomer|  楼主 | 2012-3-14 15:34 | 只看该作者
9# 香水城
您好,在6楼。

使用特权

评论回复
11
香水城| | 2012-3-14 18:59 | 只看该作者
9# 香水城
您好,在6楼。
eehomer 发表于 2012-3-14 15:34


我的意思是加上这句后是什么样的:if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)

6楼程序里没有这句。

使用特权

评论回复
12
nongfuxu| | 2012-3-14 21:05 | 只看该作者
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)

这是查询中断语句,判断有中断时清相应中断标志位。

使用特权

评论回复
13
eehomer|  楼主 | 2012-3-14 21:13 | 只看该作者
本帖最后由 eehomer 于 2012-3-14 23:01 编辑

11# 香水城
您好,因为我没有说清楚,把您给弄糊涂了,不好意思。
是这样的,因为我没有用库,所以没有加这if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
我在网上看到别人的程序有这样一句,我就用if((TIM2->SR)&(1<<0))来代替
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)。
所以6楼的程序里没有
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET),而是
if((TIM2->SR)&(1<<0))。
在中断服务里没有
if((TIM2->SR)&(1<<0)),似乎程序只能进一次中断,加了就好了。我是定时LED闪烁。
完整的程序是
void TIM2_IRQHandler(void)
{
  if((TIM2->SR)&(1<<0))
  {
    if((GPIOC->ODR)&(0x01))
    {
      GPIOC->BRR |= (1<<0);      
    }
    else
    {
      GPIOC->BSRR |= (1<<0);      
    }
  }
  TIM2->SR &= ~(1<<0);
}

int main(void)
{
  /*使能GPIOC*/
  RCC->APB2ENR |= (1<<4);
  /*GPIOC推挽输出 50MHz*/
  GPIOC->CRL &= ~(3<<2);
  GPIOC->CRL |= (3<<0);
  /*使能GPIOA*/
  RCC->APB2ENR |= (1<<2);
  /*GPIOC推挽输出 50MHz*/
  GPIOA->CRH &= ~(3<<2);
  GPIOA->CRH |= (3<<0);

  //hc595_init();
  //send_2byte_hc595(0x65,0x65);
  NVIC_Config();
  timer2_init();
  while(1)
  {

  }
}

void timer2_init(void)
{
  RCC->APB1ENR |= (1<<0);              //TIM2 timer clock enable

  TIM2->PSC = 0x7F;
  TIM2->ARR = 0xFFFF;
  TIM2->CR1 |= (1<<7);                 //Auto-reload preload enable
  TIM2->CR1 &= ~(3<<5);                //Edge-aligned mode
  TIM2->CR1 &= ~(1<<4);                //Counter used as upcounter
  TIM2->CR1 |= (1<<2);                 //Only counter overflow/underflow generates an update interrupt or DMA request if enable   
  TIM2->CR1 &= ~(1<<1);
  TIM2->CR1 |= (1<<0);
  TIM2->DIER |= (1<<0);                //Update interrupt enable
  //TIM2->DIER |= (1<<6);
}
void NVIC_Config(void)
{
  //SCB->VTOR = ((uint32_t)0x08000000);
  NVIC->ISER[28>>0x05] = 1<<28;
}

使用特权

评论回复
14
eehomer|  楼主 | 2012-3-14 21:49 | 只看该作者
本帖最后由 eehomer 于 2012-3-14 21:53 编辑

是的,我也觉得不是if((TIM2->SR)&(1<<0))或者if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)的原因了。因为我现在把中断服务函数改成下面的都可以实现LED闪烁,注意最后一句红色的if((TIM1->CR1)&(8)==1):即使做这样一个判断LED都可以闪烁,这个很诡异:我用的是TIM2,这句检查的却是TIM1->CR,而且删掉这句LED就不闪了。
void TIM2_IRQHandler(void)
{  if((GPIOC->ODR)&(0x01))
    { GPIOC->BRR |= (1<<0);}  
    else  
    { GPIOC->BSRR |= (1<<0);}
    TIM2->SR &= ~(1<<0);
    if((TIM1->CR1)&(8)==1);

}

使用特权

评论回复
15
香水城| | 2012-3-15 12:36 | 只看该作者
怀疑是时序的问题。

请把清中断标志的语句TIM2->SR &= ~(1<<0);  移到中断程序的开始试试看,应该不需要14楼的红色语句。

使用特权

评论回复
16
eehomer|  楼主 | 2012-3-15 20:35 | 只看该作者
15# 香水城
我试了,可以。但不知道为啥要这样。

使用特权

评论回复
17
eehomer|  楼主 | 2012-3-15 20:50 | 只看该作者
这个现象很诡异,我也没看到哪里说要进中断就清中断标志,而且其实进中断不清中断表示也是可以的,例如我在14楼的程序,这让我觉得这是芯片本身的问题,因为我搜了下,别人也遇到过这种莫名其妙的问题。

使用特权

评论回复
18
香水城| | 2012-3-16 11:32 | 只看该作者
这个现象很诡异,我也没看到哪里说要进中断就清中断标志,而且其实进中断不清中断表示也是可以的,例如我在14楼的程序,这让我觉得这是芯片本身的问题,因为我搜了下,别人也遇到过这种莫名其妙的问题。 ...
eehomer 发表于 2012-3-15 20:50


这是因为从执行清中断的语句到中断标志被清除需要一点时间,如果你在中断处理程序结束时执行清中断语句,然后马上退出中断程序,此时中断标志还未被清除,结果导致返回出错。

使用特权

评论回复
19
eehomer|  楼主 | 2012-3-16 12:50 | 只看该作者
18# 香水城
虽然说得有一定道理,但是我之前没有按你的要求去做,也是在最后才清中断,也碰巧可以,而且像5楼那位朋友贴出来的程序也是在最后清中断,也没发生问题。这就说明了这个问题确实诡异。说实话我觉得这是芯片的bug。

使用特权

评论回复
20
mage心寒| | 2012-4-23 16:54 | 只看该作者
哎兄弟们定时器都搞完了。。我刚开始啊。。而且我用的是2XX系列的,论坛里面好少哇。。。:Q

使用特权

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

本版积分规则

0

主题

130

帖子

1

粉丝