[STM32F4] 定时器无法进入中断

[复制链接]
9013|16
 楼主| penghuiyanbiyun 发表于 2014-10-16 11:38 | 显示全部楼层 |阅读模式
使用的是STM32F407的Discovery板,用的库是官方的库。只是简单的配置定时器2,然后通过定时器中断实现LED的闪烁,结果定时器中断进不去,查看断点执行的时候,中断服务程序中的flag数值的变化也很混乱,不知道什么原因,麻烦大家帮忙看看是不是配置有问题。。。
  1. #include"stm32f4_discovery.h"
  2. #include"stm32f4xx.h"

  3. void led(int n);
  4. void tim_config(void);
  5. int flag=0;
  6. void main()
  7. {
  8.   SystemInit();
  9.   
  10.   GPIO_InitTypeDef GPIO_InitStructure;
  11.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_14;            
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /*端口模式为输出 */
  14.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*输出类型 推挽输出 */
  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  16.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  17.   GPIO_Init(GPIOD, &GPIO_InitStructure);
  18.   tim_config();
  19. }


  20. void tim_config(void)
  21. {
  22.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  23.   NVIC_InitTypeDef NVIC_InitStructure;
  24.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  25.   NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  26.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 0
  27.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    //响应优先级为 0
  28.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //通道中断使能
  29.   NVIC_Init(&NVIC_InitStructure);
  30.   
  31.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  32.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  33.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  34.   TIM_TimeBaseStructure.TIM_Period = 9999;
  35.   TIM_TimeBaseStructure.TIM_Prescaler = 7199;//定时1s

  36.   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
  37.   TIM_ClearFlag(TIM2,TIM_FLAG_Update);   
  38.   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   
  39.   TIM_Cmd(TIM2,ENABLE);
  40.   
  41.   
  42. }

  43. void led(int n)
  44. {
  45.     if(n==0){
  46.       GPIO_SetBits(GPIOD,GPIO_Pin_12);
  47.       GPIO_SetBits(GPIOD,GPIO_Pin_14);
  48.     }
  49.     else if(n==1){
  50.       GPIO_ResetBits(GPIOD,GPIO_Pin_12);
  51.       GPIO_ResetBits(GPIOD,GPIO_Pin_14);  
  52.    
  53.     }
  54. }

  55. void TIM2_IRQHandler(void)
  56. {
  57.   if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  58.   {
  59.     TIM_ClearFlag(TIM2,TIM_FLAG_Update);
  60.     led(flag);
  61.     flag=!flag;
  62.   }
  63. }

  64. void Delay(uint32_t nCount)
  65. {
  66. while (nCount--);
  67. }


  68. #ifdef  USE_FULL_ASSERT

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

  80.   while (1)
  81.   {}
  82. }
  83. #endif

  84. /**
  85.   * @}
  86.   */

  87. /**
  88.   * @}
  89.   */

  90. /******************* (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吗?
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);
}
 楼主| 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 );也没用,情况还是一样,中断应该只进去了一次,运行程序后灯一直是亮的。。。
 楼主| penghuiyanbiyun 发表于 2014-10-17 10:22 | 显示全部楼层
还有,我查看断点情况之后,发现灯就一直不亮了。。。请大神指导!!
LOVE_ELEC 发表于 2014-10-17 10:24 | 显示全部楼层
中断函数中没有清除中断标志位,清中断标志位应该用下面这条语句:
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
 楼主| penghuiyanbiyun 发表于 2014-10-17 10:48 | 显示全部楼层
LOVE_ELEC 发表于 2014-10-17 10:24
中断函数中没有清除中断标志位,清中断标志位应该用下面这条语句:
TIM_ClearITPendingBit(TIM2, TIM_IT_Up ...

谢谢啊,不过不是这个原因,之前都试过了的,灯还是一直亮的。。不过断点调试之后还是亮的。。。应该是中断出了问题,只进去了一次,点亮了灯。不过实在找不到原因了。。添加的库函数就是GPIO,RCC,TIM的,这应该没错吧?请问你们有调试成功了的程序可以分享一下吗?
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);  
              }
         }
这个是我用的好用的程序!你参考下!                                                    
 楼主| penghuiyanbiyun 发表于 2014-10-17 13:18 | 显示全部楼层
谢谢大家,我之前在IAR中运行的时钟都不能成功,放在KEIL里运行成功了!!所以不是程序的问题。IAR还是太麻烦了。还是谢谢大家!
 楼主| 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?
mmuuss586 发表于 2014-10-17 17:23 | 显示全部楼层
penghuiyanbiyun 发表于 2014-10-17 13:59
请问你对数据手册里的时钟树了解深吗?我对这块还不是很熟,你能解释一下吗?比如那个HSE分频 APB分频之 ...

这几个时钟范围有要求的
捕获.JPG
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);
 楼主| 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有效?
 楼主| 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的频率闪,否则就不是,这是什么原因呢?
shoujuanhappy 发表于 2014-10-23 11:43 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

110

帖子

1

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