【问题标题】:Stm32 Time Base Interrupt (without any library)Stm32 时基中断(没有任何库)
【发布时间】:2020-05-17 21:12:35
【问题描述】:

我使用 Stm32f103c8t6 处理器,我想制作 1 秒计数器。 Normaly 我不使用 tımer update ınterrupt 并且我的计数器计数正确,但是当我在代码中添加 timer update ınterrupt 时,我的计数器计数不正确。这么快的增量。而且我无法删除 TIM1 的 SR 寄存器中的更新中断标志 (UIF)。如果我删除此标志,我的代码将进入无限循环。我无法解决这个问题。感谢您的帮助

这部分是引入startup_stm32f10x_md.s

/**
 * @brief  This is the code that gets called when the processor receives an
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 *
 * @param  None
 * @retval : None
*/
    .section    .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
    b   Infinite_Loop -----------------------------> my code is stuck here
    .size   Default_Handler, .-Default_Handler

这是我的代码。

#include <stddef.h>
#include "stm32f10x.h"

void CLK_Config(){
     RCC-> CR = 0x00000000;             //CR Reset
     RCC-> CR |= 0x00010000;            //HSE enable
     while(!(RCC-> CR & 0x00020000));   //HSE FLAG control
     RCC-> CR |= 0x00080000;            //CSS enable
     RCC-> CR |= 0x01000000;            //PLL On
     RCC-> CFGR |= 0x00010000;          //HSE Select PLL input
     RCC-> CFGR |= 0x001C0000;          //PLL Multi With 9 = 72 Mhz
     RCC-> CFGR |= 0x00000002;          //PLL Select as SYSCLK
     RCC-> CFGR |= 0x00000400;          //APB1 Clock divided by 2

     RCC-> APB1ENR |= 0x18000000;       //APB1 BKP Clock Enable
     PWR-> CR |= 0x0100;                //PWR BKP Access Enable

     RCC-> APB2ENR |= 0x00000001;       //APB2 AFIO Clock Enable
}

void TIM1_Config(){
     RCC-> APB2ENR  |= 0x00000800;      //TIM1 CLK Enable
     TIM1-> CR1     |= 0x0085;          //Update Request Source, Counter Enable
     TIM1-> DIER     = 0x0001;          //Update Interrupt Enable
     TIM1-> ARR      = 0x1F40;          //8000 is set as Auto Reload Value
     TIM1-> PSC      = 0x2327;          //9000 is set as Prescaler Value for 1 sn Formula: 1sn=1Hz=(PCLK/(PSC*ARR))
}

void USART1_Config(){
    RCC-> APB2ENR   |= 0x00000004;      //GPIOA CLK Enable
    GPIOA-> CRH     |= 0x00000AA0;      //GPIOA 10,9 Push-Pull Alternate Function 2Mhz
    RCC-> APB2ENR   |= 0x00004000;      //USART1 CLK Enable
    USART1-> BRR    |= 0x00001D4C;      //USART1 Baund Rate 9600
    USART1-> CR1    |= 0x000020C8;      //USART, TXE Interrupt, TC Interrupt, Transmitter Enable
}

void Interrupt_Config(){
    NVIC-> ISER[0]  |= 0x02000000;      //NVIC TIM1 UP
    NVIC-> ISER[1]  |= 0x00000020;      //NVIC USART1 Global Interrupt

    NVIC-> IP[25]   = 0x10;             //TIM1 UP Interrupt Priority 2.         25th Interrupt
    NVIC-> IP[37]   = 0x40;             //USART1 Global Interrupt Priority 5.   37th Interrupt

}

uint8_t count1sec; // Global variable

int main(void)
{
    CLK_Config();
    Interrupt_Config();
    TIM1_Config();
    USART1_Config();

  while (1)
  {
      if(count1sec != 0){
          USART1-> DR = count1sec;
      }
  }

}

void TIM1_UP_IRQHandler(){
    TIM1-> SR = 0x00000000;
    NVIC-> ICPR[0] = 0x02000000;
    count1sec += 1;
}

【问题讨论】:

  • 可能您在启动文件中的处理程序被不同地调用或根本没有定义。幻数 - 另一个问题,我个人不会浪费时间去“解码”它们

标签: c timer stm32 interrupt usart


【解决方案1】:

我无法检测出问题的确切原因,但我可以提供一些建议并做出一些猜测。

1) 不要使用幻数!使用预定义的位名称。这是一个例子:

USART2->BRR = 0x1a0; // 115200 bps @ 24 MHz (OVER8=1, ONEBIT=1)
USART2->CR1 |= USART_CR1_OVER8 // Oversampling is reduced for higher baud rates
            | USART_CR1_IDLEIE // Idle line detection interrupt is enabled
            | USART_CR1_TE // Transmitter is enabled
            | USART_CR1_RE; // Receiver is enabled
USART2->CR3 |= USART_CR3_ONEBIT // One bit mode for increased clock deviation tolerance
            | USART_CR3_DMAT // DMA for TX
            | USART_CR3_DMAR; // DMA for RX
USART2->CR1 |= USART_CR1_UE; // Enable USART2

2) 使用 CMSIS 功能访问 NVIC 功能。这是一个例子:

NVIC_SetPriority(TIM6_DAC_IRQn, 2);
NVIC_EnableIRQ(TIM6_DAC_IRQn);

3) 您在TIM1-&gt;CR1 寄存器中设置了Auto-reload preload enable 位。这通常会延迟ARR 寄存器的更新,直到下一次更新事件。我不确定它在计时器的初始运行期间是如何工作的,但我建议在您确定一切正常之前避免使用它。

4) 通常不需要清除 NVIC 中的待处理位。我建议从 ISR 中删除该代码。清除外设寄存器中的标志就是您所需要的,而且您已经使用TIM1-&gt;SR = 0 行来完成。

5) 卡在Infinite_Loop 的原因可能是USART TX 中断。它被解雇了,但由于您没有为它提供 ISR,它属于Default_Handler。您在主循环中手动加载 DR,因此在这种情况下您甚至不需要 USART TX 中断。

【讨论】:

  • 塔格利感谢您的回复。我将更改我的代码。我的问题出在您的第 4 种方法中。我无法清除 tım1->SR 寄存器!!。而且 Usart tx 中断不会影响我的代码。
  • 我觉得你首先需要找到卡在Infinite_Loop的原因。在调试会话期间,检查故障。默认情况下,如果您不提供自己的故障处理程序,故障也会分支到Default_Handler。如果调试过程中没有故障,那么一定是没有 ISR 的中断。我想不出另一种可能性。
猜你喜欢
  • 2018-01-23
  • 1970-01-01
  • 2019-07-10
  • 2012-02-07
  • 2021-02-28
  • 2012-09-14
  • 2015-02-21
  • 2018-01-09
  • 2021-06-19
相关资源
最近更新 更多