我正在使用stm8l-发现,并且我已经创建了一个代码,用于使用计时器(TIM1)每1秒切换一次led,但这无法正常工作。我的配置中缺少这里的东西

我可以第一次进入中断功能,但此后它不再进入中断功能。有人请调查并帮助我

enter code here
#include <iostm8l.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"

unsigned int count = 0;

@svlreg @interrupt void TIM1(void)
{
count += 1;
TIM1_SR1 &= ~(0x01);
}

main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
CLK_PCKENR2 = 0x02; // clock for timer1
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
PE_DDR = 0x80; // direction output for led
PE_CR1 = 0x80; // fast push pull mode
TIM1_PSCRH = 0x3e; //to create a frequency for 1000 hz
TIM1_PSCRL = 0x80; // so prescalar is 16000
TIM1_CR1 = 0x01;
TIM1_IER = 0x01;
_asm("rim\n");
while(1)
{

    if (count == 1000)
    {
        PE_ODR ^= 0x80;
        count = 0;
    }
}
}


中断仅进入一次,但之后不进入。因此变量“ count”保持为值1

最佳答案

您将魔术数字用作位掩码,而不是定义的常量,因此对于您我来说,代码都很难读。更改它,以使代码最终像例如

TIM1_SR1 &= ~TIM1_SR1_UIF;
由于这是一个8位MCU,因此您必须u为所有整数后缀加上后缀,否则它们将成为带符号的int,这是不必要的。

例如,此代码TIM1_SR1 &= ~(0x01);等效于TIM1_SR1 &= -2。这样很容易编写意外的细微错误。我建议学习Implicit type promotion rules

强烈建议拆解您编写的每个ISR,以查看最终使用的机器代码,并在调试器中一步步观察调试器,同时查看寄存器。这个特定的寄存器似乎忽略了向其写入1的情况,因此您可能只需执行TIM1_SR = TIM1_SR1_UIF;即可。 ISR内部未正确清除的计时器标志是嵌入式系统中最常见的错误之一。
引用手册:


  UIF:更新中断标志
  –如果TIM1_CR1寄存器中的UDIS = 0,则发生上溢或下溢
  –如果使用TIM1_EGR寄存器中的UG位由软件重新初始化CNT,并且TIM1_CR1寄存器中的URS = 0和UDIS = 0。
  –通过触发事件重新初始化CNT(请参考TIM1_SMCR寄存器说明)时,如果TIM1_CR1寄存器中的URS = 0和UDIS = 0


您的代码似乎没有执行任何此操作,因此可以很安全地假定计时器计数器未重置。
另一个问题是必须将count声明为volatile,否则编译器可能会完全优化此代码:

if (count == 1000)
{
    PE_ODR ^= 0x80;
    count = 0;
}

关于c - 我需要知道为什么我的打扰在这里不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58087436/

10-10 16:13