0

我正在使用 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

4

1 回答 1

1
  • 您正在为位掩码使用幻数而不是定义的常量,因此代码对于您和我来说都非常难以阅读。更改它,以便代码最终像例如

    TIM1_SR1 &= ~TIM1_SR1_UIF;

  • 由于这是一个 8 位 MCU,因此您绝对必须为u所有整数内容添加后缀,否则它们将是int您不想要的类型 signed 。

    例如,此代码TIM1_SR1 &= ~(0x01);等效于TIM1_SR1 &= -2. 以这种方式很容易编写意外的细微错误。我建议研究隐式类型提升规则

    强烈建议对您编写的每个 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;
    }
    
于 2019-09-24T21:05:49.507 回答