打印
[STM32F4]

定时器无法进入中断

[复制链接]
8392|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
使用的是STM32F407的Discovery板,用的库是官方的库。只是简单的配置定时器2,然后通过定时器中断实现LED的闪烁,结果定时器中断进不去,查看断点执行的时候,中断服务程序中的flag数值的变化也很混乱,不知道什么原因,麻烦大家帮忙看看是不是配置有问题。。。
#include"stm32f4_discovery.h"
#include"stm32f4xx.h"

void led(int n);
void tim_config(void);
int flag=0;
void main()
{
  SystemInit();
  
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_14;            
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /*端口模式为输出 */
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*输出类型 推挽输出 */
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  tim_config();
}


void tim_config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //响应优先级为 0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //通道中断使能
  NVIC_Init(&NVIC_InitStructure);
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = 9999;
  TIM_TimeBaseStructure.TIM_Prescaler = 7199;//定时1s

  TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
  TIM_ClearFlag(TIM2,TIM_FLAG_Update);   
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   
  TIM_Cmd(TIM2,ENABLE);
  
  
}

void led(int n)
{
    if(n==0){
      GPIO_SetBits(GPIOD,GPIO_Pin_12);
      GPIO_SetBits(GPIOD,GPIO_Pin_14);
    }
    else if(n==1){
      GPIO_ResetBits(GPIOD,GPIO_Pin_12);
      GPIO_ResetBits(GPIOD,GPIO_Pin_14);  
   
    }
}

void TIM2_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  {
    TIM_ClearFlag(TIM2,TIM_FLAG_Update);
    led(flag);
    flag=!flag;
  }
}

void Delay(uint32_t nCount)
{
while (nCount--);
}


#ifdef  USE_FULL_ASSERT

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  while (1)
  {}
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
沙发
mmuuss586| | 2014-10-16 12:19 | 只看该作者

简单点,装个STM32 CUBE软件生成代码看看;

使用特权

评论回复
板凳
mmuuss586| | 2014-10-16 12:26 | 只看该作者
1、中断程序没问题;
2、定时器初始化
好像少了TIM_PrescalerConfig(TIM2, 13, TIM_PSCReloadMode_Immediate );
下面是我的程序:

        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
                /* Time base configuration */
                TIM_TimeBaseStructure.TIM_Period =TIM_Period;
                TIM_TimeBaseStructure.TIM_Prescaler = 0;                //¶¨Ê±Æ÷ʱÖÓ·ÖƵ
                TIM_TimeBaseStructure.TIM_ClockDivision = 0;        //²ÉÑù·ÖƵ
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //ÏòÉϼÆÊý
                TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
          TIM_PrescalerConfig(TIM2, 13, TIM_PSCReloadMode_Immediate );
          TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
          TIM_Cmd(TIM2, ENABLE);

使用特权

评论回复
地板
mmuuss586| | 2014-10-16 12:30 | 只看该作者
3、中断初始化也也没问题;
你的分频值不对,你的主频72M吗?

使用特权

评论回复
5
mmuuss586| | 2014-10-16 12:37 | 只看该作者
刚才乱码现在改了
//对84MHz(TIM3时钟源为168MHz/2)进行TIM_scale分频后作为计数时钟
void        TIM2_Init(u32 TIM_Period)//TIM_Period为16位的数
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
                /* Time base configuration */
                TIM_TimeBaseStructure.TIM_Period =TIM_Period;
                TIM_TimeBaseStructure.TIM_Prescaler = 0;                //定时器时钟分频
                TIM_TimeBaseStructure.TIM_ClockDivision = 0;        //采样分频
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //向上计数
                TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
          TIM_PrescalerConfig(TIM2, 13, TIM_PSCReloadMode_Immediate );
          TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
          TIM_Cmd(TIM2, ENABLE);
}

使用特权

评论回复
6
penghuiyanbiyun|  楼主 | 2014-10-17 10:12 | 只看该作者
mmuuss586 发表于 2014-10-16 12:37
刚才乱码现在改了
//对84MHz(TIM3时钟源为168MHz/2)进行TIM_scale分频后作为计数时钟
void        TIM2_Init(u32 ...

//对84MHz(TIM3时钟源为168MHz/2)进行TIM_scale分频后作为计数时钟
void        TIM2_Init(u32 TIM_Period)//TIM_Period为16位的数
请问这里是不是有点问题,那个数据手册上写的是如果APB2的分频不为1的话,那么定时器的时钟就要乘以2,所以TIM3的时钟是不是应该理解为 168MHz/2*2=168M呢??时钟这一块始终没怎么弄明白,麻烦你解释一下可以吗?

另外定时器初始化加了一条TIM_PrescalerConfig(TIM2, 13, TIM_PSCReloadMode_Immediate );也没用,情况还是一样,中断应该只进去了一次,运行程序后灯一直是亮的。。。

使用特权

评论回复
7
penghuiyanbiyun|  楼主 | 2014-10-17 10:22 | 只看该作者
还有,我查看断点情况之后,发现灯就一直不亮了。。。请大神指导!!

使用特权

评论回复
8
LOVE_ELEC| | 2014-10-17 10:24 | 只看该作者
中断函数中没有清除中断标志位,清中断标志位应该用下面这条语句:
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

使用特权

评论回复
9
penghuiyanbiyun|  楼主 | 2014-10-17 10:48 | 只看该作者
LOVE_ELEC 发表于 2014-10-17 10:24
中断函数中没有清除中断标志位,清中断标志位应该用下面这条语句:
TIM_ClearITPendingBit(TIM2, TIM_IT_Up ...

谢谢啊,不过不是这个原因,之前都试过了的,灯还是一直亮的。。不过断点调试之后还是亮的。。。应该是中断出了问题,只进去了一次,点亮了灯。不过实在找不到原因了。。添加的库函数就是GPIO,RCC,TIM的,这应该没错吧?请问你们有调试成功了的程序可以分享一下吗?

使用特权

评论回复
10
LOVE_ELEC| | 2014-10-17 11:20 | 只看该作者
NVIC_InitTypeDef NVIC_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                                                                                                         
        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;          
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;       
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period=1000;                                                                                                                  
        TIM_TimeBaseStructure.TIM_Prescaler= (72 - 1);                                  
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;                   
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;      
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        TIM_ClearFlag(TIM2, TIM_FLAG_Update);                                                  
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
        TIM_Cmd(TIM2, ENABLE);               

        void TIM2_IRQHandler(void)
        {
             if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )
             {       
                TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);  
              }
         }
这个是我用的好用的程序!你参考下!                                                    

使用特权

评论回复
11
penghuiyanbiyun|  楼主 | 2014-10-17 13:18 | 只看该作者
谢谢大家,我之前在IAR中运行的时钟都不能成功,放在KEIL里运行成功了!!所以不是程序的问题。IAR还是太麻烦了。还是谢谢大家!

使用特权

评论回复
12
penghuiyanbiyun|  楼主 | 2014-10-17 13:59 | 只看该作者
mmuuss586 发表于 2014-10-16 12:37
刚才乱码现在改了
//对84MHz(TIM3时钟源为168MHz/2)进行TIM_scale分频后作为计数时钟
void        TIM2_Init(u32 ...

请问你对数据手册里的时钟树了解深吗?我对这块还不是很熟,你能解释一下吗?比如那个HSE分频 APB分频之类的还有定时器的时钟计算方法,到底要不要乘以2?

使用特权

评论回复
13
mmuuss586| | 2014-10-17 17:23 | 只看该作者
penghuiyanbiyun 发表于 2014-10-17 13:59
请问你对数据手册里的时钟树了解深吗?我对这块还不是很熟,你能解释一下吗?比如那个HSE分频 APB分频之 ...

这几个时钟范围有要求的

使用特权

评论回复
14
mmuuss586| | 2014-10-17 17:36 | 只看该作者
penghuiyanbiyun 发表于 2014-10-17 13:59
请问你对数据手册里的时钟树了解深吗?我对这块还不是很熟,你能解释一下吗?比如那个HSE分频 APB分频之 ...

不用乘2,看系统函数,实际上就是对系统时钟分频得到的;
你看407的用户手册,有时钟的图,也没有乘2;
定时器,再在相应的AHB时钟上进行分频,得到你需要的频率;
担心不对,用示波器看下是否一样;

/*首先配置 AHB时钟(HCLK). 为了获得较高的频率,我们对 SYSCLK 1分频,得到HCLK*/

     RCC_HCLKConfig(RCC_HCLK_Div1);

  

     /*APBx时钟(PCLK)由AHB时钟(HCLK)分频得到,下面我们配置 PCLK*/

  

     /*APB1时钟配置. 4分频,即 PCLK1 = 42 MHz*/

     RCC_PCLK1Config(RCC_HCLK_Div4);

  

     /*APB2时钟配置. 2分频,即 PCLK2 = 84 MHz*/

     RCC_PCLK2Config(RCC_HCLK_Div2);

使用特权

评论回复
15
penghuiyanbiyun|  楼主 | 2014-10-21 10:12 | 只看该作者
我现在是用定时器2实现1s的中断,TIM2 是挂在APB1上的,那就是说TIM2的时钟是42M?不用倍频?  可是我设置Prescaler=4200-1,Period = 9999,并不是实现的1s中断,而是过了10多 秒才中断一次,这是什么原因呢?   我利用HSE作为时钟源是不是要在主程序中加上这两条语句 RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);
  RCC_HSEConfig(RCC_HSE_ON);

才能使的HSE有效?

使用特权

评论回复
16
penghuiyanbiyun|  楼主 | 2014-10-21 10:42 | 只看该作者
penghuiyanbiyun 发表于 2014-10-21 10:12
我现在是用定时器2实现1s的中断,TIM2 是挂在APB1上的,那就是说TIM2的时钟是42M?不用倍频?  可是我设置P ...

刚试了一下,定时器2的时钟是42M,但是要把这两条语句删掉 RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);
  RCC_HSEConfig(RCC_HSE_ON);灯才是以1s的频率闪,否则就不是,这是什么原因呢?

使用特权

评论回复
17
shoujuanhappy| | 2014-10-23 11:43 | 只看该作者
mark

使用特权

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

本版积分规则

26

主题

110

帖子

1

粉丝