4

所以我用 C 语言为微控制器编写了一个程序STM32F103C8T6,使用 RTC(实时时钟)和一个显示模块。

RTC 和显示器都工作正常,但是当我尝试从 RTC 中断处理程序内部更新显示器时,它不起作用。

当我从 中向显示器写入内容时main(),它工作得很好。

中断处理程序也可以正常工作,所以我认为问题出在写入显示器的函数中。

此函数使用小的延迟来对与显示控制器的通信进行位爆炸。

我以前使用SysTick来生成这样的延迟:

void delay(uint32_t n){
    uint32_t start =  systick_count;
    while (systick_count - start < n);
    return;
}

但不知何故,在 RTC 的中断处理程序内部它不起作用。所以我用这个替换了我的延迟函数,而不是使用 SysTick:

for (; i>0; i--) {
    for (int j = 0; j < 72; ++j) {
        __asm__ __volatile__("nop\n\t":::"memory");
    }
}

现在一切正常。

我试图理解,为什么SysTick在 RTC 中断处理程序中显然不起作用。

我认为这可能是由中断优先级引起的,但根据数据表,默认情况下SysTick Interrupt' 的优先级高于 RTC 中断优先级。

也许有人可以解释,为什么会这样?

EDIT1:好的,所以我已经阅读了更多关于中断优先级的内容,看来我需要正确配置 NVIC_IRQChannelPreemptionPriority 。我会尽快尝试这个...

关于中断内部的延迟,我知道这不是正确的做法,但我仍然想了解程序的行为

EDIT2:我只是尝试通过以下方式更改中断优先级:

// set RTC interrupt priority to 15 (lowest)
NVIC_SetPriority(RTC_IRQn, 15);
// set interrupt priority of SysTick to 0 (highest)
NVIC_SetPriority(SysTick_IRQn, 0);

现在 SysTick 延迟在 RTC 中断处理程序中起作用。

4

1 回答 1

7

HAL_Delay您使用 SysTick 实现延迟的方式与来自 ST 的 HAL 库中的相同。它的工作方式是 SysTick 不断增加(通常以 1ms 间隔)一个变量 -systick_count在你的情况下 - 与延迟函数内的局部变量进行比较 -start在​​你的情况下。

这里需要注意两点:

  1. systick_count需要将其设置为 volatile 以在每次比较之前强制重新读取其值。它由中断修改,而不是在该函数内部。您的编译器可能会选择优化这部分代码。

  2. 调用延迟函数时,SysTick 中断需要“运行”。如果不是因为您处于较高优先级(数值较低)的中断中,那么您处于死锁状态并且延迟功能将永远不会完成,因为计数器永远不会被 SysTick 递增,而这永远不会发生。关于这一点——不要假设事情,只依赖数据表。继续并实际验证它是否在延迟时运行。要么在调用延迟函数时检查 NVIC 寄存器值,要么在 RTC 中断中简单地在 SysTick 中设置一个断点——它应该在你在延迟函数中时命中该断点。如果没有,您可能需要调整中断优先级。

关于延迟中断的整个想法 - 这通常被认为是不好的做法。中断应该用于非常快速地完成非常小的部分工作,例如设置需要在主程序代码中完成的标志或将接收到的字节放入队列中以供以后处理。虽然这在一个只有一个中断(如果算上 Systick 的话是两个)的简单程序中似乎并不明显,但一旦添加更多中断,它很快就会出现问题,并且会遇到诸如丢失信息等问题,因为您的中断会阻塞每个中断其他,他们没有足够快地被调用。

于 2018-09-14T13:14:00.133 回答